Branch: refs/heads/bbiiggppiigg/emitelf-verdef-base-relr
Home: https://github.com/dyninst/dyninst
Commit: 5bee176cacddb4fe1528e543151d6f552eddc7f5
https://github.com/dyninst/dyninst/commit/5bee176cacddb4fe1528e543151d6f552eddc7f5
Author: wuxx1279 <bbiiggppiigg@xxxxxxxxx>
Date: 2026-07-08 (Wed, 08 Jul 2026)
Changed paths:
M symtabAPI/src/emitElf.C
Log Message:
-----------
symtabAPI: fix emitElf verdef BASE and RELR
emitElf regenerates .dynsym/.gnu.version*/.dynamic for every rewritten
object that has dynamic symbols, and that regeneration corrupts any
modern (glibc >= 2.36) versioned library -- e.g. the libc.so.6 that
test_reloc rewrites: every process loading the result, even a pristine
/bin/true, crashed in _dl_relocate_object before main. Two independent
bugs:
1. Regenerated .gnu.version_d loses the BASE definition.
createSymbolVersions rebuilds verdefs purely from per-symbol version
strings; the BASE entry (the library's own SONAME, vd_ndx
VER_NDX_GLOBAL, flag VER_FLG_BASE) is referenced by no symbol in
libc -- every defined symbol carries a GLIBC_2.x version -- so it was
silently dropped (39 -> 38 entries; eu-elflint: "no BASE
definition"), and vd_flags has been hardcoded 0 since the code was
written. The loader then builds a version table with a hole at index
1 and dies at strcmp(NULL, ...). Fix: synthesize the SONAME verdef at
VER_NDX_GLOBAL with VER_FLG_BASE whenever verdefs are regenerated and
no symbol supplied it; when a symbol does carry the SONAME version,
map it to VER_NDX_GLOBAL instead of a sequential index.
2. emitElf predates RELR (DT_RELR packed relative relocations,
glibc >= 2.36). Everything RELR is expressed in link-time vaddrs, so
the library_adjust section shift left three things stale: the DT_RELR
pointer (unknown tag, never adjusted), the address entries inside
.relr.dyn, and the contents of every covered slot (RELR is REL-style:
the addend -- the link-time target address -- lives in the slot).
The loader executed garbage relative relocations and crashed on the
first entry. Fix: add DT_RELR to the library_adjust tag switch and
rewrite the RELR data after the section copy: shift even (address)
entries -- odd entries are bitmaps of word deltas, invariant under a
uniform shift -- and add library_adjust to each covered slot,
skipping sections whose pointer contents emitElf already shifts
(.init_array and friends) to avoid double adjustment.
Verified in a glibc-2.36 container where test_reloc previously CRASHED:
testsuite -rewriter -allcomp gcc+g++ 94/94 PASSED, -staticlink 47/47;
/bin/true runs against the rewritten libc.so.6 + ld-linux; eu-elflint's
BASE complaint is gone. Also compiles against a pre-RELR elf.h
(RHEL 8, gcc 15) via fallback defines.
Co-Authored-By: Claude Fable 5 <noreply@xxxxxxxxxxxxx>
To unsubscribe from these emails, change your notification settings at https://github.com/dyninst/dyninst/settings/notifications
|