Help with libc implementation
Posted: Sat Mar 07, 2015 4:31 pm
Hi again
So, I got so far to have a running cross-compiler. I tried compiling an ELF executable that prints a simple "Hello World" string using my libc printf function, which in turn calls the respective syscall to do the writing. It seemingly compiled error-free, so I copied it to my virtual disk and tried running it. The module loads correctly into memory (entry at 0x08048090 as indicated in the file header), all ELF header checks passed, I switch to user mode, and execution starts, but a few instructions down the road, it page faults. I dumpobj'd the executable and traced it. _start goes on and calls init_std_library which currently does nothing (I didn't implement the memory-environ-argc-argv stuff yet), then _init is called. Here _init calls __do_global_ctors_aux, which (as I understand) should traverse a list of global constructors and call them. Okay, the problem is that the list is empty (not *empty*, but contains ffffff followed by 00). The .ctors section shows:
After looking at __do_global_ctors_aux, it looks that it loads the first item in the list, compares it to 0xffffffff (which turns true) and then bails out and returns.
When it returns, execution goes to 0x08048081, the instruction at which tries to access the address saved in %eax (currently0xffffffff) which of course is not mapped to the user process, hence the page fault. Furthermore, i don't know where this address came from, as it is absent from the dump:
I read the Wiki on "Calling global constructors" & "Creating C library" but they doesn't say much about the global constructors. I spent hours googling it (to no avail). I looked into the GNU libc source, but it is too much twisted and full of macros that it is very hard to decipher .
So, I guess my questions are:
[1] How can I define (or for the moment, while running simple programs, skip) the global constructors? In other words, how can I change (or edit) the list of ctors used by the cross compiler when cross compiling my code using my libc?
[2] Is there any specific standard for what items to push on the stack before invoking the executable (I know I need to push a pointer to argv, environmental variables, argc, anything else *essential* for a simple "Hello World" program to run)?
[3] Any good sources on implementing the standard C library? I've read the ISO standard which gave me a good insight but it's rather theoretical, and the crt* stuff is not included in the standard. I am reading "The Standard C Library" by P.J. Plaucer currently. Any other practical sources?
Thanx
So, I got so far to have a running cross-compiler. I tried compiling an ELF executable that prints a simple "Hello World" string using my libc printf function, which in turn calls the respective syscall to do the writing. It seemingly compiled error-free, so I copied it to my virtual disk and tried running it. The module loads correctly into memory (entry at 0x08048090 as indicated in the file header), all ELF header checks passed, I switch to user mode, and execution starts, but a few instructions down the road, it page faults. I dumpobj'd the executable and traced it. _start goes on and calls init_std_library which currently does nothing (I didn't implement the memory-environ-argc-argv stuff yet), then _init is called. Here _init calls __do_global_ctors_aux, which (as I understand) should traverse a list of global constructors and call them. Okay, the problem is that the list is empty (not *empty*, but contains ffffff followed by 00). The .ctors section shows:
Code: Select all
Disassembly of section .ctors:
080493a8 <__CTOR_LIST__>:
80493a8: ff (bad)
80493a9: ff (bad)
80493aa: ff (bad)
80493ab: ff 00 incl (%eax)
080493ac <__CTOR_END__>:
80493ac: 00 00 add %al,(%eax)
...
Code: Select all
080482b0 <__do_global_ctors_aux>:
80482b0: 55 push %ebp
80482b1: 89 e5 mov %esp,%ebp
80482b3: 53 push %ebx
80482b4: bb a8 93 04 08 mov $0x80493a8,%ebx
80482b9: 83 ec 04 sub $0x4,%esp
80482bc: a1 a8 93 04 08 mov 0x80493a8,%eax <<<<< This is the address of the first item in the .ctors list
80482c1: 83 f8 ff cmp $0xffffffff,%eax
80482c4: 74 16 je 80482dc <__do_global_ctors_aux+0x2c>
80482c6: 8d 76 00 lea 0x0(%esi),%esi
80482c9: 8d bc 27 00 00 00 00 lea 0x0(%edi,%eiz,1),%edi
80482d0: 83 eb 04 sub $0x4,%ebx
80482d3: ff d0 call *%eax
80482d5: 8b 03 mov (%ebx),%eax
80482d7: 83 f8 ff cmp $0xffffffff,%eax
80482da: 75 f4 jne 80482d0 <__do_global_ctors_aux+0x20>
80482dc: 83 c4 04 add $0x4,%esp
80482df: 5b pop %ebx <<<<<< bails out
80482e0: 5d pop %ebp
80482e1: c3 ret
Code: Select all
....
804807c: e8 2f 02 00 00 call 80482b0 <__do_global_ctors_aux>
******* NOTHING in between these addresses!!! *******
Disassembly of section .text:
08048090 <_start>:
....
So, I guess my questions are:
[1] How can I define (or for the moment, while running simple programs, skip) the global constructors? In other words, how can I change (or edit) the list of ctors used by the cross compiler when cross compiling my code using my libc?
[2] Is there any specific standard for what items to push on the stack before invoking the executable (I know I need to push a pointer to argv, environmental variables, argc, anything else *essential* for a simple "Hello World" program to run)?
[3] Any good sources on implementing the standard C library? I've read the ISO standard which gave me a good insight but it's rather theoretical, and the crt* stuff is not included in the standard. I am reading "The Standard C Library" by P.J. Plaucer currently. Any other practical sources?
Thanx