Live data from Hacker News

On ELF, Part 2 (2018)

kestrelcomputer.github.io

1–10 of 36 posts

Re: On ELF, Part 2 (2018)

#2
Just submitting part 2 of this as I stumbled across it after having played around with write ELF files by hand. Never knew about the Hunk format and I think the author makes some interesting points.

Re: On ELF, Part 2 (2018)

#4
This is all well and good, but in reality everyone is using all the rich features of ELF -- dynamic linking obviously, but also symbol versioning, constructors, symbol interposition (probably the worst one for performance), symbol visibility, preload, etc. The question is how to make it fast in the common case, and actually the Linux and glibc authors are doing a pretty good job here.

Re: On ELF, Part 2 (2018)

#5
post #4

This is all well and good, but in reality everyone is using all the rich features of ELF -- dynamic linking obviously, but also symbol versioning, constructors, symbol interposition (probably the worst one for performance), symbol visibility, preload, etc. The question is how to make it fast in the common case, and actually the Linux and glibc authors are doing a pretty good job here.

I have looked quite closely into glibc in the past and there are great many things that could be improved and not using some of the fancy ELf features is probably one of them. For example symbol versioning doesn't appear to have a good cost/benefit balance.

Re: On ELF, Part 2 (2018)

#6
I worked with a.out on early unixes and elf on later ones - not addressed here is the main reason for switching: ELF allowed you manage pages contiguously on disk so that they could be paged in directly (stuff can be page aligned within the file at it's natural offsets), while a.out was designed for swapped kernels where you would just read() data into a text section, address 0 might be 32 bytes from the start of a file (disk space was more of a concern back then).

Re: On ELF, Part 2 (2018)

#8
post #4

This is all well and good, but in reality everyone is using all the rich features of ELF -- dynamic linking obviously, but also symbol versioning, constructors, symbol interposition (probably the worst one for performance), symbol visibility, preload, etc. The question is how to make it fast in the common case, and actually the Linux and glibc authors are doing a pretty good job here.

Some of the features you mentioned are not really features of ELF itself but rather tacked on by tools and libraries.

For instance, symbol versioning is just an ad-hoc convention for embedding version numbers into the symbol strings themselves. And the convention assumes that the source language is C, which requires other languages to mangle their symbols to make them fit.

Some features that systems rely on are not even officially documented. I've read accounts from a developer of a linker who had to read through code, blogs and old mailing lists to figure out the actual format for a feature.

Re: On ELF, Part 2 (2018)

#9
post #6

I worked with a.out on early unixes and elf on later ones - not addressed here is the main reason for switching: ELF allowed you manage pages contiguously on disk so that they could be paged in directly (stuff can be page aligned within the file at it's natural offsets), while a.out was designed for swapped kernels where you would just read() data into a text section, address 0 might be 32 bytes from the start of a f…

What’s the advantage of that? Would the kernel just load the entire file into contiguous memory and set up pages at the correct physical addresses?

Re: On ELF, Part 2 (2018)

#10
post #4

This is all well and good, but in reality everyone is using all the rich features of ELF -- dynamic linking obviously, but also symbol versioning, constructors, symbol interposition (probably the worst one for performance), symbol visibility, preload, etc. The question is how to make it fast in the common case, and actually the Linux and glibc authors are doing a pretty good job here.

One thing I saw in KDE applications (KDE has split its base libraries into a bazillion small libraries) is that looking up a symbol in a dynamic library is fast, but linearly trying all the libraries is costly - (IIRC) 20-40% of startup time. A possible solution would be to store with each symbol where it's expected to come from. Required libraries are listed as an array, so the "where" could be an index into the array. Symbol overriding would have priority over that lookup mechanism, but apart from overrides, lookup could be just one hash lookup in the already known library.

I am still hoping for someone else to implement that so I occasionally mention the idea :)

Post reply on HN