Skip to content

Parse __eh_frame DWARF info on macOS for per-PC frame descriptions#430

Open
jbachorik wants to merge 3 commits intomainfrom
jb/prof-14088
Open

Parse __eh_frame DWARF info on macOS for per-PC frame descriptions#430
jbachorik wants to merge 3 commits intomainfrom
jb/prof-14088

Conversation

@jbachorik
Copy link
Copy Markdown
Collaborator

@jbachorik jbachorik commented Mar 22, 2026

What

Parse raw __eh_frame DWARF 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.cpp

  • Add new DwarfParser constructor accepting a raw (eh_frame, size) pair (no binary-search index).
  • Implement parseEhFrame(): linearly iterates CIE/FDE records, extracts code/data alignment from each CIE, decodes per-PC frame descriptions from FDEs, then qsorts the result.
  • Add _has_z_augmentation field: 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-z augmentation. 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_frame sections.
  • Pass detectedDefaultFrame() to setDwarfTable(), matching the Linux path and correctly selecting the clang frame layout on aarch64.
  • Add bounds check in CIE parsing before getLeb()/getSLeb() calls to guard against malformed or truncated __eh_frame data.

ddprof-lib/src/main/cpp/symbols_macos.cpp

  • Detect __eh_frame section in the __TEXT segment during Mach-O parsing.
  • When DWARF_SUPPORTED and the section is present, construct a DwarfParser and call cc->setDwarfTable() with the detected default frame.
  • Add missing Symbols::clearParsingCaches() definition (fixes linker error on macOS).

ddprof-lib/src/test/cpp/dwarf_ut.cpp (new)

  • Four gtest unit tests covering parseEhFrame(): empty section, terminator-only, CIE-only, and CIE+FDE.

Why

On macOS, GCC-built shared libraries (libgcc, Homebrew packages) emit __eh_frame with 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

@jbachorik jbachorik changed the title PROF-14088 Parse __eh_frame DWARF info on macOS for per-PC frame descriptions Mar 22, 2026
@dd-octo-sts
Copy link
Copy Markdown

dd-octo-sts bot commented Mar 22, 2026

CI Test Results

Run: #23953274128 | Commit: fb1831f | Duration: 22m 7s (longest job)

All 32 test jobs passed

Status Overview

JDK glibc-aarch64/debug glibc-amd64/debug musl-aarch64/debug musl-amd64/debug
8 - - -
8-ibm - - -
8-j9 - -
8-librca - -
8-orcl - - -
11 - - -
11-j9 - -
11-librca - -
17 - -
17-graal - -
17-j9 - -
17-librca - -
21 - -
21-graal - -
21-librca - -
25 - -
25-graal - -
25-librca - -

Legend: ✅ passed | ❌ failed | ⚪ skipped | 🚫 cancelled

Summary: Total: 32 | Passed: 32 | Failed: 0


Updated: 2026-04-03 16:45:40 UTC

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 DwarfParser constructor + parseEhFrame() path to parse linear .eh_frame / __eh_frame without an .eh_frame_hdr index.
  • Extends macOS Mach-O parsing to locate __eh_frame and populate CodeCache’s DWARF table; also adds Symbols::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.

@dd-octo-sts
Copy link
Copy Markdown

dd-octo-sts bot commented Apr 3, 2026

Scan-Build Report

User:runner@runnervmrg6be
Working Directory:/home/runner/work/java-profiler/java-profiler/ddprof-lib/src/test/make
Command Line:make -j4 all
Clang Version:Ubuntu clang version 18.1.3 (1ubuntu1)
Date:Fri Apr 3 14:40:28 2026

Bug Summary

Bug TypeQuantityDisplay?
All Bugs1
Logic error
Stack address stored into global variable1

Reports

Bug Group Bug Type ▾ File Function/Method Line Path Length
Logic errorStack address stored into global variablestackWalker.cppwalkVM84837

@jbachorik jbachorik force-pushed the jb/prof-14088 branch 3 times, most recently from dfe7b83 to 4466cfb Compare April 3, 2026 14:38
@jbachorik jbachorik marked this pull request as ready for review April 3, 2026 14:51
@jbachorik jbachorik requested a review from a team as a code owner April 3, 2026 14:51
@jbachorik jbachorik marked this pull request as draft April 3, 2026 15:43
jbachorik and others added 2 commits April 3, 2026 18:14
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>
@jbachorik jbachorik marked this pull request as ready for review April 3, 2026 16:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants