Jump to Protected Mode not working after linking the kernel - c++

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.

Related

How to find the proc name for `GetProcAddress` function using WinDbg

I want to use GetProcAddress to get some functions addresses inside a loaded DLL. I run some attempts on PSAPI library and I can see the the expected proc name is not identical to the symbol names I find with WinDbg x statements. For example, I look for "EnumProcessModules"(which is the name expected by GetProcAddress method) with x psapi!*EnumProcessModules* and I find
00007ff9`fe112210 PSAPI!_imp_K32EnumProcessModulesEx = <no type information>
00007ff9`fe111360 PSAPI!EnumProcessModulesExStub (<no parameter info>)
00007ff9`fe111030 PSAPI!EnumProcessModulesStub (<no parameter info>)
00007ff9`fe1121a8 PSAPI!_imp_K32EnumProcessModules = <no type information>
When I provide any of the found symbols above (with or without "PSAPI!" as a prefix) to the GetProcAddress method as the second parameter (procName) - it returns NULL, but when I use the method name "EnumProcessModules" - it returns 0xfe111030, which is the address of "PSAPI!EnumProcessModulesStub".
How could I know the expected procName in advance? What if I have 2 different classes or namespaces with the same method name in one DLL? How can I distinguish between the two method names when I call GetProcAddress?
PSAPI! is just a prefix, it's the DLL name printed by WinDbg. That's used to disambiguate names. A clear example why this is useful: you will have many DllMain's in your process.
The expected name for GetProcAddress is the documented name of the function, as stated on MSDN. Keep in mind that you will need to add either the A or W suffix when MSDN states both versions are available. E.g. you can't call GetProcAddress with "GetDeviceDriverFileName", you need either "GetDeviceDriverFileNameA" or L"GetDeviceDriverFileNameW".
For non-system DLL's, you need the function name from the Export Address Table.
Background: What you see in WinDbg is the name from the .PDB, which as you have discovered can differ from the exported name. There is nothing which enforces a relation between the two. For instance, it's technically possible to have PDB names Foo and Bar, and have them swapped in the Export Address Table. More realistically, Microsoft may internally add an _wrapper_EnumProcessModules at any time, but the documented and exported name will stay EnumProcessModules.
The Core Functionality for this API is implemented in kernel32.dll
and Named K32EnumProcessModules
in paspi.h header this API is ifdeffed based on PSAPI_VERSION
#ifndef PSAPI_VERSION
#if (NTDDI_VERSION >= NTDDI_WIN7)
#define PSAPI_VERSION 2
#else
#define PSAPI_VERSION 1
#endif
#endif
#if (PSAPI_VERSION > 1)
#define EnumProcessModules K32EnumProcessModules
if you GetProcAddress in psapi.dll you get a stub which gets transferred to kernel32.dll
0:001> u PSAPI!EnumProcessModulesStub l 5
PSAPI!EnumProcessModulesStub:
762d1408 8bff mov edi,edi
762d140a 55 push ebp
762d140b 8bec mov ebp,esp
762d140d 5d pop ebp
762d140e eb05 jmp PSAPI!K32EnumProcessModules (762d1415)
0:001> u 762d1415 l1
PSAPI!K32EnumProcessModules:
762d1415 ff2504102d76 jmp dword ptr [PSAPI!_imp__K32EnumProcessModules (762d1004)]
0:001> u poi(762d1004) l1
kernel32!K32EnumProcessModules:
7668cc52 8bff mov edi,edi
you can use dumpbin /exports on the dll to see if there is any correlation
or if there is a name change (see the Stub#16 )
:\>dumpbin /exports c:\windows\System32\psapi.dll | grep -w EnumProcessModules
5 4 00001408 EnumProcessModules = _EnumProcessModulesStub#16
you could also find the same info from the export table of psapi.dll using some thing like below
0:001> .shell -ci "!dh psapi" grep Export
1088 [ 359] address [size] of Export Directory
.shell: Process exited
0:001> dt ole32!_IMAGE_EXPORT_DIRECTORY (psapi + 1088)
+0x000 Characteristics : 0
+0x004 TimeDateStamp : 0x4a5bc026
+0x008 MajorVersion : 0
+0x00a MinorVersion : 0
+0x00c Name : 0x11be
+0x010 Base : 1
+0x014 NumberOfFunctions : 0x1b
+0x018 NumberOfNames : 0x1b
+0x01c AddressOfFunctions : 0x10b0
+0x020 AddressOfNames : 0x111c
+0x024 AddressOfNameOrdinals : 0x1188
0:001> r? $t0 = (int *) ##(psapi + 10b0)
0:001> r? $t1 = (int *) ##(psapi + 111c)
0:001> r? $t2 = (short *) ##(psapi + 1188)
0:001> .printf "%x %ma %y\n" , ##(#$t2[4]) , (##(#$t1[4]) + psapi) , (##(#$t0[4]) + psapi)
4 EnumProcessModules PSAPI!EnumProcessModulesStub (762d1408)

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

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 = .;
}

