Parse __eh_frame DWARF info on macOS for per-PC frame descriptions#430
Open
Parse __eh_frame DWARF info on macOS for per-PC frame descriptions#430
Conversation
CI Test ResultsRun: #23953274128 | Commit:
Status Overview
Legend: ✅ passed | ❌ failed | ⚪ skipped | 🚫 cancelled Summary: Total: 32 | Passed: 32 | Failed: 0 Updated: 2026-04-03 16:45:40 UTC |
Contributor
There was a problem hiding this comment.
Pull request overview
Adds macOS support for parsing raw __eh_frame DWARF CFI to produce per-PC frame descriptions, improving unwinding for binaries that don’t provide __unwind_info (e.g., GCC-built libs).
Changes:
- Introduces a
DwarfParserconstructor +parseEhFrame()path to parse linear.eh_frame/__eh_framewithout an.eh_frame_hdrindex. - Extends macOS Mach-O parsing to locate
__eh_frameand populateCodeCache’s DWARF table; also addsSymbols::clearParsingCaches()for macOS. - Adds new gtest unit tests for
parseEhFrame().
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
ddprof-lib/src/main/cpp/dwarf.h |
Declares the new raw-eh-frame constructor and parseEhFrame() API. |
ddprof-lib/src/main/cpp/dwarf.cpp |
Implements linear __eh_frame parsing and augmentation handling. |
ddprof-lib/src/main/cpp/symbols_macos.cpp |
Finds __eh_frame in Mach-O __TEXT and wires parsed DWARF into CodeCache. |
ddprof-lib/src/test/cpp/dwarf_ut.cpp |
Adds unit tests exercising the new linear .eh_frame parsing path. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Scan-Build Report
Bug Summary
Reports
|
||||||||||||||||||||||||||||||||||||
dfe7b83 to
4466cfb
Compare
Revert static thread_local jmp_buf in walkVM — thread_local access via __tls_get_addr is not async-signal-safe in a dlopen'd agent. Suppress core.StackAddressEscape in scan-build instead: the jmp_buf address is always restored to saved_exception before walkVM returns. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Parse raw
__eh_frameDWARF CFI data on macOS to provide per-PC frame descriptions for GCC-built libraries, improving stack unwinding accuracy for functions with non-standard frame layouts (leaf functions,-fomit-frame-pointer).Changes
ddprof-lib/src/main/cpp/dwarf.h/dwarf.cppDwarfParserconstructor accepting a raw(eh_frame, size)pair (no binary-search index).parseEhFrame(): linearly iterates CIE/FDE records, extracts code/data alignment from each CIE, decodes per-PC frame descriptions from FDEs, thenqsorts the result._has_z_augmentationfield: set when the CIE augmentation string starts with'z'. The FDE augmentation-data-length LEB field is only present in that case; guarding the skip prevents corrupting the instruction stream for CIEs with empty or non-zaugmentation. The parser assumes a single CIE per module — the DWARF spec allows multiple CIEs with different augmentation strings, but macOS binaries compiled by clang always emit one CIE per module and this path is only exercised for macOS__eh_framesections.detectedDefaultFrame()tosetDwarfTable(), matching the Linux path and correctly selecting the clang frame layout on aarch64.getLeb()/getSLeb()calls to guard against malformed or truncated__eh_framedata.ddprof-lib/src/main/cpp/symbols_macos.cpp__eh_framesection in the__TEXTsegment during Mach-O parsing.DWARF_SUPPORTEDand the section is present, construct aDwarfParserand callcc->setDwarfTable()with the detected default frame.Symbols::clearParsingCaches()definition (fixes linker error on macOS).ddprof-lib/src/test/cpp/dwarf_ut.cpp(new)parseEhFrame(): empty section, terminator-only, CIE-only, and CIE+FDE.Why
On macOS, GCC-built shared libraries (
libgcc, Homebrew packages) emit__eh_framewith standard DWARF CFI, but no__unwind_info. Previously the profiler fell back to a single library-wide heuristic frame layout for these libraries. Parsing the DWARF FDE table yields exact CFA/FP/PC rules per instruction address, eliminating unwinding failures at function prologues and epilogues.JIRA: PROF-14088