https://sourceware.org/bugzilla/show_bug.cgi?id=34403
Bug ID: 34403
Summary: libelf.a bundles lib/crc32.o whose public crc32 symbol
collides with zlib's when statically linking —
eu-strip fails with "multiple definition of crc32
Product: elfutils
Version: unspecified
Status: UNCONFIRMED
Severity: normal
Priority: P2
Component: libelf
Assignee: unassigned at sourceware dot org
Reporter: robb at datalogics dot com
CC: elfutils-devel at sourceware dot org
Target Milestone: ---
Created attachment 16847
--> https://sourceware.org/bugzilla/attachment.cgi?id=16847&action=edit
Makefile.am patch against elfutils 0.195
Since elfutils 0.193, statically linking the elfutils tools (or any consumer of
the installed libelf.a) together with a static zlib fails with a duplicate
symbol error. Building 0.195 with BUILD_STATIC enabled against a static
libz.a (zlib 1.3.1, clang 21 / GNU ld 2.44, observed identically with earlier
toolchains):
CCLD strip
/usr/bin/ld: libz.a(crc32.c.o): in function `crc32':
crc32.c:(.text+0x900): multiple definition of `crc32';
../libelf/libelf.a(crc32.o):crc32.c:(.text+0x0): first defined here
clang: error: linker command failed with exit code 1 (use -v to see
invocation)
make[2]: *** [Makefile:834: strip] Error 1
Versions 0.190/0.191/0.192 link the same configuration successfully.
Root cause:
Commit f5d6e088f84dd ("Add libeu objects to libelf.a static archive", first
released in 0.193, the fix for bug #32293) makes libelf/Makefile.am bundle
every
object listed in lib/libeu.manifest into libelf.a via libelf_a_LIBADD. That
manifest includes crc32.o, which exports a global, default-visibility crc32
symbol
— the same name (and the same standard CRC-32) as zlib's.
The failure sequence, confirmed with ld --trace-symbol:
1. strip.o references crc32_file (for the .gnu_debuglink checksum). Scanning
libelf.a extracts crc32_file.o, whose crc32 reference is satisfied within the
same archive by crc32.o. libelf.a now contributes a strong global crc32.
2. -lz is scanned next: deflate.c.o/inflate.c.o are needed (libelf's
elf_compress uses them), and since zlib 1.2.12 deflate.c.o also references
crc32_z.
elfutils' crc32.o does not define crc32_z, so the linker is forced to extract
libz.a(crc32.c.o) — which also defines crc32. Two strong definitions → hard
error.
Before 0.193 this could not happen: crc32.o/crc32_file.o lived only in the
internal libeu.a, which the tool link lines place after -lz. By the time
libeu.a
was scanned, crc32 was already defined by zlib's crc32.c.o, so
libeu.a(crc32.o) was never extracted.
Note the problem is not limited to the elfutils tools: the installed libelf.a
now exposes a public crc32, so any downstream program statically linking
libelf.a alongside libz.a can hit the same collision in its own link (e.g. if
the application itself calls zlib's crc32() and links -lelf before -lz). Link
reordering cannot fix it, because zlib's crc32.c.o is always required (for
crc32_z) whenever the compression code is pulled in.
Suggested fix:
Exclude crc32.o from the objects bundled into libelf.a. libelf's internal
users already go through the hidden __libelf_crc32 wrapper (libelf_crc32.o),
and
libdwfl uses its own __libdwfl_crc32. The still-bundled crc32_file.o then
resolves crc32 from zlib, which is a hard dependency of libelf anyway
(functionally
identical implementation — the .gnu_debuglink CRC is defined as the zlib
CRC-32). Patch against 0.195 attached.
--
You are receiving this mail because:
You are on the CC list for the bug.