[DynInst_API:] [dyninst/dyninst] 467e64: symtab/dyninstAPI: synthesize eh_frame + gcc_excep...


Date: Sun, 05 Jul 2026 19:34:21 -0700
From: bbiiggppiigg <noreply@xxxxxxxxxx>
Subject: [DynInst_API:] [dyninst/dyninst] 467e64: symtab/dyninstAPI: synthesize eh_frame + gcc_excep...
  Branch: refs/heads/bbiiggppiigg/eh-frame-lsda
  Home:   https://github.com/dyninst/dyninst
  Commit: 467e641196ad521dd9ee18ce2dbd4155e0b1236c
      https://github.com/dyninst/dyninst/commit/467e641196ad521dd9ee18ce2dbd4155e0b1236c
  Author: wuxx1279 <bbiiggppiigg@xxxxxxxxx>
  Date:   2026-07-05 (Sun, 05 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.

  * dyninstAPI_RT: DYNINSTBaseInit() resolves __dyninst_eh_frame and libgcc's
    __register_frame and registers the synthesized FDEs at startup.

  * 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 both PIE and non-PIE binaries, and on 641.leela_s (which uses
exceptions in normal control flow) -- instrumented output matches the
uninstrumented binary.

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] 467e64: symtab/dyninstAPI: synthesize eh_frame + gcc_excep..., bbiiggppiigg <=