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


Date: Wed, 03 Jun 2026 13:07:31 -0700
From: bbiiggppiigg <noreply@xxxxxxxxxx>
Subject: [DynInst_API:] [dyninst/dyninst] d13214: Fix failing to write instrumented shared library (...
  Branch: refs/heads/bbiiggppiigg/fix-2081
  Home:   https://github.com/dyninst/dyninst
  Commit: d132147e5488d000441aa6133f24eed32ab9cd5a
      https://github.com/dyninst/dyninst/commit/d132147e5488d000441aa6133f24eed32ab9cd5a
  Author: wuxx1279 <bbiiggppiigg@xxxxxxxxx>
  Date:   2026-06-03 (Wed, 03 Jun 2026)

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

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

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] d13214: Fix failing to write instrumented shared library (..., bbiiggppiigg <=