zaval wrote:You don't care about dynamic linking, and I do. And it looks awful to me how it's done in ELF and I like how it is in PE. For example that export by ordinal thing, easy to understand, efficient and easy to achieve. This is just an example, popped up from my memory, there are a lot more. I want to have modules that would import/export from each other and that it were done an efficient and elegant way.
ELF does not have a concept of exporting by ordinal. Symbols are only identified by their name. There is a symbol type (none, data object, function), but its utility is architecture dependent. However, you can of course implement some naming scheme for your ordinal export functions.
No, fundamental differences between PE and ELF when it comes to dynamic linking are:
- ELF has no concept of "exporting" a function. All external functions are exported. However, there is a patch on top of it called "symbol visibility". So now you can set external symbols to "local" visibility, and they will be used only within that library.
- ELF has no concept of importing a function from a library. You can only declare the need for a library, and later the need for a certain symbol, but nothing binds the symbol to the library. However, this does allow symbol interposition. For example, running a program and replacing the standard malloc with Electric Fence is possible/simple because of this. I have fond memories of reading the source code for a Skyrim mod package and finding out that the special launcher they require us to use is basically just setting LD_PRELOAD. What would have been one line of sh script became a hundred lines of C on Windows.
- The calling sequence through the PLT means that import libraries are unnecessary. And the cdecl calling convention makes the PE symbol name mangling (e.g. "ExitProcess@4") unnecessary. Both of these are positive things, I find.
zaval wrote:ELF, it seems, basically forces you to have just one giant executable and forget about the modularity, just like you like.
Oh no, if you want dynamic linking, you can have that. If you avoid symbol versioning, it can even be very modular. The problem here is already the idea of a giant executable. The UNIX model was supposed to be many tiny executables, and modularity by standardized IPC between them (which usually meant pipes transporting text streams). Having a big, complicated system, like Firefox, was not meant to be the UNIX way. But, here we are anyway.
After compilation, modularity is often highly compromised, anyway. Swap out a library version at your peril. However, that is not really a difference between ELF and PE. You can only change libraries as long as binary compatibility was maintained. No, to me, modularity is something achieved at the source level. Do you want to render your text using Pango/Cairo or Xft, that sort of thing. And that is basically fixed in place once the code is compiled, unless you make it a runtime switch. But that would be wasteful, having two code blocks to do the same thing, and only one of them is ever in use.