Branch: refs/heads/bbiiggppiigg/eh-frame-lsda
Home: https://github.com/dyninst/dyninst
Commit: 65736833134c78d40b62109bb82b190463c3c1cd
https://github.com/dyninst/dyninst/commit/65736833134c78d40b62109bb82b190463c3c1cd
Author: wuxx1279 <bbiiggppiigg@xxxxxxxxx>
Date: 2026-07-06 (Mon, 06 Jul 2026)
Changed paths:
M common/src/debug_common.C
M common/src/debug_common.h
M dyninstAPI/src/binaryEdit.C
M dyninstAPI_RT/src/RTcommon.c
M symtabAPI/h/Symtab.h
M symtabAPI/src/Object-elf.C
M symtabAPI/src/Object-elf.h
M symtabAPI/src/Symtab.C
Log Message:
-----------
symtab/dyninstAPI: synthesize eh_frame + gcc_except_table for relocated code (#1437)
Dyninst relocates instrumented functions into a new segment (.dyninstInst) but
emits no unwind info for the relocated code. When a relocated function is on the
stack during a C++ throw, libgcc's unwinder finds no FDE for the relocated PC and
calls std::terminate() -- so any exception thrown through, or caught in, an
instrumented frame aborts the program (issue #1437).
Generate unwind + exception-handling info for the relocated code at rewrite time
and register it at process startup:
* symtabAPI: Symtab::getCFALocations() exposes the original .eh_frame CFA rules
per PC range (via DwarfFrameParser); Symtab::getEHFrameInfo() decodes each
function's LSDA (call-site table, action table, type table, personality) from
.eh_frame + .gcc_except_table.
* dyninstAPI (binaryEdit): for every relocated function emit one FDE spanning
its relocated extent, with CFA rules mapped from the original .eh_frame. A
function that carried an LSDA also gets a "zPLR" CIE and a regenerated
.gcc_except_table whose call sites + landing pads are remapped block-by-block
through the CodeTracker (a function's hot and cold partitions merge into one
table). Pointers are pcrel where we own both ends; personality and type-table
entries preserve the original encoding (pcrel for PIE, absolute/udata4 for
non-PIE). The blobs live in loadable .dyninst_ehframe / .dyninst_gcc_except
regions with an exported __dyninst_eh_frame symbol. This runs for DYNAMICally
linked output only (guarded by !isStaticBinary()).
* dyninstAPI_RT: DYNINSTBaseInit() reads the weak __dyninst_eh_frame and libgcc's
weak __register_frame and registers the synthesized FDEs at startup. This is
compiled out of the static RT (#ifndef DYNINST_RT_STATIC_LIB): the static
rewriter mis-relocates any new global-data reference added to the relocated
DYNINSTBaseInit (it links the RT at emit, after such references are computed),
which crashed statically-linked rewritten binaries. Static-binary exception
support needs a rewriter-aware delivery (post-link patching / runtime scan)
and is left as follow-up; dynamic binaries are unaffected.
* common: add eh_printf (gated by DYNINST_DEBUG_EH) for diagnostics.
Verified with the #1437 reproducer (a function instrumented while on the stack
during a throw) for PIE and non-PIE dynamically-linked binaries, and on
641.leela_s. The static rewriter test suite passes with no crashes (registration
compiled out of the static RT).
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
|