GCC (MingW) + LD generate nearly empty executable. Why? - c++

For a specific requirement, I need my binary to fall below 510bytes.
Doing the program in assembler, I get <100 bytes, while adding same code in C++, the resulting code is over 1K. Looking the resulting binary, mostly all ( + 90%) is full of 0x00 characters (Only a few characters at the beginning and end are really populated).
Currently building commands:
gcc -Wall -Os -s -Wl,--stack,32 -nostdinc -nostdinc++ -fno-ident -fno-builtin -I. -c -o cppFile.coff cppFile.cpp
nasm -f elf -o main.elf main.asm
ld -T link.ld -o out.elf main.elf cppFile.coff
objcopy -O binary out.elf out.bin
Size of files generated:
cppFile.coff = 684 bytes
main.elf = 640
out.elf = 2707
out.bin = 1112
When not linking to the cppFile.coff (with only one empty function)
out.elf = 1984
out.bin = 31 (tested and working)
Why GCC or LD add so many nul charactres?
How to remove this empty space?
ENTRY(start)
phys = 0x7c00;
HEAP_SIZE = 0;
SECTIONS
{
.text phys : AT(phys) {
code = .;
*(.text)
*(.rodata)
}
.data : AT(phys + (data - code))
{
data = .;
*(.data)
}
.bss : AT(phys + (bss - code))
{
bss = .;
*(.bss)
}
end = .;
}

Related

static library convert to a shared lib symbols are hidden?

