Skip to content

Commit 5a4b9cb

Browse files
jbachorikclaude
andcommitted
Set clang frame layout as default for macOS aarch64
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent e279f4f commit 5a4b9cb

4 files changed

Lines changed: 25 additions & 10 deletions

File tree

ddprof-lib/src/main/cpp/dwarf.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,17 @@ struct FrameDesc {
8383
static FrameDesc default_clang_frame;
8484
static FrameDesc no_dwarf_frame;
8585

86+
// Best-guess fallback frame layout when a PC doesn't map to any known library.
87+
// Per-library detection overrides this: on macOS via __eh_frame section presence,
88+
// on Linux via DwarfParser::detectedDefaultFrame().
89+
static const FrameDesc& fallback_default_frame() {
90+
#if defined(__APPLE__) && defined(__aarch64__)
91+
return default_clang_frame;
92+
#else
93+
return default_frame;
94+
#endif
95+
}
96+
8697
static int comparator(const void* p1, const void* p2) {
8798
FrameDesc* fd1 = (FrameDesc*)p1;
8899
FrameDesc* fd2 = (FrameDesc*)p2;

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

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -158,11 +158,7 @@ int StackWalker::walkDwarf(void* ucontext, const void** callchain, int max_depth
158158

159159
uintptr_t prev_sp = sp;
160160
CodeCache* cc = profiler->findLibraryByAddress(pc);
161-
#if defined(__APPLE__) && defined(__aarch64__)
162-
FrameDesc f = cc != NULL ? cc->findFrameDesc(pc) : FrameDesc::default_clang_frame;
163-
#else
164-
FrameDesc f = cc != NULL ? cc->findFrameDesc(pc) : FrameDesc::default_frame;
165-
#endif
161+
FrameDesc f = cc != NULL ? cc->findFrameDesc(pc) : FrameDesc::fallback_default_frame();
166162

167163
u8 cfa_reg = (u8)f.cfa;
168164
int cfa_off = f.cfa >> 8;
@@ -698,11 +694,7 @@ __attribute__((no_sanitize("address"))) int StackWalker::walkVM(void* ucontext,
698694
dwarf_unwind:
699695
uintptr_t prev_sp = sp;
700696
CodeCache* cc = profiler->findLibraryByAddress(pc);
701-
#if defined(__APPLE__) && defined(__aarch64__)
702-
FrameDesc f = cc != NULL ? cc->findFrameDesc(pc) : FrameDesc::default_clang_frame;
703-
#else
704-
FrameDesc f = cc != NULL ? cc->findFrameDesc(pc) : FrameDesc::default_frame;
705-
#endif
697+
FrameDesc f = cc != NULL ? cc->findFrameDesc(pc) : FrameDesc::fallback_default_frame();
706698

707699
u8 cfa_reg = (u8)f.cfa;
708700
int cfa_off = f.cfa >> 8;

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,9 @@ void ElfParser::parseDwarfInfo() {
604604
ElfProgramHeader* eh_frame_hdr = findProgramHeader(PT_GNU_EH_FRAME);
605605
if (eh_frame_hdr != NULL) {
606606
if (eh_frame_hdr->p_vaddr != 0) {
607+
// Parse per-PC frame descriptions and detect per-library default frame layout.
608+
// On aarch64 this distinguishes GCC (LINKED_FRAME_SIZE=0) from clang
609+
// (LINKED_FRAME_CLANG_SIZE=16) conventions for each shared library.
607610
DwarfParser dwarf(_cc->name(), _base, at(eh_frame_hdr));
608611
_cc->setDwarfTable(dwarf.table(), dwarf.count(), dwarf.detectedDefaultFrame());
609612
} else if (strcmp(_cc->name(), "[vdso]") == 0) {

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <mach-o/loader.h>
1313
#include <mach-o/nlist.h>
1414
#include "symbols.h"
15+
#include "dwarf.h"
1516
#include "log.h"
1617

1718
UnloadProtection::UnloadProtection(const CodeCache *cc) {
@@ -138,13 +139,15 @@ class MachOParser {
138139
const symtab_command* symtab = NULL;
139140
const dysymtab_command* dysymtab = NULL;
140141
const section_64* stubs_section = NULL;
142+
bool has_eh_frame = false;
141143

142144
for (uint32_t i = 0; i < header->ncmds; i++) {
143145
if (lc->cmd == LC_SEGMENT_64) {
144146
const segment_command_64* sc = (const segment_command_64*)lc;
145147
if (strcmp(sc->segname, "__TEXT") == 0) {
146148
_cc->updateBounds(_image_base, add(_image_base, sc->vmsize));
147149
stubs_section = findSection(sc, "__stubs");
150+
has_eh_frame = findSection(sc, "__eh_frame") != NULL;
148151
} else if (strcmp(sc->segname, "__LINKEDIT") == 0) {
149152
link_base = _vmaddr_slide + sc->vmaddr - sc->fileoff;
150153
} else if (strcmp(sc->segname, "__DATA") == 0 || strcmp(sc->segname, "__DATA_CONST") == 0) {
@@ -168,6 +171,12 @@ class MachOParser {
168171
}
169172
}
170173

174+
// GCC emits __eh_frame (DWARF CFI); clang emits __unwind_info (compact unwind).
175+
// On aarch64, GCC and clang use different frame layouts, so detecting the
176+
// compiler matters. On x86_64 both use the same layout (no-op distinction).
177+
const FrameDesc& frame = has_eh_frame ? FrameDesc::default_frame : FrameDesc::fallback_default_frame();
178+
_cc->setDwarfTable(NULL, 0, frame);
179+
171180
return true;
172181
}
173182
};

0 commit comments

Comments
 (0)