Haxxoring the elf format for 1k/4k stuff

category: code [glöplog]
I've been investigating/experimenting with this for the past week and discovered some interesting stuff but haven't made a whole lot of progress implementing it because I'm a n00b at assembly language. Is anyone else interested in this stuff? If so I'll share what I've found out.
Someone said something about that the other day on the oneliner. Was it you?

I could be interested. What did you find?
added on the 2008-06-14 15:16:33 by xernobyl xernobyl
might be interesting, since i looked into doing 4k intros on os4.

It doesn't help that PowerPC takes a lot of instructions to do not so much, or that OS4 exe's have to have relocation information (unlike linux) because it doesn't have virtual memory, so are automatically bigger.

In pure C, i got an OpenGL window on workbench with a (xor ;-) textured quad in it in 2748 bytes, although that could be shrunk by a hundred or so, i think.

In pure PowerPC assembler, i've got the OpenGL window up and being cleared, but no textured quad because my call to glTexSubImage2D is crashing and i don't know why, but the exe for that is 1300 bytes, which is still quite a lot of your 4k allowance :-)

Sound is going to be a bitch, since AHI takes a fair amount of setup, although i'm thinking it might be possible to precalculate the entire intro soundtrack at the beginning and just write it to the AUDIO: handler.

Anyway, any insights you have on making small elf executables might be useful for me, too.
added on the 2008-06-14 15:18:42 by xeron xeron
.. and of course, not only does PowerPC take lots of instructions to do stuff (want to call a routine that has local variables and calls other routines? you need a bunch of instructions to set up a stack frame! HA!), every instruction is 4bytes long.

I'm thinking some kind of bytecode compiler might help, but then the compiler takes up part of the 4k.

Also, the only executable cruncher for OS4 (joerg's lzmaloader) is no help since the decrunch header is 5000 bytes, so thats another problem.

I'm thinking of writing a dropper in 68k assembler which dumps its payload to ram, then i can pack that with a traditional amiga exe packer.
added on the 2008-06-14 15:22:04 by xeron xeron
xernobyl, yep that was me.

Hmmm that's a shame about relocation information on OS4. My main discoveries are probably specific to linux:

  • libc is automatically loaded into an executable's process image by the loader (as long as some sections are present, I havent' worked out which yet)
  • you can import shared libraries with libc using glibc_dlopen_mode (I've got proof of concept for this)
  • it's possible to find shared libraries in a process image by inspecting structures created by the loader at runtime, or by reading /proc/self/maps (I've got proof of concept for the latter)
  • it's possible to import functions by hash manually by inspecting the shared libraries' process image

All this means that you can import shared library functions with an extremely cut down elf header. What I'm investigating now is just how much you can leave out of the elf header and still keep the loader happy.
I thought you were talking about Wii's elf files somehow :)
added on the 2008-06-14 15:57:17 by xernobyl xernobyl
Well presumably the same will apply?
Smoke and I did some elf hacking quite a long time ago. Check out http://pouet.net/prod.php?which=1318, it uses a custom constructed elf header and comes with source.
added on the 2008-06-14 16:06:19 by avoozl avoozl
avoozl, cool I will have a look at that
Okay, it appears that I was wrong about my first point. All's not lost though...
I managed to do the import by hash trick on linux some time ago, finding the library in /proc/self/maps (loading it with LD_PRELOAD from the unpacker/launcher shell script) and then looking at the symbol table on the elf header, but didn't test it enough to use it in an actual intro and eventually forgot about it. I can share my (quick and dirty, of course) sources if anyone wants them.

What's that glibc_dlopen_mode thing? It sounds interesting :D
added on the 2008-06-14 21:08:01 by slack slack
slack, yup I was doing the /proc/self/maps trick too but I've found a much smaller method of getting shared library addresses using the loader's link_map structure. The glibc_dlopen_mode function is a version of dlopen from libdl but with less error check (infact i think dlopen uses this function). However, I now realise it's fairly useless. libc isn't loaded automatically as I suspected unless you link against at least 1 library (having juts an interp section in the elf is not enough). After implementing this I realised that using the elf header is actually the smallest way of importing libraries (8 bytes+ the length of the string containing the library name). I should have some code to show soon, trouble is even implementing the simplest things in assembler takes hours for me since I'm a n00b ;)
slack, is it your code on linuxdemos.org for import by hash and the /proc/self/maps trick? If so thanks very much as that was extremely helpful (despite the fact that it crashes on my machine ;) )
I'm going to keep a close watch on this thread...
added on the 2008-06-14 22:16:50 by LiraNuna LiraNuna
I'm also interrested in this!
added on the 2008-06-15 00:39:00 by jaw jaw
btw, where is linuxdemos hosted? it's always very slow...
added on the 2008-06-15 00:40:11 by jaw jaw
parapete: no, that code isn't mine. it was what i used as a starting point, too ;)
added on the 2008-06-15 01:36:55 by slack slack
slack, how rigorously did you test import by hash using the hash section provided in an elf? After some experimentation it seems to me it's absolutely useless because the table contains tonnes of collisions even for a small amount of entries and only appears to be there as a performance increase so you don't have to linearly search through the list of strings. Still, this doesn't stop one using import by hash like it's done on Windows.
try importing on hash.
added on the 2008-06-15 17:38:05 by visy visy
visy: you read the thread, did you?
added on the 2008-06-15 19:14:43 by v3nom v3nom
I'm quite sure you missed the point. :)
added on the 2008-06-15 19:24:23 by visy visy
Not sure I understand either, I assumed you hadn't read the thread ;)
I guess it was a drug-reference, parapete
added on the 2008-06-15 19:42:48 by kusma kusma
kusma : haha yes I think you might be right.

visy : I shall give it a try then! I can confirm that importing on booze is not a good strategy.
Elf32 headers take about 70 bytes when not using dynamic libraries. And we all know that dynamic libraries suck at the 1k/4k size class (however, as X11 is a slightly complicated protocol, people seem to prefer using them).

See http://in4k.untergrund.net/index.php?title=Linux