I am trying to link v8's static library to a shared library using the following cmake command
add_library(v8jni SHARED ${THIRDPARTY_LIB_PATH}/shared/v8jni.cpp)
target_link_libraries(v8jni log
-Wl,--whole-archive v8_inspector
v8_base
v8_snapshot
v8_libplatform
v8_libsampler
v8_libbase
-Wl,--no-whole-archive)
libv8jni.so is generated successfully. But it's useless because all the v8 function are marked as local.
nm -C libv8_base.a | grep v8::HandleScope
00000000 T v8::HandleScope::Initialize(v8::Isolate*)
00000000 T v8::HandleScope::CreateHandle(v8::internal::NeverReadOnlySpaceObject*, unsigned int)
00000000 T v8::HandleScope::CreateHandle(v8::internal::Isolate*, unsigned int)
00000000 T v8::HandleScope::NumberOfHandles(v8::Isolate*)
00000000 T v8::HandleScope::HandleScope(v8::Isolate*)
00000000 T v8::HandleScope::HandleScope(v8::Isolate*)
00000000 T v8::HandleScope::~HandleScope()
00000000 T v8::HandleScope::~HandleScope()
00000000 T v8::HandleScope::operator delete[](void*, unsigned int)
00000000 T v8::HandleScope::operator delete(void*, unsigned int)
00000000 T v8::HandleScope::operator new[](unsigned int)
00000000 T v8::HandleScope::operator new(unsigned int)
U v8::HandleScope::CreateHandle(v8::internal::Isolate*, unsigned int)
U v8::HandleScope::HandleScope(v8::Isolate*)
U v8::HandleScope::~HandleScope()
U v8::HandleScope::HandleScope(v8::Isolate*)
U v8::HandleScope::~HandleScope()
whereas nm -C libv8jni.so | gives me the following output.
Please note the symbol type is t not T, means they only be accessed locally.
nm -C libv8jni.so| grep v8::HandleScope
000c0b48 t v8::HandleScope::Initialize(v8::Isolate*)
000c0c32 t v8::HandleScope::CreateHandle(v8::internal::NeverReadOnlySpaceObject*, unsigned int)
000c0c0c t v8::HandleScope::CreateHandle(v8::internal::Isolate*, unsigned int)
000c0c08 t v8::HandleScope::NumberOfHandles(v8::Isolate*)
000c0b3c t v8::HandleScope::HandleScope(v8::Isolate*)
000c0b3c t v8::HandleScope::HandleScope(v8::Isolate*)
000c4ad4 t v8::HandleScope::~HandleScope()
000c4ad4 t v8::HandleScope::~HandleScope()
000c0c02 t v8::HandleScope::operator delete[](void*, unsigned int)
000c0bfc t v8::HandleScope::operator delete(void*, unsigned int)
000c0bf6 t v8::HandleScope::operator new[](unsigned int)
000c0bf0 t v8::HandleScope::operator new(unsigned int)
v8jni.cpp is very simple
#include <jni.h>
#include <android/log.h>
#include <assert.h>
static const char* LOG_TAG = "v8jni";
extern "C" jint JNI_OnLoad(JavaVM *vm, void *reserved)
{
JNIEnv* env = NULL;
jint result = -1;
__android_log_print(ANDROID_LOG_INFO, LOG_TAG, "JNI_OnLoad");
if (vm->GetEnv((void **) &env, JNI_VERSION_1_4) != JNI_OK) {
__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "GetEnv Failed!");
return result;
}
assert(env != nullptr && "env is nullptr");
return JNI_VERSION_1_4;
}
The link command as follows, it's a test script.
+ rm ../../../.././build/intermediates/cmake/debug/obj/armeabi-v7a/libv8jni.so
+ /Users/leoliu/Library/Android/sdk/ndk-bundle/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ -v --target=armv7-none-linux-androideabi --gcc-toolchain=/Users/leoliu/Library/Android/sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64 --sysroot=/Users/leoliu/Library/Android/sdk/ndk-bundle/sysroot -fPIC -isystem /Users/leoliu/Library/Android/sdk/ndk-bundle/sysroot/usr/include/arm-linux-androideabi -D__ANDROID_API__=15 -g -DANDROID -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -std=c++11 --sysroot /Users/leoliu/Library/Android/sdk/ndk-bundle/platforms/android-15/arch-arm -L/Users/leoliu/Library/Android/sdk/ndk-bundle/sources/cxx-stl/llvm-libc++/libs/armeabi-v7a -shared -Wl,-soname,libv8jni.so -o ../../../../build/intermediates/cmake/debug/obj/armeabi-v7a/libv8jni.so CMakeFiles/v8jni.dir/src/main/cpp/thirdparty/shared/v8jni.cpp.o -llog -Wl,--whole-archive ../../../../src/main/cpp/thirdparty/library/static/armeabi-v7a/libv8_inspector.a ../../../../src/main/cpp/thirdparty/library/static/armeabi-v7a/libv8_base.a ../../../../src/main/cpp/thirdparty/library/static/armeabi-v7a/libv8_snapshot.a ../../../../src/main/cpp/thirdparty/library/static/armeabi-v7a/libv8_libplatform.a ../../../../src/main/cpp/thirdparty/library/static/armeabi-v7a/libv8_libsampler.a ../../../../src/main/cpp/thirdparty/library/static/armeabi-v7a/libv8_libbase.a -Wl,--no-whole-archive -latomic -lm /Users/leoliu/Library/Android/sdk/ndk-bundle/sources/cxx-stl/llvm-libc++/libs/armeabi-v7a/libc++.a
Android clang version 5.0.300080 (based on LLVM 5.0.300080)
Target: armv7-none-linux-android
Thread model: posix
InstalledDir: /Users/leoliu/Library/Android/sdk/ndk-bundle/toolchains/llvm/prebuilt/darwin-x86_64/bin
Found candidate GCC installation: /Users/leoliu/Library/Android/sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/lib/gcc/arm-linux-androideabi/4.9.x
Selected GCC installation: /Users/leoliu/Library/Android/sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/lib/gcc/arm-linux-androideabi/4.9.x
Candidate multilib: thumb;#thumb
Candidate multilib: armv7-a;#armv7
Candidate multilib: armv7-a/thumb;#armv7#thumb
Candidate multilib: .;
Selected multilib: armv7-a;#armv7
"/Users/leoliu/Library/Android/sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/lib/gcc/arm-linux-androideabi/4.9.x/../../../../arm-linux-androideabi/bin/ld" --sysroot=/Users/leoliu/Library/Android/sdk/ndk-bundle/platforms/android-15/arch-arm -X --eh-frame-hdr -m armelf_linux_eabi -shared -o ../../../../build/intermediates/cmake/debug/obj/armeabi-v7a/libv8jni.so /Users/leoliu/Library/Android/sdk/ndk-bundle/platforms/android-15/arch-arm/usr/lib/../lib/crtbegin_so.o -L/Users/leoliu/Library/Android/sdk/ndk-bundle/sources/cxx-stl/llvm-libc++/libs/armeabi-v7a -L/Users/leoliu/Library/Android/android-ndk-r16b/toolchains/llvm/prebuilt/darwin-x86_64/lib64/clang/5.0.300080/lib/linux/arm -L/Users/leoliu/Library/Android/sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/lib/gcc/arm-linux-androideabi/4.9.x/armv7-a -L/Users/leoliu/Library/Android/sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/lib/gcc/arm-linux-androideabi/4.9.x/../../../../arm-linux-androideabi/lib/../lib/armv7-a -L/Users/leoliu/Library/Android/sdk/ndk-bundle/platforms/android-15/arch-arm/usr/lib/../lib -L/Users/leoliu/Library/Android/sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/lib/gcc/arm-linux-androideabi/4.9.x/../../../../arm-linux-androideabi/lib/armv7-a -L/Users/leoliu/Library/Android/sdk/ndk-bundle/platforms/android-15/arch-arm/usr/lib -soname libv8jni.so CMakeFiles/v8jni.dir/src/main/cpp/thirdparty/shared/v8jni.cpp.o -llog --whole-archive ../../../../src/main/cpp/thirdparty/library/static/armeabi-v7a/libv8_inspector.a ../../../../src/main/cpp/thirdparty/library/static/armeabi-v7a/libv8_base.a ../../../../src/main/cpp/thirdparty/library/static/armeabi-v7a/libv8_snapshot.a ../../../../src/main/cpp/thirdparty/library/static/armeabi-v7a/libv8_libplatform.a ../../../../src/main/cpp/thirdparty/library/static/armeabi-v7a/libv8_libsampler.a ../../../../src/main/cpp/thirdparty/library/static/armeabi-v7a/libv8_libbase.a --no-whole-archive -latomic -lm /Users/leoliu/Library/Android/sdk/ndk-bundle/sources/cxx-stl/llvm-libc++/libs/armeabi-v7a/libc++.a -lstdc++ -lm -lgcc -ldl -lc -lgcc -ldl /Users/leoliu/Library/Android/sdk/ndk-bundle/platforms/android-15/arch-arm/usr/lib/../lib/crtend_so.o
+ nm -C ../../../.././build/intermediates/cmake/debug/obj/armeabi-v7a/libv8jni.so
+ grep v8::HandleScope
000c0b48 t v8::HandleScope::Initialize(v8::Isolate*)
000c0c32 t v8::HandleScope::CreateHandle(v8::internal::NeverReadOnlySpaceObject*, unsigned int)
000c0c0c t v8::HandleScope::CreateHandle(v8::internal::Isolate*, unsigned int)
000c0c08 t v8::HandleScope::NumberOfHandles(v8::Isolate*)
000c0b3c t v8::HandleScope::HandleScope(v8::Isolate*)
000c0b3c t v8::HandleScope::HandleScope(v8::Isolate*)
000c4ad4 t v8::HandleScope::~HandleScope()
000c4ad4 t v8::HandleScope::~HandleScope()
000c0c02 t v8::HandleScope::operator delete[](void*, unsigned int)
000c0bfc t v8::HandleScope::operator delete(void*, unsigned int)
000c0bf6 t v8::HandleScope::operator new[](unsigned int)
000c0bf0 t v8::HandleScope::operator new(unsigned int)
Any possible reason causing the problem? Thanks in advance.
I might know the answer, I suspect the root cause is the .hidden in the object file
cpu-arm.o: file format elf32-littlearm
SYMBOL TABLE:
00000000 l df *ABS* 00000000 cpu-arm.cc
00000000 l d .text._ZN2v88internal11CpuFeatures11FlushICacheEPvj 00000000 .text._ZN2v88internal11CpuFeatures11FlushICacheEPvj
00000000 g F .text._ZN2v88internal11CpuFeatures11FlushICacheEPvj 00000010 .hidden _ZN2v88internal11CpuFeatures11FlushICacheEPvj
00000000 *UND* 00000000 __aeabi_unwind_cpp_pr0
The nm's output is a miss leading.
What does ".hidden" mean in the output of output objdump -t?
For anyone encounters the problem, there is a switch in v8's build script
v8/gni/v8.gni
if ((is_posix || is_fuchsia) && (v8_enable_backtrace || v8_monolithic)) {
v8_remove_configs += [ "//build/config/gcc:symbol_visibility_hidden" ]
v8_add_configs += [ "//build/config/gcc:symbol_visibility_default" ]
}
so we need set v8_enable_backtrace=true when compiling v8, problem resolved.

