Win32 Is The Only Stable ABI on Linux
- Glibc 2.36 was released and all the games using EAC EOS are no longer playable.
- A user did bisect and found the offending commit.
- I’ve filed a Glibc bug hoping for a quick revert.
- Turns out other things are also broken.
- Most likely it will stay this way.
- Win32 (via Wine + friends) is the only stable ABI on Linux :-P
In the ELF format there are two ways of providing a hash table of symbols.
DT_GNU_HASH. The first one is part of SYSV generic
ABI and is well documented and marked as mandatory.
a newer, smaller, and faster replacement that is not documented,
implemented in a few places (Glibc, GNU ld, Musl, LLVM, mold, etc.) and a
subject of a couple of blog posts that I’ve found.
Turns out it also doesn’t provide the same functionality as
DT_HASH. To get
the number of symbols you have to completely parse it.
It’s worth noting that unless you are building
ELFOSABI_NONE binaries you are
not forced to follow the generic ABI. Glibc uses
technically not including
DT_HASH is fine.
Glibc was forcing having both sections for a very long time claiming to maintain compatibility. It was recently dropped and the build instead relies on “the defaults”.
This problem was first noticed by rolling-release distros users when games using EAC EOS stopped working. There’s also an open source project that has regressed - a frame rate limiter called libstrangle. The non-EAC game Shovel Knight is broken as well.
Those are only a few breakages users of the more bleeding-edge distros found shortly after the Glibc 2.36 release. I suspect there will be more broken games (and other software) once 2.36 will hit the mainstream.
To ABI Or Not To ABI
DT_HASHis not part of the ABI.
- It’s not an ABI break - the lookup information is still there, just in a different format.
DT_HASHis up to distributions.
- It saves 16kB (< 1% of total size).
DT_HASHshould not be mandatory in gABI.
I suggest you read through all the linked discussions and develop your own opinion on who is responsible for what exactly.
Personally I share Linus’ opinion that changing ABI is okay as long as no one has noticed, but once it gets noticed - then it’s a regression. Once it’s a thing people depend on, it becomes a feature.
Sadly not everything can be easily modified to accommodate or recompiled.
Shifting the problem downstream onto the distributions is also problematic and adds to fragmentation.
I know that
DT_GNU_HASH is a thing for 16 years already and
most distributions have switched to using it and only it by default. For those
16 years, it was Glibc who provided the compatibility and overrode the defaults
for everyone and there never were any easy-to-spot deprecation warnings. It’s
also unrealistic to expect every ELF consumer to keep up with undocumented
developments of the format.
--hash-style=gnu is The Default?
Kinda by accident? GCC’s default behavior is to allow linkers to do whatever they want. The GNU Linker defaults to “both”
ld --help | grep hash-style --hash-style=STYLE Set hash style to sysv/gnu/both. Default: both
while mold defaults to “sysv”. So why most things are built with –hash-style=gnu? On a lot of distributions gcc -v claims that
Configured with: /build/gcc/src/gcc/configure ... --with-linker-hash-style=gnu ...
which seems to be a leftover from the days long gone where
DT_GNU_HASH was so
young that ld’s default was still sysv. Distributions wanted to have the
promised speedup so they have just forced this and it stuck.
This seems to spread further - clang does distro detection and seems to be mimicking whatever the distro is doing with their default gcc.
I think this whole situation shows why creating native games for Linux is challenging. It’s hard to blame developers for targeting Windows and relying on Wine + friends. It’s just much more stable and much less likely to break and stay broken.