[DynInst_API:] [dyninst/dyninst] 1bb8b2: Fix failing to write instrumented shared library (...


Date: Fri, 19 Jun 2026 15:09:55 -0700
From: bbiiggppiigg <noreply@xxxxxxxxxx>
Subject: [DynInst_API:] [dyninst/dyninst] 1bb8b2: Fix failing to write instrumented shared library (...
  Branch: refs/heads/master
  Home:   https://github.com/dyninst/dyninst
  Commit: 1bb8b2698323fb902fcc3e00c6d70bea491b74cc
      https://github.com/dyninst/dyninst/commit/1bb8b2698323fb902fcc3e00c6d70bea491b74cc
  Author: bbiiggppiigg <bbiiggppiigg@xxxxxxxxx>
  Date:   2026-06-19 (Fri, 19 Jun 2026)

  Changed paths:
    M symtabAPI/src/emitElf.C
    M symtabAPI/src/emitElf.h

  Log Message:
  -----------
  Fix failing to write instrumented shared library (#2081) (#2294)

Rewriting some shared libraries (e.g. libtorch_python.so) produced a
broken or unloadable output. Two assumptions in the ELF emitter break
on binaries whose program/section layout is unusual; both must be fixed.

1. Insertion point for new loadable sections.
   findSegmentEnds() computed dataSegEnd as max(p_vaddr + p_memsz) over
   all PT_LOAD segments, and driver() only appended the new instrumentation
   sections when some section satisfied sh_addr + sh_size == dataSegEnd.
   When the highest-addressed loadable segment holds relocated read-only
   metadata (.gnu.hash/.dynstr) and is padded past its last section, no
   section ends on that boundary, so createLoadableSections() was never
   called and the result came out with a zero-sized .dynamic ("object file
   has no dynamic section"). Replace findSegmentEnds() with
   findLastLoadableSec(), which returns the start address of the
   highest-addressed section contained in the last loadable segment; the
   trigger becomes shdr->sh_addr == lastLoadableSecStart. This is
   equivalent to the previous behavior for ordinary binaries (still
   triggers on .bss).

2. Program-header insertion order.
   fixPhdrs() located the slot for the new PT_LOAD by scanning for the
   first LOAD -> non-LOAD transition, assuming PT_LOAD entries are
   contiguous in the program header table. libtorch_python.so has
   GNU_STACK as the second program header (right after the first LOAD),
   so the new highest-vaddr segment was inserted at index 1, leaving the
   PT_LOAD entries unsorted by p_vaddr. glibc's _dl_map_segments relies on
   ascending p_vaddr order and crashes. Insert the new segment before the
   first PT_LOAD whose p_vaddr is greater than newSegmentStart (else append
   at the end), keeping PT_LOAD entries sorted regardless of interspersed
   non-loadable entries.

With both fixes, the rewritten library has a valid .dynamic, a correctly
ordered new loadable segment, and loads under the dynamic linker the same
way the original does; instrumenting and running ordinary binaries is
unaffected.

Co-authored-by: Claude Opus 4.8 <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] 1bb8b2: Fix failing to write instrumented shared library (..., bbiiggppiigg <=