Undefined reference within static library, although the function is there

I try to compile QDP++ C++ library using the Intel 17 compiler and Intel MPI on an Intel Xeon supercomputer. The dependency QMP C library has already been compiled with that compiler (mpiicc), there were no compilation errors.
When trying to configure QDP++, I get this error from the Intel compiler:
~/local-jureca/lib/libqmp.a(QMP_init.o): In function `QMP_comm_get_allocated':
QMP_init.c:(.text+0x55): undefined reference to `QMP_abort_mpi(int)'
And this from GCC 5.4:
~/local-jureca/lib/libqmp.a(QMP_init.o):QMP_init.c:function QMP_comm_get_allocated: error: undefined reference to 'QMP_abort_mpi(int)'
So it is an actual problem and not just something that the Intel C++ with MPI compiler cannot do.
The output of nm ~/local-jureca/lib/libqmp.a contains this stanza where QMP_comm_get_allocated resides in.
QMP_init.o:
U atol
U __ctype_b_loc
U exit
U __gcc_personality_v0
U __gxx_personality_v0
U malloc
00000000000015f0 T QMP_abort
00000000000015c0 T QMP_abort_string
0000000000000010 D QMP_allocated_comm
0000000000000018 d QMP_allocated_comm_s
0000000000000000 D QMP_args
0000000000000000 b QMP_args_s
U QMP_barrier
U QMP_comm_declare_logical_topology_map
0000000000000000 T QMP_comm_get_allocated
0000000000001760 T QMP_comm_get_default
00000000000000e0 T QMP_comm_get_job
U QMP_comm_get_logical_coordinates
U QMP_comm_logical_topology_is_declared
0000000000000070 T QMP_comm_set_allocated
00000000000016f0 T QMP_comm_set_default
0000000000000150 T QMP_comm_set_job
U QMP_comm_split
0000000000000048 D QMP_default_comm
U QMP_error
00000000000001c0 T QMP_finalize_msg_passing
U QMP_get_allocated_dimensions
U QMP_get_allocated_number_of_dimensions
U QMP_get_msg_passing_type
0000000000001620 T QMP_init_msg_passing
0000000000000040 D QMP_job_comm
0000000000000008 D QMP_machine
0000000000000048 b QMP_machine_s
0000000000000080 B QMP_stack_level
U __svml_idiv4
0000000000000000 r __$U0
0000000000000017 r __$U1
000000000000002e r __$U2
000000000000003f r __$U3
0000000000000091 r __$U4
000000000000007c r __$U5
0000000000000050 r __$U6
000000000000005a r __$U7
0000000000000067 r __$U8
U _Unwind_Resume
0000000000000500 t _Z12process_argsPiPPPc
000000000000002c r _Z12process_argsPiPPPc$$LSDA
U _Z13QMP_abort_mpii
U _Z20QMP_init_machine_mpiPiPPPc16QMP_thread_levelPS3_
U _Z28QMP_finalize_msg_passing_mpiv
00000000000001e0 t _Z9get_colorv
0000000000000000 r _Z9get_colorv$$LSDA
Another stanza contains the function QMP_abort_mpi which supposedly cannot be found:
QMP_init_mpi.o:
U malloc
U MPI_Abort
U MPI_Comm_dup
U MPI_Comm_rank
U MPI_Comm_size
U MPI_Finalize
U MPI_Get_processor_name
U MPI_Init_thread
0000000000000010 T QMP_abort_mpi
U QMP_abort_string
U QMP_allocated_comm
0000000000000000 T QMP_finalize_msg_passing_mpi
0000000000000020 T QMP_init_machine_mpi
U QMP_machine
The relevant output of `configure is:
configure: Parscalar build! Checking for QMP
checking for qmp-config... ~/local-jureca/bin/qmp-config
configure: Found QMP configuration program ~/local-jureca/bin/qmp-config
configure: QMP compile flags: -I~/local-jureca/include
configure: QMP linking flags: -L~/local-jureca/lib
configure: QMP libraries flags: -lqmp
checking if we can compile/link of a simple QMP C++ program... no
configure: error: Cannot compile/link a basic QMP C++ program!
Check QMP_CFLAGS, QMP_LDFLAGS, QMP_LIBS.
So it seems to find the library just fine.
In the config.log a little larger chunk is this:
configure:4227: /usr/local/software/jureca/Stages/2016b/software/impi/2017.0.098-iccifort-2017.0.098-GCC-5.4.0/bin64/mpiicpc -o conftest -O2 -Wall -fopenmp --std=c++11 -I~/local-jureca/include -L~/local-jureca/lib conftest.cpp -lqmp >&5
~/local-jureca/lib/libqmp.a(QMP_init.o): In function `QMP_comm_get_allocated':
QMP_init.c:(.text+0x55): undefined reference to `QMP_abort_mpi(int)'
~/local-jureca/lib/libqmp.a(QMP_init.o): In function `QMP_comm_set_allocated':
QMP_init.c:(.text+0xc7): undefined reference to `QMP_abort_mpi(int)'
~/local-jureca/lib/libqmp.a(QMP_init.o): In function `QMP_comm_get_job':
QMP_init.c:(.text+0x135): undefined reference to `QMP_abort_mpi(int)'
~/local-jureca/lib/libqmp.a(QMP_init.o): In function `QMP_comm_set_job':
QMP_init.c:(.text+0x1a7): undefined reference to `QMP_abort_mpi(int)'
~/local-jureca/lib/libqmp.a(QMP_init.o): In function `QMP_finalize_msg_passing':
QMP_init.c:(.text+0x1cf): undefined reference to `QMP_finalize_msg_passing_mpi()'
~/local-jureca/lib/libqmp.a(QMP_init.o): In function `get_color()':
QMP_init.c:(.text+0x29b): undefined reference to `QMP_abort_mpi(int)'
QMP_init.c:(.text+0x45c): undefined reference to `QMP_abort_mpi(int)'
QMP_init.c:(.text+0x4be): undefined reference to `QMP_abort_mpi(int)'
configure:4227: $? = 1
configure: failed program was:
| /* confdefs.h */
| #define PACKAGE_NAME "qdp++"
| #define PACKAGE_TARNAME "qdp--"
| #define PACKAGE_VERSION "1.44.0"
| #define PACKAGE_STRING "qdp++ 1.44.0"
| #define PACKAGE_BUGREPORT "edwards#jlab.org"
| #define PACKAGE_URL ""
| #define PACKAGE "qdp--"
| #define VERSION "1.44.0"
| #define QDP_ND 4
| #define QDP_NC 3
| #define QDP_NS 4
| #define QDP_AC_ALIGNMENT_SIZE 16
| #define QDP_USE_GENERIC_OPTS 1
| #define QDP_USE_BLUEGENEL 1
| #define BASE_PRECISION 64
| #define QDP_USE_CB2_LAYOUT 1
| #define ARCH_PARSCALAR 1
| /* end confdefs.h. */
| #include "qmp.h"
| int
| main ()
| {
|
| int argc ; char **argv ;
| QMP_thread_level_t prv;
| ;
| QMP_init_msg_passing(&argc, &argv, QMP_THREAD_SINGLE, &prv) ;
| ;
| QMP_finalize_msg_passing() ;
|
| ;
| return 0;
| }
configure:4253: checking if we can compile/link of a simple QMP C++ program
configure:4261: result: no
configure:4263: error: Cannot compile/link a basic QMP C++ program!
Check QMP_CFLAGS, QMP_LDFLAGS, QMP_LIBS.
I have replaced the absolute path to my home directory with ~ because the actual path is not interesting.
What happens here? And how can I go about fixing it?
Update 1
This is part of the make output for QMP. It seems to be compiled with mpiicc which is a C (not C++) compiler:
depbase=`echo mpi/QMP_topology_mpi.o | sed 's|[^/]*$|.deps/&|;s|\.o$||'`;\
/usr/local/software/jureca/Stages/2016b/software/impi/2017.0.098-iccifort-2017.0.098-GCC-5.4.0/bin64/mpiicc -DHAVE_CONFIG_H -I. -I../include -I../include -O2 -Wall -fopenmp -MT mpi/QMP_topology_mpi.o -MD -MP -MF $depbase.Tpo -c -o mpi/QMP_topology_mpi.o mpi/QMP_topology_mpi.c &&\
mv -f $depbase.Tpo $depbase.Po
And then the static library is linked together from the various units:
rm -f libqmp.a
ar cru libqmp.a QMP_comm.o QMP_error.o QMP_grid.o QMP_init.o QMP_machine.o QMP_mem.o QMP_split.o QMP_topology.o QMP_util.o mpi/QMP_comm_mpi.o mpi/QMP_error_mpi.o mpi/QMP_init_mpi.o mpi/QMP_mem_mpi.o mpi/QMP_split_mpi.o mpi/QMP_topology_mpi.o

Jump to Protected Mode not working after linking the kernel

I have been developing a Bootloader and have run into a problem when linking c++ code to my assembly stage2 code before I linked the files the second stage would jump to protected mode then to long mode without any problems but now after I have linked it there seems to be a problem when jumping to protected mode Here is the code I use to jump to protected mode:
main:
;first stage of bootloader is loaded at the address 0x07c0:0
;second stage of bootloader is loaded at address 0x200:0x0
cli
xor ax, ax ; All segments set to 0, flat memory model
mov ds, ax
mov es, ax
mov gs, ax
mov fs, ax
mov ss, ax
;
; Set stack top SS:0xffff
;
mov sp, 0x0FFFF
;
mov [CDDriveNumber], dl
SwitchToProtectedMode:
lgdt [GDT_32];load the gdt
call EnableA20
mov eax, cr0
or eax, 1
mov cr0, eax
; Flush CS and set code selector
;
jmp 0x8:Protected_Mode
[BITS 32];Declare 32 bits
Protected_Mode:
Here is the GDT:
GDT_START:
;null descriptor
dd 0
dd 0
;data descriptor
dw 0xFFFF
dw 0
db 0
db 10011010b
db 11001111b
db 0
;code descriptor
dw 0xFFFF
dw 0
db 0
db 10010010b
db 11001111b
db 0
GDT_END:
align 4
GDT_32:
dw GDT_END - GDT_START - 1
dd GDT_START
Here is the linker script I use to link my c and assembly code
KernAddr = 0x200;
ENTRY(_Start)
SECTIONS
{
. = KernAddr;
.text : AT(ADDR(.text) - KernAddr)
{
_code = .;
*(.text)
*(.rodata*)
. = ALIGN(4096);
}
.data : AT(ADDR(.data) - KernAddr)
{
_data = .;
*(.data)
. = ALIGN(4096);
}
.eh_frame : AT(ADDR(.eh_frame) - KernAddr)
{
_ehframe = .;
*(.eh_frame)
. = ALIGN(4096);
}
.bss : AT(ADDR(.bss) - KernAddr)
{
_bss = .;
*(.bss)
/*
* You usually need to include generated COMMON symbols
* under kernel BSS section or use gcc's -fno-common
*/
*(COMMON)
. = ALIGN(4096);
}
_end = .;
/DISCARD/ :
{
*(.comment)
}
}
Here is the batch program I made to build everything:
nasm Stage1.asm -o Stage1.bin
nasm -f elf64 Stage2.asm -o Stage2.o
x86_64-elf-g++ -ffreestanding -mcmodel=large -mno-red-zone -mno-mmx -mno-sse -mno-sse2 -mno-sse3 -mno-3dnow -c -o kernel.o kernel.cpp
x86_64-elf-ld -T linkerscript.ld -o Anmu.bin Stage2.o kernel.o -nostdlib
copy Stage1.bin Root
copy Anmu.bin Root
mkisofs -b Stage1.bin -no-emul-boot -boot-info-table -o BootLoader.iso ./Root
The rest of the code is available here: https://github.com/AnonymousUser1337/Anmu
You say that Stage2 is loaded at segment 0x0200, which is address 0x2000, but your linker says it starts at offset 0x0200.
Also, despite naming your output "Anmu.bin", your file is actually still an ELF executable, which means all of the headers and whatnot are still present in the file. Instead, you need to use objcopy to strip all of the headers and debugging symbols, giving you a flat binary:
objcopy -S -O binary Anmu.bin Anmu-flat.bin
Now, "Anmu-flat.bin" is nothing but code and data, and the first byte of the file is the start of the first instruction.

Values of numbers being lost (changed) when called in subroutine

I have written two .f90 text files prog1.f90:
PROGRAM prog1
READ (5,*) A,B,C
PRINT*, "A = ",A
PRINT*, "B = ",B
PRINT*, "C = ",C
CALL test(A,B,C)
END PROGRAM prog1
and aux.f90
SUBROUTINE test(E,F,G)
real(kind=8) :: E,F,G
PRINT*,"E = ",E
PRINT*,"F = ",F
PRINT*,"G = ",G
END SUBROUTINE test
Which are compiled using the Makefile:
FC = gfortran
FCFLAGS = -g -fbounds-check
FCFLAGS = -O2
FCFLAGS += -I/usr/include
PROGRAMS = prog1
all: $(PROGRAMS)
prog1: aux.o
%: %.o
$(FC) $(FCFLAGS) -o $# $^ $(LDFLAGS)
%.o: %.f90
$(FC) $(FCFLAGS) -c $<
%.o: %.F90
$(FC) $(FCFLAGS) -c $<
.PHONY: clean veryclean
clean:
rm -f *.o *.mod *.MOD
veryclean: clean
rm -f *~ $(PROGRAMS)
I use this makefile to compile prog1 and then run prog1 with the input file input.inp:
0.0033943878 0.0018085515 0.0011798956
I expect the output of this code to be
A = 0.339439E-02
B = 0.180855E-02
C = 0.117990E-02
E = 0.339439E-02
F = 0.180855E-02
G = 0.117990E-02
However it is:
A = 0.339439E-02
B = 0.180855E-02
C = 0.117990E-02
E = 0.100765847236215E-21
F = 0.750936901926887E-24
G = 0.261410786221168-313
The number are much much smaller in the subroutine and seem to have no logical connection to the original A,B and C and are returned from the subroutine as such.
I take it my error is to do with the type I am storing these numbers as, i.e. they are not read in as real(kind=8) but are being converted into this type causing the error but I am not sure what the type should be in the subroutine or if this is even the cause. I may just be missing something obvious.
Any help would be appreciated and please tell me if I need to clarify anything I have written.
Thank you for your time.
James
You made the common error to forget the IMPLICIT NONE statement at the beginning of your program. (At least, it is heavily recommended to avoid this kind of error.)
As a result, all variables starting with I, J, K, L, M or N are of type INTEGER(4) and all other variables of type REAL(4). This means, that your variables A, B and C are of REAL(4). Passing them to the subroutine results in principle in an undetected type mismatch which results in misinterpreted values.
You should always place IMPLICIT NONE at the beginning of your programs and modules to be forced to specify explicit types for your variables!
I think I have fixed this error by correcting prog1.f90:
PROGRAM prog1
real(kind=8) :: A,B,C
READ (5,*) A,B,C
PRINT*, "A = ",A
PRINT*, "B = ",B
PRINT*, "C = ",C
CALL test(A,B,C)
END PROGRAM prog1

Android NDK: Call to System.loadLibrary Results in SIGSEGV Code=1

I have a massive C/C++ library that I'm trying to use through JNI for an Android project. It's comprised of several classes that were originally written for MFC and we've ported them over for execution on the Android environment.
The library builds fine (at least according to ndk-build). The size of the library is 56 MB in size.
When I call System.loadLibrary, the application terminates with the following being logged:
Fatal Signal 11 (SIGSEGV) at 0x00000004 (Code = 1), thread 16123
I performed an objdump on my library and there is nothing at 0004. Here's the first few lines of the dump :
DYNAMIC SYMBOL TABLE:
00000000 DF *UND* 00000000 __cxa_finalize
002fe600 g D .bss 00000000 __dso_handle
002f1e9c g D .init_array 00000000 __INIT_ARRAY__
002f20a4 g D .fini_array 00000000 __FINI_ARRAY__
0011dc58 g DF .text 000000ec WideToJava
00000000 DF *UND* 00000000 __android_log_print
0021f460 g DF .text 00000030 wcslen
00000000 DF *UND* 00000000 malloc
00000000 DF *UND* 00000000 free
0011dd44 g DF .text 000000e4 WideToJava2
0011de28 g DF .text 0000004e JavaToWSZ
0027443c g DF .text 0000001c _Znaj
0011dec4 w DF .text 00000018
I then performed a readelf to see if there is another library that needs to be loaded, listed here :
Dynamic section at offset 0x2d99e0 contains 28 entries:
Tag Type Name/Value
0x00000003 (PLTGOT) 0x2fe464
0x00000002 (PLTRELSZ) 776 (bytes)
0x00000017 (JMPREL) 0x11d4a0
0x00000014 (PLTREL) REL
0x00000011 (REL) 0x107770
0x00000012 (RELSZ) 89392 (bytes)
0x00000013 (RELENT) 8 (bytes)
0x6ffffffa (RELCOUNT) 11169
0x00000006 (SYMTAB) 0x128
0x0000000b (SYMENT) 16 (bytes)
0x00000005 (STRTAB) 0x31cd8
0x0000000a (STRSZ) 791389 (bytes)
0x00000004 (HASH) 0xf3038
0x00000001 (NEEDED) Shared library: [liblog.so]
0x00000001 (NEEDED) Shared library: [libandroid.so]
0x00000001 (NEEDED) Shared library: [libstdc++.so]
0x00000001 (NEEDED) Shared library: [libm.so]
0x00000001 (NEEDED) Shared library: [libc.so]
0x00000001 (NEEDED) Shared library: [libdl.so]
0x0000000e (SONAME) Library soname: [libCSEntry.so]
0x00000019 (INIT_ARRAY) 0x2f1e9c
0x0000001b (INIT_ARRAYSZ) 520 (bytes)
0x0000001a (FINI_ARRAY) 0x2f20a4
0x0000001c (FINI_ARRAYSZ) 12 (bytes)
0x00000016 (TEXTREL) 0x0
0x00000010 (SYMBOLIC) 0x0
0x0000001e (FLAGS) SYMBOLIC TEXTREL
0x00000000 (NULL) 0x0
Then I added those libraries before my call to loadLibrary :
public class ApplicationInterface
{
static
{
System.loadLibrary("log");
System.loadLibrary("android");
System.loadLibrary("stdc++");
System.loadLibrary("m");
System.loadLibrary("c");
System.loadLibrary("dl");
// when i call load library it blows up
System.loadLibrary("CSEntry");
}
// code
}
What's stranger is that there is a specific class that blows up this code. When I commented out the constructor to this class the library loads fine. I've verified that the constructor exists in the resulting library using objdump. I then proceeded to comment out the code in the constructor and it fails as well. Here's the offending code in the C++:
// Code
m_pPifFile = new CNPifFile(sPifFilePath);
m_pPifFile->SetAppType(ENTRY_TYPE);
m_pPifFile->SetAppFName(sApplicationFilename);
m_pPifFile->SetBinaryLoad(true);
// load the PIF file
if(m_pPifFile->LoadPifFile())
{
// PIF file loaded create a new Run App
// the offending line
m_pRunAplEntry = new CRunAplEntry(m_pPifFile);
// Code
RunAplEntry.h
class AFX_EXT_CLASS CRunAplEntry : public CRunApl
{
public:
CRunAplEntry(CNPifFile* pPifFile);
~CRunAplEntry();
// code
};
RunApl.h
class CLASS_DECL_ZBRIDGEO CRunApl : public CObject
{
public:
CRunApl();
virtual ~CRunApl();
// code
};
AFX_EXT_CLASS and CLASS_DECL_ZBRIDGEO are #defined to empty space.
We wrote a CObject equivalient for the Android NDK.
Here are the makefiles :
Application.mk
# set the platform to the latest processor type
APP_ABI := armeabi-v7a
# build for GNU STL
APP_STL := gnustl_static
# turn on exceptions and runtime type info
APP_CPPFLAGS += -fexceptions -frtti
Android.mk
LOCAL_LDLIBS := -llog -landroid $(BOOST_LIBS) -lgnustl_static
LOCAL_LDFLAGS := -L$(BOOST_PATH)/lib/arm
LOCAL_CFLAGS := -D__GLIBC__=1
LOCAL_CFLAGS += -D_GLIBCXX_USE_C99_MATH=1
LOCAL_CFLAGS += -DUNICODE=1
LOCAL_CFLAGS += -D_UNICODE=1
LOCAL_CFLAGS += -DGENERATE_BINARY=1
LOCAL_CFLAGS += -DUSE_BINARY=1
LOCAL_CFLAGS += -DPORTABLE=1
LOCAL_CFLAGS += -fpermissive
LOCAL_CFLAGS += $(CSPROMOBILE_INCLUDE)
LOCAL_STATIC_LIBRARIES := Engine zTbdO zFormO zDictO zToolsO zUtilO zCommonO
I've noticed that the GCC compiler doesn't handle virtual functions very well and I suspect this could be the problem, but I'm not sure. Here are the details for my environment.
NDK: Crystax r75
ABI Target: 4.6.3
ADT: v21.0.1-543035
Debug Device: Nexus 7
Any help will be greatly appreciated.
If you have any additional info please don't hesitate to ask.
Thanks,
Will