Map

Win32 Is The Only Stable ABI on Linux

Wiki summarylinuxabielfwineglibc โ†ณ show in map Markdown
title
Win32 Is The Only Stable ABI on Linux
type
summary
summary
Glibc 2.36 broke Linux games by dropping DT_HASH; Win32 via Wine is the only stable ABI on Linux
tags
linux, abi, elf, wine, glibc
created
2026-04-08
updated
2026-04-15

In August 2022, glibc 2.36 shipped a change that broke games using Easy Anti-Cheat's EOS module on Linux. The culprit: glibc stopped emitting DT_HASH sections in its shared libraries, keeping only the newer DT_GNU_HASH. Software that walked the old hash table to count symbols โ€” a reasonable thing to do, since DT_HASH is part of the SYSV generic ABI โ€” started crashing.

The breakage wasn't limited to anti-cheat. libstrangle (an open-source frame limiter) and Shovel Knight also regressed. More was expected as distros picked up the new glibc.

The two hash tables

ELF binaries can carry two kinds of symbol hash tables. DT_HASH is specified in the SYSV generic ABI and documented: it has a fixed layout, and you can read the symbol count directly from the header. DT_GNU_HASH is a glibc/GNU invention โ€” faster lookups, smaller tables, but undocumented and missing some functionality. Getting the symbol count from DT_GNU_HASH requires parsing the entire table.

Glibc had been emitting both for years. The 2.36 release dropped DT_HASH from glibc's own libraries. The justification: glibc marks itself as ELFOSABI_GNU, so strictly speaking it isn't bound by the generic ABI's requirement to include DT_HASH. The savings: about 16 kB per library, under 1% of total size.

Why distros made it worse

Most Linux distributions configured GCC with --with-linker-hash-style=gnu, which tells the linker to emit only DT_GNU_HASH. This was a leftover from when the GNU hash table was new and the linker defaulted to sysv-only โ€” distros flipped the flag to get the performance benefit and never flipped it back. GNU ld itself defaults to --hash-style=both (emitting both tables), and mold defaults to --hash-style=sysv. But the distro GCC flag overrides the linker default, so most Linux binaries in practice have only DT_GNU_HASH.

Clang copies whatever the local GCC does through distro detection, propagating the choice further.

The kernel rule glibc ignores

Linus Torvalds has a standing policy for the Linux kernel: changing ABI is fine as long as nobody noticed, but once someone notices breakage, it's a regression and gets reverted. The kernel treats user-visible behavior as a stability contract regardless of what the spec says.

Glibc doesn't operate this way. The glibc maintainers argued that DT_HASH was never part of their ABI, that the information is still available in a different format, and that distros should solve the problem themselves. Real software breaking was treated as those programs' fault for depending on undocumented layout.

The punchline

The author's conclusion: Win32 via Wine is the only stable ABI on Linux. Wine commits to not breaking Windows applications. The Linux kernel commits to not breaking userspace. But glibc โ€” the layer between them โ€” doesn't make that promise, and it sits right where game developers need stability most. Targeting Windows and letting Wine handle the Linux side gives developers a more reliable contract than building native Linux binaries.

See also win32-weird-shaped-windows for an example of Win32's programming model stability โ€” the same region APIs from Windows 95 work identically today.