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
|