[DynInst_API:] [dyninst/dyninst] 5bee17: symtabAPI: fix emitElf verdef BASE and RELR


Date: Wed, 08 Jul 2026 16:23:00 -0700
From: bbiiggppiigg <noreply@xxxxxxxxxx>
Subject: [DynInst_API:] [dyninst/dyninst] 5bee17: symtabAPI: fix emitElf verdef BASE and RELR
  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
[← Prev in Thread] Current Thread [Next in Thread→]
  • [DynInst_API:] [dyninst/dyninst] 5bee17: symtabAPI: fix emitElf verdef BASE and RELR, bbiiggppiigg <=