thursday, 13 december 2007

posted at 22:04
  • mood: hobbitish

I just now have the extensions to the ELF loader implemented such that my gargantuan WebKit test binary loads. It took me a lot of reading and experimenting to figure out what was going on but I got it.

In my last post I talked about how files with large numbers of section headers store the count of headers elsewhere in the file. I'd taken care of that just fine. The other important thing that I missed is that every entry in the symbol table has a section header index that points to the section that the symbol is relative to. Of course this is a 16-bit field also, and has the same problem as the header count does.

The solution to this one is even more crazy. Basically there's an entire extra section in the file that is just an array of 32-bit values. If a symbol refers to a section with an index that is too large, you basically go fishing into that array to find the index instead. This of course means that I have to have that array loaded and available before I start doing symbol table work.

Finally, something that confused me until I put together some nice macros to deal with it was that there's a "hole" in the range of possible section header index numbers. What used to be the top 256 values (0xff00 to 0xffff) are reserved as special control codes, markers and other such things. Now that the header number is fudged into 32 bits, we get the situation where the header at index 65279 (0xfeff) corresponds to section 65279, but the header at index 65280 actually corresponds to section 65536 (0x10000). So basically, anywhere that a section number is found in any of the ELF structures, it has to be massaged into a header array index number taking the hole into account. This caused no end of issues, particularly since my file has hundreds of effectively unused sections - it was hard to even see when it was going wrong!

So now ArosLauncher loads and runs and I get some debug output before it crashes:

UNIMPLEMENTED:
(../../../WebCore/platform/aros/TemporaryLinkStubs.cpp:42 void WebCore::setFocusRingColorChangeFunction(void (*)()))
UNIMPLEMENTED:
(../../../WebCore/platform/aros/SharedTimerAros.cpp:10 void WebCore::setSharedTimerFiredFunction(void (*)()))

Before I get back into WebKit though I need to cleanup this code and commit it. I still need to merge the other two ELF loaders. As far as I can tell from a cursory glance the elf64 version is basically the same but using 64-bit definitions, macros, etc as defined by the ELF specs. The other, elf_aros, I'm not entirely sure about but its certainly much simpler. Its possible it just hasn't been looked at for a long time (the changelog certainly appears to show that). I'll continue to try to figure out what its for, but my feeling is that it can probably go, and elf64 and elf can be comfortably merged with a little restructuring of the code.

One thing that has become apparent is that our loader is incredibly slow and rather naive. As we start implementing more features (debug support, memory protection, shared objects) I don't think its going to cope well with its current structure. And its certainly got its work cut out for it - I've been reading Ulrich Drepper's paper "How To Write Shared Libraries", and it goes into a lot of detail about the kind of pain the dynamic linker has to go through to make things work. The glibc loader is something I'll have to study, I think.