The coding frenzy will certainly slow down.
My sabbatical vacation has come to an end. And to sum things up, I started this blog not because I got bored (even though I was afraid I would just end up geeking on nothing in particular all day long), but from a suggestion from fabienne: « why don't you document what you do, when you find solutions to your problems that google did not know about? ».
Very good suggestion indeed, and even though I could not document everything I did this month, I wrote a how-to and linked to a few interesting (or less interesting) pages. I'm glad that my friend oz found it interesting enough (or was simply really bored) to create an RSS feed of my stupid plain HTML page. The problem it creates for me now is that if I continue to add stuff to this page, it will become annoyingly long to load and still have no permanent links. I'm gonna think about that.
Anyway, all in all, even if (as always) I could not do as much as I wanted, I think I can be satisfied (maybe I'll even be proud one day) that my libc combined statically with my shell can now assist it enough to launch commands and eventually, be, hmm, somewhat, useful. Sadly, when used as the init program on NetBSD/i386 it crashes for some reason, and it still has more function stubs than actual code...
As mentioned earlier, getting it to work took more than expected, and was not exactly heavily documented. As too often, the answer is in the source, and kudos to free software for that, but it's often not really helpful (which is part of the reason why I am writing my own code in the first place). On the other hand, I really improved with gdb and reverse-engineering with objdump. Not that I dislike IDA, but it just forces one to really get the picture oneself, and the lack of practice over theory bit me again.
I should stop the chit chat now, and get to actual content, but I can't really sort out what I should have documented myself earlier (insert shame here). So, here it is, your moment of zen...
About developping a libc
Thankfully, smaller projects than glibc or BSD libc exist to get good inspiration from. These two were the first to help me figure that out:
- _start (the actual starting point in a program before main) should never be part of the shared object itself (libc.so), as it is meant to load it properly (among other things)
- this also means that if you don't load it properly, the afore-mentioned shared object will (almost) never work; as a consequence the libc supports only static linking to this date
- the compiler may expect you to restore the content of some registers to their original value, even after a function call (notably %ebx on i386) although I could not confirm this anywhere (and on Sparc I must say that it is actually part of the design and specification)
- some syscalls have weird undocumented particularities, take for
example NetBSD/i386:
- fork() in the source is considered to return the child's PID in both the parent *and* the child, where %edx (sic) actually allows the caller to make the difference
- execve() will not return -errno in %eax but directly its actual value (thanks again guys)
As a conclusion, I have to say that Linux emulation on NetBSD was reliable to the point that everything crashed in the exact same way that my actual Linux host did. Quite amazing. I could perform both development efforts just on my NetBSD host, since my libc allows you to compile native Linux binaries using the plain standard gcc installation there (with CPPFLAGS="-U __NetBSD__ -D __linux__"). This was also part of my plan and works :)
Update: of course the third point was because of the cdecl calling convention.
I said I'd never blog

