Re: Executable entry point
Re: Executable entry point
- Subject: Re: Executable entry point
- From: Terry Lambert <email@hidden>
- Date: Tue, 20 Mar 2007 07:10:09 -0700
On Mar 20, 2007, at 4:13 AM, Filipe Cabecinhas wrote:
On 20 Mar, 2007, at 10:07, Quinn wrote:
Can you (Filipe) post the output from otool -l?
Here it is:
godel:~/dev/compiladores/tests filcab$ otool -l hello
hello:
[ ... ]
Load command 8
cmd LC_UNIXTHREAD
cmdsize 80
flavor i386_THREAD_STATE
count i386_THREAD_STATE_COUNT
eax 0x00000000 ebx 0x00000000 ecx 0x00000000 edx
0x00000000
edi 0x00000000 esi 0x00000000 ebp 0x00000000 esp
0x00000000
ss 0x0000001f eflags 0x00000000 eip 0x00002492 cs
0x00000017
ds 0x0000001f es 0x0000001f fs 0x00000000 gs
0x00000000
godel:~/dev/compiladores/tests filcab$
You should probably go to <http://developer.apple.com> and do a text
search for "Mac OS X ABI Mach-O File Format Reference"; that said,
knowing the object file format is not going to really be enough,
without reading the rest of the ABI documentation.
For example, there are several obvious problems with the binary you
posted.
Your thread state is corrupt; you should only set the eip; everything
else should be zeroed.
You are missing a LC_LOAD_DYLINKER section; the way the binary grading
works, you need the right slice of the Universal dyld binary, and the
only way to know that is to use the knowledge of the binary that you
got from loading it - that's done in mach_loader.c, which loads up the
dyld using a load command to set the path to it.
It'll look something like this:
Load command 6
cmd LC_LOAD_DYLINKER
cmdsize 28
name /usr/lib/dyld (offset 12)
The kernel really only knows about loading LC_SEGMENT, LC_SEGMENT_64,
LC_UNIXTHREAD, and LC_LOAD_DYLINKER sections of binaries. Everything
else is more or less ignored by the kernel, and dyld deals with it..
Depending on the specific tools you're using, you likely also need to
load the library /usr/lib/libgcc_s.1.dylib before you load /usr/lib/
libSystem.B.dylib.
I noticed that some of your data and text sections are improperly
aligned; specifically, minimal alignment on some sections is 4, and
__data and __bss need an alignment of 32 on Intel, since you might do
an SSE spill or make SSE calls, and they have to be aligned to avoid
your program dying as a result of an unaligned access fault. PPC
needs an alignment of 4, in case of Altivec.
It'd probably be informative for you to look at a binary that you
already know that it works, e.g. "/bin/ls" or something similar and
simple, and compare that to what you are generating.
If you want to be a little more ambitious, then you could download the
xnu source and look at the files in xnu/bsd/kern for mach_fat.c,
mach_loader.c, mach_loader.h, and kern_exec.c.
Oh, and you *really* don't want to be calling the system calls
directly: they don't match the documentation, since the documentation
for kill (for example) really documents the libc function; the actual
kill system call takes a third argument to tell it whether or not you
want it to act like the POSIX standard kill, or whether you ant it to
act like the Legacy MacOS X call kill, which, when you e.g. send a
signal to your own process group, whether or not you get the signal
sent to you _by_ you depends on the third argument. And that's just
one off the top of my head.
The reason for this type of thing is that we define our system
interface as being at the top of Libc, not between libc and the
kernel. This lets us change the contract between the kernel and user
space, if we need to to e.g. fix an issue, or provide a more efficient
implementation under the covers, or just switch to an entirely new
paradigm. It also lets us do things like make changes to e.g. the
stat structure to return more information, and then hide the
difference in a system call wrapper to maintain binary compatibility.
Minimally, you will at least want to use our libc sources to learn the
correct way to handle error returns and signals, etc.; the way error
returns and signals are trampolined, for example, is to return to an
alternate address - you don't necessarily come back to where you left,
and if you don't e.g. fix up the thread state following a signal using
the sigreturn entry point, you will quickly become sad every time
someone sends you a signal (as in any time you reboot, for example).
If you do decide to handle this all yourself anyway, then you'll
definitely need the xnu and Libc sources, since the structures you
pass into various Libc routines sometimes are not similar to the
structures that pass the user/kernel boundary, and like I said
earlier, there are argument list differences in the calls themselves.
You'll need the internal versions of the structures that define what
really goes across the user/kernel boundary.
-- Terry
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Darwin-kernel mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden