ELF fails on several fronts. Elf is for execution and linking. It mixes two kinds of things in one file. You would think, with all the junk they put in there, that it would get it right. As we can see, they didn't even get the 64/32 thing right, which is amazing.
You make it sound like it is hard to load an ELF file. It's not; it's about ten lines of code (half of that architecture-specific).
Also, you can strip the "linking" "junk" from an ELF file (get rid of all the section headers), and it will still load and run fine.
But let's suppose you have the ELF for /bin/cat: Section Headers: [Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[24] .bss NOBITS 0804c1e0 0041d0 000168 00 WA 0 0 32
whew! what's all that? It's stuff you use for linking. Why is it there? because cat gets linked to things at runtime.
Note the .bss ... it's in the L part, the "Link" part.
"L"? I don't see an "L"?
Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align PHDR 0x000034 0x08048034 0x08048034 0x000e0 0x000e0 R E 0x4 INTERP 0x000114 0x08048114 0x08048114 0x00013 0x00013 R 0x1 [Requesting program interpreter: /lib/ld-linux.so.2] LOAD 0x000000 0x08048000 0x08048000 0x03cb4 0x03cb4 R E 0x1000 LOAD 0x004000 0x0804c000 0x0804c000 0x001d0 0x00348 RW 0x1000 DYNAMIC 0x004014 0x0804c014 0x0804c014 0x000d0 0x000d0 RW 0x4 NOTE 0x000128 0x08048128 0x08048128 0x00020 0x00020 R 0x4 GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x4
program headers, which is stuff for when you run. These are images to load to memory.
Some of those are, yes.
Note that bss is not in the program headers ...
Look more closely, at the second PT_LOAD segment: it has a mem_size bigger than load_size, and that is your bss (and some other zero- initialised data).
and knowing about bss is pretty important at load time on an embedded system.
For what?
Note that a.out actually got this right, but who needs a working 40-year-old design when we've got a broken 20-year-old design :-)
a.out isn't 2% as flexible as ELF is. It's fine when you don't need that flexibility, but you won't be happy when you do need it and you chose a.out ;-P
Other issues. We had compressed ELF. So I got to watch coreboot uncompress the elf *somewhere* and then deal with having to memcpy the uncompressed elf sections *somewhere else*. That's gross. I got a nice speedup when I got rid of ELF in v3 -- it was actually noticeable.
Yeah. This could be solved some other way, of course.
Finally ... people (me included) keep messing up ELF parsers.
Really :-)
The GNU BFD tools don't quite get it right, in fact objdump used to coredump on some valid ELF files, which is why we have readelf.
That's not the history behind readelf, but sure, objdump is way more fragile than readelf -- but that's not because it does ELF, quite the opposite: it tries to be everything for every binary format!
I know one large company that totally blew it and implemented a simulator which used section headers and not program headers.
I've recently seen something quite like that. Almost made my head explode.
We had to modify the plan 9 linker to generate bogus ELF files for that system. The linuxbios ELF parser was always broken, and we didn't know it: it always assumed the program header section of elf came first, which it does *almost* all the time. But not always. It can come at the back.
You can easily force it to be at the start. Either do it in the linker script, or post-process the ELF.
As far as I can see, SELF saves about 100 bytes over ELF, at the cost of a lot of flexibility (only one code/data/bss/notes section, to start with), and a bunch of important header data is missing, too (endianness, word size, architecture).
Segher