Windbg conditional break point not working as expected, is my syntax correct?

I was trying to learn how to set conditional break point inside windbg, I've program named ConsoleApplication7 like below:
int main()
{
int r1 = 0;
r1 += 1;
r1 = 3;
return 0;
}
I compile this program with VC. Then in windbg, I setup the "Symbol path" and "Source path", open ConsoleApplication7.exe inside windbg, windbg runs and opens the .cpp file.
Inside windbg I set a conditional break point, I wish the program should when in line "r1=3".
bp consoleapplication7!main "j (poi(r1)>2) ''; 'gc'"
But when I press "g", windbg doesn't say it "Hit breakpoint", but just print out registers information. After running "g" for 3 times, the program terminate, like below:
0:000> bp consoleapplication7!main "j (poi(r1)>2) ''; 'gc'"
*** WARNING: Unable to verify checksum for ConsoleApplication7.exe
0:000> bl
0 e 01251380 0001 (0001) 0:**** ConsoleApplication7!main "j (poi(r1)>2) ''; 'gc'"
0:000> g
eax=00718918 ebx=7efde000 ecx=0071b880 edx=00000001 esi=00000000 edi=00000000
eip=01251380 esp=002afeb4 ebp=002aff00 iopl=0 nv up ei pl nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000202
ConsoleApplication7!main:
01251380 55 push ebp
0:000> g
eax=00000000 ebx=00000000 ecx=00000000 edx=00000000 esi=77c02100 edi=77c020c0
eip=77b1fcd2 esp=002afe18 ebp=002afe34 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
ntdll!NtTerminateProcess+0x12:
77b1fcd2 83c404 add esp,4
0:000> g
^ No runnable debuggees error in 'g'
Other commands like ba, bp works well in the program, just conditional break point doesn't.
Is my conditional statement correct? Why it doesn't work?
I tried the suggestion from Dono's answer, but it shows another problem
0:000> bp ConsoleApplication7!main+0x3e "j (poi(r1) > 2) ''; 'gc'"
0:000> bl
0 e 008e143e 0001 (0001) 0:**** ConsoleApplication7!main+0x3e "j (poi(r1) > 2) ''; 'gc'"
0:000> g
(4458.4840): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000000 ebx=7efde000 ecx=d3392f75 edx=00000001 esi=00000000 edi=00000000
eip=cccccccc esp=0046f82c ebp=cccccccc iopl=0 nv up ei pl nz na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010206
cccccccc ?? ???
Seems this conditional break point leads to an exception?
Thanks!
I also tried Blabb's suggestion, unluckily, it didn't work:
0:000> t "$$>a< c:\\autostep.txt"
Couldn't resolve error at 'r1) == 3 ) { dv } .else { t "$$>a< c:\\autostep.txt" } '
eax=00000001 ebx=7efde000 ecx=00000000 edx=00000001 esi=00000000 edi=001dfcb0
eip=013b13c0 esp=001dfbac ebp=001dfcb0 iopl=0 nv up ei pl nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000202
ConsoleApplication7!f:
013b13c0 55 push ebp
Seems C++ style command didn't work, so I changed it to MASM style
j (poi(r1)==3)''; 't "$$>a< c:\\autostep.txt"'
Save as c:\autostep.txt
Then I restart windbg to reload it.
0:000> t "$$>a< c:\\autostep.txt"
eax=00000000 ebx=00000000 ecx=bc260000 edx=0015dc38 esi=fffffffe edi=00000000
eip=77ba0e15 esp=0042f804 ebp=0042f830 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000244
ntdll!LdrpDoDebuggerBreak+0x2d:
77ba0e15 8975fc mov dword ptr [ebp-4],esi ss:002b:0042f82c=00000000
0:000> g
eax=00000000 ebx=00000000 ecx=00000000 edx=00000000 esi=77c02100 edi=77c020c0
eip=77b1fcd2 esp=0042fb94 ebp=0042fbb0 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
ntdll!NtTerminateProcess+0x12:
77b1fcd2 83c404 add esp,4
This time, it has no syntax issue, when it doesn't break/stop as I expected. Did I miss anything?
Thanks.
First of all you should be aware that your program will be optimized away to just xor eax,eax ; ret
Unless you compile in debug mode and explicitly disable optimizations with /Od switch
( I assume you are using visual monster project in debug mode which takes care of this )
Second you should be aware is that debugger does not know your r1 r2 or whatever unless symbol information is present and event then you should be aware that there are two expression evaluator MASM and C++ and by default windbg uses MASM
? poi(r1) == MASM evaluation
?? r1 == c++ evaluation
other wise debugger understands only the variables that cpu understands like BYTE , WORD , DWORD , QWORD .... etc and addresses
when you set conditional breakpoint like bp xxxxxmodule!yyyyysymbol "condition" conditions are evaluated only on the address specified not further below
so your condition was evaluated only on main
you should step further down and evaluate your condition on each step until you encounter a match
your code compiled and main() disassembled will look like this
0:000> .dml_flow steptest!main .
<No previous node>
STEPTEST!main (013e6aa0):
e:\test\steptest\steptest.cpp
2 013e6aa0 push ebp
2 013e6aa1 mov ebp,esp
2 013e6aa3 push ecx
3 013e6aa4 mov dword ptr [ebp-4],0
4 013e6aab mov eax,dword ptr [ebp-4]
4 013e6aae add eax,1
4 013e6ab1 mov dword ptr [ebp-4],eax
5 013e6ab4 mov dword ptr [ebp-4],3
6 013e6abb xor eax,eax
7 013e6abd mov esp,ebp
7 013e6abf pop ebp
7 013e6ac0 ret
<No next node>
0:000> lsa .
1: int main()
2: {
3: int r1 = 0;
> 4: r1 += 1;
5: r1 = 3;
6: return 0;
7: }
so your condition can be true only on line 6 or in assembly at address 013e6abb xor eax, eax
you set a conditional bp on 013e6aa0 and the condition was evaluated at that address only
you need to find a way to step till 013e6abb
that is you should
step <evaluate> if match stop else repeat step and evaluate until match occurs
to do that put the following line in a file named autostep.txt and save it to c:\
explanation of the script
if the c++ expression r1 equals 3 show the locals else step and reevaluate by running this script again ( so this script will be executed on each instruction sequence until a match is found )
.if ( ##c++(r1) == 3 ) { dv } .else { t "$$>a< c:\\autostep.txt" }
now open the exe in windbg and do
bp xxxxmod!main
g
t "$$>a< c:\\autostep.txt"
windbg will break when r1 is 3
E:\test\STEPTEST>cdb -c "g steptest!main" STEPTEST.exe
0:000> cdb: Reading initial command 'g steptest!main'
STEPTEST!main:
013e6aa0 55 push ebp
0:000> t "$$>a< c:\\autostep.txt"
r1 = 0n3
013e6abb 33c0 xor eax,eax
0:000> ?? r1
int 0n3
0:000> ? poi(r1)
Evaluate expression: 3 = 00000003
0:000> ? &main ; ? &#eip
Evaluate expression: 20867744 = 013e6aa0
Evaluate expression: 20867771 = 013e6abb
0:000>
you can invoke the script in cmd.exe
cat c:\autostep.txt
.if ( ##c++(r1) == 3 ) { dv } .else { t "$$>a< c:\\autostep.txt" }
cdb -c "g steptest!main;$$>a< c:\autostep.txt" STEPTEST.exe
0:000> cdb: Reading initial command 'g steptest!main;$$>a< c:\autostep.txt'
r1 = 0n3
eax=00000001 ebx=7ffd6000 ecx=a4894de4 edx=00000001 esi=00a2dd04 edi=00a2dd08
eip=009d6abb esp=0019f8d0 ebp=0019f8d4 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
STEPTEST!main+0x1b:
009d6abb 33c0 xor eax,eax
0:000>
Your command means: Unconditionally break at the start of the main function. Then, if r1 > 2, do nothing; otherwise, continue.
Note that bp takes an address and breaks on it. Because you have symbols (PDB), you are able to convert the symbol "consoleapplication7!main" into an address. This points to the start of the function, where r1 has not yet even been initialized, so there is no way for it to be > 2, except for random garbage values.
So first you need to break at a more reasonable spot. There are multiple ways to do this. You can "unscramble" the assembly code uf consoleapplication7!main and determine the offset address to break. Something like bp ConsoleApplication7!main+0x35 "j (poi(r1) > 2) ''; 'gc'". This may be a little difficult. An easier method is to specify the line number such as bp `driver.cpp:6` "j (poi(r1) > 2) ''; 'gc'", assuming your main function is in a file called driver.cpp.
Also, you need to careful whether your application was compiled for debug or release mode. In release mode, most of your main function can be optimized away as the value of r1 can be pre-computed at compile time. This will naturally affect the offsets.
And finally, unless you have a habit of using j to mean "if", I would suggest the more modern .if (condition) { commands } .else { commands } syntax. While they do the same thing, the later is much more readable.
See here for further details.

ida pro doesn't show complete disassambled export function?

Please excuse my newbie question but when I tried exporting a function in the header using
__declspec(dllexport) void testfunction(double i);
and declared the function in the .cpp file like this
void testfunction(double i) {
for (int k = 0; k<10; k++) {
double j = 0.1;
}
}
I only see this for the function after disassembling the .exe file using IDA pro:
.text:00401130 ; void __cdecl testfunction(double)
.text:00401130 public ?testfunction##YAXN#Z
.text:00401130 ?testfunction##YAXN#Z proc near ; DATA XREF: .rdata:off_40BE88o
.text:00401130 jmp dword_40C000
.text:00401130 ?testfunction##YAXN#Z endp
Below I have provided the location of dword_40C000
.data:0040C000 ; Section 3. (virtual address 0000C000)
.data:0040C000 ; Virtual size : 000004A0 ( 1184.)
.data:0040C000 ; Section size in file : 00000200 ( 512.)
.data:0040C000 ; Offset to raw data for section: 0000B200
.data:0040C000 ; Flags C0000040: Data Readable Writable
.data:0040C000 ; Alignment : default
.data:0040C000 ; ===========================================================================
.data:0040C000
.data:0040C000 ; Segment type: Pure data
.data:0040C000 ; Segment permissions: Read/Write
.data:0040C000 _data segment para public 'DATA' use32
.data:0040C000 assume cs:_data
.data:0040C000 ;org 40C000h
.data:0040C000 dword_40C000 dd 6000001h ; DATA XREF: testfunction(double)r
.data:0040C004 align 10h
.data:0040C010 db 2
.data:0040C011 db 0
.data:0040C012 db 0
.data:0040C013 db 0
.data:0040C014 db 2
.data:0040C015 db 0
.data:0040C016 db 0
.data:0040C017 db 0
.data:0040C018 dword_40C018 dd 6000003h ; DATA XREF: .text:004011A0r
.data:0040C01C dword_40C01C dd 6000004h ; DATA XREF: .text:004011D0r
.data:0040C020 dword_40C020 dd 6000005h ; DATA XREF: .text:00401200r
...
Shouldn't there be more code since I have a for loop and some other stuff? Where is the actual code?
It seems you're using C++/CLI. I think the 6000001 is the managed method's token, it will be replaced by the address of the JITted code at runtime.
Compile your binary for native x86 to see machine code.

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