https://github.com/jroelofs updated https://github.com/llvm/llvm-project/pull/202772
>From 25829ccdbe4d045170328a97ba55f23600403e27 Mon Sep 17 00:00:00 2001 From: Jon Roelofs <[email protected]> Date: Tue, 9 Jun 2026 14:04:32 -0700 Subject: [PATCH 1/6] [libunwind][arm64e] Mach-O Support unwinding PAuth_LR frames Under PAuth_LR, compact unwind entries marked UNWIND_ARM64_MODE_FRAME_PAUTH_LR are signed with the PC of the pacibsppc at the start of the range. The compiler may emit those entries with UNWIND_IS_NOT_FUNCTION_START when the pacibsppc is not the first instruction in the function; the unwinder must scan backwards past such entries to find the actual function start (and its LSDA pointer). When unwinding a PAuth_LR frame, authenticate and re-sign using setIPPAuthLR(), which calls __builtin_ptrauth_auth_with_pc_and_resign when available, falling back to inline asm (autib171615 + pacib) for compilers that lack the builtin. To reduce the size of Compact Unwind entries for shrinkwrapped frames, new offset bits encode the distance in multiples of 4 bytes from the range start to the pacibsppc. The compiler emits paired FRAMELESS/FRAMELESS+PAUTH_LR entries that the linker merges into a single FRAME_PAUTH_LR | (offset/4) << 12 encoding. rdar://161907302&169746432&171118419 --- .../include/mach-o/compact_unwind_encoding.h | 13 ++- libunwind/src/CompactUnwinder.hpp | 20 ++++- libunwind/src/DwarfInstructions.hpp | 22 +++-- libunwind/src/Registers.hpp | 25 ++++++ libunwind/src/UnwindCursor.hpp | 83 ++++++++++++++----- 5 files changed, 131 insertions(+), 32 deletions(-) diff --git a/libunwind/include/mach-o/compact_unwind_encoding.h b/libunwind/include/mach-o/compact_unwind_encoding.h index c495b83c40b90..b6901cfb9055d 100644 --- a/libunwind/include/mach-o/compact_unwind_encoding.h +++ b/libunwind/include/mach-o/compact_unwind_encoding.h @@ -288,6 +288,10 @@ enum { UNWIND_ARM64_MODE_FRAMELESS = 0x02000000, UNWIND_ARM64_MODE_DWARF = 0x03000000, UNWIND_ARM64_MODE_FRAME = 0x04000000, + UNWIND_ARM64_MODE_FRAME_PAUTH_LR = 0x05000000, + + UNWIND_ARM64_PAUTH_LR_OFFSET_MASK = 0x00FFF000, + UNWIND_ARM64_PAUTH_LR_OFFSET_SHIFT = 12, UNWIND_ARM64_FRAME_X19_X20_PAIR = 0x00000001, UNWIND_ARM64_FRAME_X21_X22_PAIR = 0x00000002, @@ -323,8 +327,13 @@ enum { // This mode is never used in object files. It is only generated by the // linker in final linked images which have only DWARF unwind info for a // function. -// - +// For arm64e there is one more mode for compact unwind encoding: +// UNWIND_ARM64_MODE_FRAME_PAUTH_LR: +// An arm64e prologue, where LR is signed in the range with a `pacibsppc`. +// The UNWIND_ARM64_PAUTH_LR_OFFSET_MASK bits specify an unsigned positive +// offset (encoded as a multiple of 4 bytes) from the beginning of the range +// to the `pacibsppc`, with 0 indicating that the `pacibsppc` is the first +// instruction in the range. diff --git a/libunwind/src/CompactUnwinder.hpp b/libunwind/src/CompactUnwinder.hpp index 929f540b662b4..0daf76a373296 100644 --- a/libunwind/src/CompactUnwinder.hpp +++ b/libunwind/src/CompactUnwinder.hpp @@ -520,6 +520,7 @@ int CompactUnwinder_arm64<A>::stepWithCompactEncoding( A &addressSpace, Registers_arm64 ®isters) { switch (compactEncoding & UNWIND_ARM64_MODE_MASK) { case UNWIND_ARM64_MODE_FRAME: + case UNWIND_ARM64_MODE_FRAME_PAUTH_LR: return stepWithCompactEncodingFrame(compactEncoding, functionStart, addressSpace, registers); case UNWIND_ARM64_MODE_FRAMELESS: @@ -619,7 +620,7 @@ int CompactUnwinder_arm64<A>::stepWithCompactEncodingFrameless( template <typename A> int CompactUnwinder_arm64<A>::stepWithCompactEncodingFrame( - compact_unwind_encoding_t encoding, uint64_t, A &addressSpace, + compact_unwind_encoding_t encoding, uint64_t functionStart, A &addressSpace, Registers_arm64 ®isters) { Registers_arm64::reg_t savedRegisterLoc = registers.getFP() - 8; @@ -698,7 +699,22 @@ int CompactUnwinder_arm64<A>::stepWithCompactEncodingFrame( registers.setSP(fp + 16); // pop return address into pc - registers.setIP(addressSpace.get64(fp + 8)); + Registers_arm64::reg_t linkRegister = addressSpace.get64(fp + 8); + + // authenticate lr, if needed + if ((encoding & UNWIND_ARM64_MODE_MASK) == UNWIND_ARM64_MODE_FRAME_PAUTH_LR) { + // Offset from the beginning of the range to the pacibsppc, in words. + uint32_t offset = (encoding & UNWIND_ARM64_PAUTH_LR_OFFSET_MASK) >> + UNWIND_ARM64_PAUTH_LR_OFFSET_SHIFT; + + // Address of the pacibsppc + uint64_t pacibsppcAddr = functionStart + offset * 4; + + registers.setIPPAuthLR(linkRegister, pacibsppcAddr); + } else { + registers.setIP(linkRegister); + } + return UNW_STEP_SUCCESS; } diff --git a/libunwind/src/DwarfInstructions.hpp b/libunwind/src/DwarfInstructions.hpp index 165c4a99e9a92..62c4a71f87be3 100644 --- a/libunwind/src/DwarfInstructions.hpp +++ b/libunwind/src/DwarfInstructions.hpp @@ -302,16 +302,27 @@ int DwarfInstructions<A, R>::stepWithDwarf( isSignalFrame = cieInfo.isSignalFrame; -#if defined(_LIBUNWIND_TARGET_AARCH64) && \ - !defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING) +#if defined(_LIBUNWIND_TARGET_AARCH64) // There are two ways of return address signing: pac-ret (enabled via // -mbranch-protection=pac-ret) and ptrauth-returns (enabled as part of // Apple's arm64e or experimental pauthtest ABI on Linux). The code - // below handles signed RA for pac-ret, while ptrauth-returns uses - // different logic. + // below handles signed RA for ptrauth-returns, while pac-ret uses pacm + // instructions from the hint space. + // // TODO: unify logic for both cases, see // https://github.com/llvm/llvm-project/issues/160110 - // +#if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING) + if (isReturnAddressSignedWithPC(addressSpace, registers, cfa, prolog)) { + newRegisters.setIPPAuthLR(returnAddress, prolog.ptrAuthDiversifier); + } else { + newRegisters.setIP(returnAddress); + } + + // Simulate the step by replacing the register set with the new ones. + registers = newRegisters; + + return UNW_STEP_SUCCESS; +#else // If the target is aarch64 then the return address may have been signed // using the v8.3 pointer authentication extensions. The original // return address needs to be authenticated before the return address is @@ -353,6 +364,7 @@ int DwarfInstructions<A, R>::stepWithDwarf( #endif } #endif +#endif #if defined(_LIBUNWIND_IS_NATIVE_ONLY) && defined(_LIBUNWIND_TARGET_ARM) && \ defined(__ARM_FEATURE_PAUTH) diff --git a/libunwind/src/Registers.hpp b/libunwind/src/Registers.hpp index c88422a6d5f4f..abd0fca239a09 100644 --- a/libunwind/src/Registers.hpp +++ b/libunwind/src/Registers.hpp @@ -1917,6 +1917,31 @@ class _LIBUNWIND_HIDDEN Registers_arm64 { #endif _registers.__pc = value; } + __attribute__((target("pauth-lr"))) + void setIPPAuthLR(uint64_t value, uint64_t signing_pc) { +#if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING) +#if __has_builtin(__builtin_ptrauth_auth_with_pc_and_resign) + value = (uint64_t)ptrauth_auth_with_pc_and_resign( + (void *)value, + ptrauth_key_process_dependent_code, + (void *)getSP(), + (void *)signing_pc, + ptrauth_key_return_address, + &_registers.__pc); +#else + register uint64_t x17 __asm("x17") = value; + register uint64_t x16 __asm("x16") = getSP(); + register uint64_t x15 __asm("x15") = signing_pc; + uint64_t resignDisc = (uint64_t)&_registers.__pc; + asm("autib171615\n\t" + "pacib %0, %3" + : "+r"(x17) : "r"(x16), "r"(x15), "r"(resignDisc)); + value = x17; +#endif +#endif + _registers.__pc = value; + } + uint64_t getFP() const { return _registers.__fp; } void setFP(uint64_t value) { _registers.__fp = value; } diff --git a/libunwind/src/UnwindCursor.hpp b/libunwind/src/UnwindCursor.hpp index ff92c9e0a844a..468107f3ded49 100644 --- a/libunwind/src/UnwindCursor.hpp +++ b/libunwind/src/UnwindCursor.hpp @@ -1869,6 +1869,7 @@ bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection( // do a binary search of second level page index uint32_t encoding = 0; pint_t funcStart = 0; + pint_t rangeStart = 0; pint_t funcEnd = 0; pint_t lsda = 0; pint_t personality = 0; @@ -1908,21 +1909,32 @@ bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection( } } encoding = pageIndex.encoding(low); - funcStart = pageIndex.functionOffset(low) + sects.dso_base; + rangeStart = pageIndex.functionOffset(low) + sects.dso_base; + + // If UNWIND_IS_NOT_FUNCTION_START is set, walk backwards to find the actual function start. + funcStart = rangeStart; + if (encoding & UNWIND_IS_NOT_FUNCTION_START) { + uint32_t backIndex = low; + do { + --backIndex; + } while (backIndex > 0 && (pageIndex.encoding(backIndex) & UNWIND_IS_NOT_FUNCTION_START)); + funcStart = pageIndex.functionOffset(backIndex) + sects.dso_base; + } + if (pc < funcStart) { if (log) fprintf( stderr, - "\tpc not in table, pc=0x%llX, funcStart=0x%llX, funcEnd=0x%llX\n", - (uint64_t) pc, (uint64_t) funcStart, (uint64_t) funcEnd); + "\tpc not in table, pc=0x%llX, funcStart=0x%llX, rangeStart=0x%llX, funcEnd=0x%llX\n", + (uint64_t) pc, (uint64_t) funcStart, (uint64_t) rangeStart, (uint64_t) funcEnd); return false; } if (pc > funcEnd) { if (log) fprintf( stderr, - "\tpc not in table, pc=0x%llX, funcStart=0x%llX, funcEnd=0x%llX\n", - (uint64_t) pc, (uint64_t) funcStart, (uint64_t) funcEnd); + "\tpc not in table, pc=0x%llX, funcStart=0x%llX, rangeStart=0x%llX, funcEnd=0x%llX\n", + (uint64_t) pc, (uint64_t) funcStart, (uint64_t) rangeStart, (uint64_t) funcEnd); return false; } } else if (pageKind == UNWIND_SECOND_LEVEL_COMPRESSED) { @@ -1956,7 +1968,7 @@ bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection( high = mid; } } - funcStart = pageIndex.functionOffset(low) + firstLevelFunctionOffset + rangeStart = pageIndex.functionOffset(low) + firstLevelFunctionOffset + sects.dso_base; if (low < last) funcEnd = @@ -1964,11 +1976,40 @@ bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection( + sects.dso_base; else funcEnd = firstLevelNextPageFunctionOffset + sects.dso_base; + + auto encodingAtIndex = [&](uint32_t idx) -> uint32_t { + uint16_t encIdx = pageIndex.encodingIndex(idx); + if (encIdx < sectionHeader.commonEncodingsArrayCount()) { + return _addressSpace.get32( + sects.compact_unwind_section + + sectionHeader.commonEncodingsArraySectionOffset() + + encIdx * sizeof(uint32_t)); + } else { + uint16_t pageEncIdx = encIdx - (uint16_t)sectionHeader.commonEncodingsArrayCount(); + return _addressSpace.get32(secondLevelAddr + + pageHeader.encodingsPageOffset() + + pageEncIdx * sizeof(uint32_t)); + } + }; + + encoding = encodingAtIndex(low); + + // If UNWIND_IS_NOT_FUNCTION_START is set, walk backwards to find the actual function start. + funcStart = rangeStart; + if (encoding & UNWIND_IS_NOT_FUNCTION_START) { + uint32_t backIndex = low; + do { + --backIndex; + } while (backIndex > 0 && (encodingAtIndex(backIndex) & UNWIND_IS_NOT_FUNCTION_START)); + funcStart = pageIndex.functionOffset(backIndex) + firstLevelFunctionOffset + + sects.dso_base; + } + if (pc < funcStart) { _LIBUNWIND_DEBUG_LOG("malformed __unwind_info, pc=0x%llX " "not in second level compressed unwind table. " - "funcStart=0x%llX", - (uint64_t) pc, (uint64_t) funcStart); + "funcStart=0x%llX, rangeStart=0x%llX", + (uint64_t) pc, (uint64_t) funcStart, (uint64_t) rangeStart); return false; } if (pc > funcEnd) { @@ -1978,21 +2019,6 @@ bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection( (uint64_t) pc, (uint64_t) funcEnd); return false; } - uint16_t encodingIndex = pageIndex.encodingIndex(low); - if (encodingIndex < sectionHeader.commonEncodingsArrayCount()) { - // encoding is in common table in section header - encoding = _addressSpace.get32( - sects.compact_unwind_section + - sectionHeader.commonEncodingsArraySectionOffset() + - encodingIndex * sizeof(uint32_t)); - } else { - // encoding is in page specific table - uint16_t pageEncodingIndex = - encodingIndex - (uint16_t)sectionHeader.commonEncodingsArrayCount(); - encoding = _addressSpace.get32(secondLevelAddr + - pageHeader.encodingsPageOffset() + - pageEncodingIndex * sizeof(uint32_t)); - } } else { _LIBUNWIND_DEBUG_LOG( "malformed __unwind_info at 0x%0llX bad second level page", @@ -2069,7 +2095,18 @@ bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection( fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX), " "encoding=0x%08X, lsda=0x%08llX for funcStart=0x%llX\n", (uint64_t) pc, encoding, (uint64_t) lsda, (uint64_t) funcStart); + + // For ARM64 PAuth_LR frames, start_ip should be the pacibsppc address (rangeStart). + // For all other cases, start_ip should be the function start. +#if defined(_LIBUNWIND_TARGET_AARCH64) + if ((encoding & UNWIND_ARM64_MODE_MASK) == UNWIND_ARM64_MODE_FRAME_PAUTH_LR) { + _info.start_ip = rangeStart; + } else { + _info.start_ip = funcStart; + } +#else _info.start_ip = funcStart; +#endif _info.end_ip = funcEnd; _info.lsda = lsda; // We use memmove to copy the personality function as we have already manually >From b4bc71c4aebd6233b6b702b2db4eeda894ddf7e9 Mon Sep 17 00:00:00 2001 From: Jon Roelofs <[email protected]> Date: Tue, 9 Jun 2026 14:15:26 -0700 Subject: [PATCH 2/6] clang-format --- .../include/mach-o/compact_unwind_encoding.h | 45 ++++++++-------- libunwind/src/CompactUnwinder.hpp | 1 - libunwind/src/Registers.hpp | 15 +++--- libunwind/src/UnwindCursor.hpp | 52 +++++++++++-------- 4 files changed, 57 insertions(+), 56 deletions(-) diff --git a/libunwind/include/mach-o/compact_unwind_encoding.h b/libunwind/include/mach-o/compact_unwind_encoding.h index b6901cfb9055d..029b781287e02 100644 --- a/libunwind/include/mach-o/compact_unwind_encoding.h +++ b/libunwind/include/mach-o/compact_unwind_encoding.h @@ -284,27 +284,27 @@ enum { // 24-bits offset of DWARF FDE in __eh_frame section // enum { - UNWIND_ARM64_MODE_MASK = 0x0F000000, - UNWIND_ARM64_MODE_FRAMELESS = 0x02000000, - UNWIND_ARM64_MODE_DWARF = 0x03000000, - UNWIND_ARM64_MODE_FRAME = 0x04000000, - UNWIND_ARM64_MODE_FRAME_PAUTH_LR = 0x05000000, - - UNWIND_ARM64_PAUTH_LR_OFFSET_MASK = 0x00FFF000, - UNWIND_ARM64_PAUTH_LR_OFFSET_SHIFT = 12, - - UNWIND_ARM64_FRAME_X19_X20_PAIR = 0x00000001, - UNWIND_ARM64_FRAME_X21_X22_PAIR = 0x00000002, - UNWIND_ARM64_FRAME_X23_X24_PAIR = 0x00000004, - UNWIND_ARM64_FRAME_X25_X26_PAIR = 0x00000008, - UNWIND_ARM64_FRAME_X27_X28_PAIR = 0x00000010, - UNWIND_ARM64_FRAME_D8_D9_PAIR = 0x00000100, - UNWIND_ARM64_FRAME_D10_D11_PAIR = 0x00000200, - UNWIND_ARM64_FRAME_D12_D13_PAIR = 0x00000400, - UNWIND_ARM64_FRAME_D14_D15_PAIR = 0x00000800, - - UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK = 0x00FFF000, - UNWIND_ARM64_DWARF_SECTION_OFFSET = 0x00FFFFFF, + UNWIND_ARM64_MODE_MASK = 0x0F000000, + UNWIND_ARM64_MODE_FRAMELESS = 0x02000000, + UNWIND_ARM64_MODE_DWARF = 0x03000000, + UNWIND_ARM64_MODE_FRAME = 0x04000000, + UNWIND_ARM64_MODE_FRAME_PAUTH_LR = 0x05000000, + + UNWIND_ARM64_PAUTH_LR_OFFSET_MASK = 0x00FFF000, + UNWIND_ARM64_PAUTH_LR_OFFSET_SHIFT = 12, + + UNWIND_ARM64_FRAME_X19_X20_PAIR = 0x00000001, + UNWIND_ARM64_FRAME_X21_X22_PAIR = 0x00000002, + UNWIND_ARM64_FRAME_X23_X24_PAIR = 0x00000004, + UNWIND_ARM64_FRAME_X25_X26_PAIR = 0x00000008, + UNWIND_ARM64_FRAME_X27_X28_PAIR = 0x00000010, + UNWIND_ARM64_FRAME_D8_D9_PAIR = 0x00000100, + UNWIND_ARM64_FRAME_D10_D11_PAIR = 0x00000200, + UNWIND_ARM64_FRAME_D12_D13_PAIR = 0x00000400, + UNWIND_ARM64_FRAME_D14_D15_PAIR = 0x00000800, + + UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK = 0x00FFF000, + UNWIND_ARM64_DWARF_SECTION_OFFSET = 0x00FFFFFF, }; // For arm64 there are three modes for the compact unwind encoding: // UNWIND_ARM64_MODE_FRAME: @@ -335,9 +335,6 @@ enum { // to the `pacibsppc`, with 0 indicating that the `pacibsppc` is the first // instruction in the range. - - - //////////////////////////////////////////////////////////////////////////////// // // Relocatable Object Files: __LD,__compact_unwind diff --git a/libunwind/src/CompactUnwinder.hpp b/libunwind/src/CompactUnwinder.hpp index 0daf76a373296..bc9c569a8ccb9 100644 --- a/libunwind/src/CompactUnwinder.hpp +++ b/libunwind/src/CompactUnwinder.hpp @@ -715,7 +715,6 @@ int CompactUnwinder_arm64<A>::stepWithCompactEncodingFrame( registers.setIP(linkRegister); } - return UNW_STEP_SUCCESS; } #endif // _LIBUNWIND_TARGET_AARCH64 diff --git a/libunwind/src/Registers.hpp b/libunwind/src/Registers.hpp index abd0fca239a09..1dce396d111d3 100644 --- a/libunwind/src/Registers.hpp +++ b/libunwind/src/Registers.hpp @@ -1917,17 +1917,13 @@ class _LIBUNWIND_HIDDEN Registers_arm64 { #endif _registers.__pc = value; } - __attribute__((target("pauth-lr"))) - void setIPPAuthLR(uint64_t value, uint64_t signing_pc) { + __attribute__((target("pauth-lr"))) void setIPPAuthLR(uint64_t value, + uint64_t signing_pc) { #if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING) #if __has_builtin(__builtin_ptrauth_auth_with_pc_and_resign) value = (uint64_t)ptrauth_auth_with_pc_and_resign( - (void *)value, - ptrauth_key_process_dependent_code, - (void *)getSP(), - (void *)signing_pc, - ptrauth_key_return_address, - &_registers.__pc); + (void *)value, ptrauth_key_process_dependent_code, (void *)getSP(), + (void *)signing_pc, ptrauth_key_return_address, &_registers.__pc); #else register uint64_t x17 __asm("x17") = value; register uint64_t x16 __asm("x16") = getSP(); @@ -1935,7 +1931,8 @@ class _LIBUNWIND_HIDDEN Registers_arm64 { uint64_t resignDisc = (uint64_t)&_registers.__pc; asm("autib171615\n\t" "pacib %0, %3" - : "+r"(x17) : "r"(x16), "r"(x15), "r"(resignDisc)); + : "+r"(x17) + : "r"(x16), "r"(x15), "r"(resignDisc)); value = x17; #endif #endif diff --git a/libunwind/src/UnwindCursor.hpp b/libunwind/src/UnwindCursor.hpp index 468107f3ded49..9e39b6f8b6e7a 100644 --- a/libunwind/src/UnwindCursor.hpp +++ b/libunwind/src/UnwindCursor.hpp @@ -1911,30 +1911,34 @@ bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection( encoding = pageIndex.encoding(low); rangeStart = pageIndex.functionOffset(low) + sects.dso_base; - // If UNWIND_IS_NOT_FUNCTION_START is set, walk backwards to find the actual function start. + // If UNWIND_IS_NOT_FUNCTION_START is set, walk backwards to find the actual + // function start. funcStart = rangeStart; if (encoding & UNWIND_IS_NOT_FUNCTION_START) { uint32_t backIndex = low; do { --backIndex; - } while (backIndex > 0 && (pageIndex.encoding(backIndex) & UNWIND_IS_NOT_FUNCTION_START)); + } while (backIndex > 0 && + (pageIndex.encoding(backIndex) & UNWIND_IS_NOT_FUNCTION_START)); funcStart = pageIndex.functionOffset(backIndex) + sects.dso_base; } if (pc < funcStart) { if (log) - fprintf( - stderr, - "\tpc not in table, pc=0x%llX, funcStart=0x%llX, rangeStart=0x%llX, funcEnd=0x%llX\n", - (uint64_t) pc, (uint64_t) funcStart, (uint64_t) rangeStart, (uint64_t) funcEnd); + fprintf(stderr, + "\tpc not in table, pc=0x%llX, funcStart=0x%llX, " + "rangeStart=0x%llX, funcEnd=0x%llX\n", + (uint64_t)pc, (uint64_t)funcStart, (uint64_t)rangeStart, + (uint64_t)funcEnd); return false; } if (pc > funcEnd) { if (log) - fprintf( - stderr, - "\tpc not in table, pc=0x%llX, funcStart=0x%llX, rangeStart=0x%llX, funcEnd=0x%llX\n", - (uint64_t) pc, (uint64_t) funcStart, (uint64_t) rangeStart, (uint64_t) funcEnd); + fprintf(stderr, + "\tpc not in table, pc=0x%llX, funcStart=0x%llX, " + "rangeStart=0x%llX, funcEnd=0x%llX\n", + (uint64_t)pc, (uint64_t)funcStart, (uint64_t)rangeStart, + (uint64_t)funcEnd); return false; } } else if (pageKind == UNWIND_SECOND_LEVEL_COMPRESSED) { @@ -1968,8 +1972,8 @@ bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection( high = mid; } } - rangeStart = pageIndex.functionOffset(low) + firstLevelFunctionOffset - + sects.dso_base; + rangeStart = pageIndex.functionOffset(low) + firstLevelFunctionOffset + + sects.dso_base; if (low < last) funcEnd = pageIndex.functionOffset(low + 1) + firstLevelFunctionOffset @@ -1985,31 +1989,35 @@ bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection( sectionHeader.commonEncodingsArraySectionOffset() + encIdx * sizeof(uint32_t)); } else { - uint16_t pageEncIdx = encIdx - (uint16_t)sectionHeader.commonEncodingsArrayCount(); + uint16_t pageEncIdx = + encIdx - (uint16_t)sectionHeader.commonEncodingsArrayCount(); return _addressSpace.get32(secondLevelAddr + - pageHeader.encodingsPageOffset() + - pageEncIdx * sizeof(uint32_t)); + pageHeader.encodingsPageOffset() + + pageEncIdx * sizeof(uint32_t)); } }; encoding = encodingAtIndex(low); - // If UNWIND_IS_NOT_FUNCTION_START is set, walk backwards to find the actual function start. + // If UNWIND_IS_NOT_FUNCTION_START is set, walk backwards to find the actual + // function start. funcStart = rangeStart; if (encoding & UNWIND_IS_NOT_FUNCTION_START) { uint32_t backIndex = low; do { --backIndex; - } while (backIndex > 0 && (encodingAtIndex(backIndex) & UNWIND_IS_NOT_FUNCTION_START)); - funcStart = pageIndex.functionOffset(backIndex) + firstLevelFunctionOffset - + sects.dso_base; + } while (backIndex > 0 && + (encodingAtIndex(backIndex) & UNWIND_IS_NOT_FUNCTION_START)); + funcStart = pageIndex.functionOffset(backIndex) + + firstLevelFunctionOffset + sects.dso_base; } if (pc < funcStart) { _LIBUNWIND_DEBUG_LOG("malformed __unwind_info, pc=0x%llX " "not in second level compressed unwind table. " "funcStart=0x%llX, rangeStart=0x%llX", - (uint64_t) pc, (uint64_t) funcStart, (uint64_t) rangeStart); + (uint64_t)pc, (uint64_t)funcStart, + (uint64_t)rangeStart); return false; } if (pc > funcEnd) { @@ -2096,8 +2104,8 @@ bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection( "encoding=0x%08X, lsda=0x%08llX for funcStart=0x%llX\n", (uint64_t) pc, encoding, (uint64_t) lsda, (uint64_t) funcStart); - // For ARM64 PAuth_LR frames, start_ip should be the pacibsppc address (rangeStart). - // For all other cases, start_ip should be the function start. + // For ARM64 PAuth_LR frames, start_ip should be the pacibsppc address + // (rangeStart). For all other cases, start_ip should be the function start. #if defined(_LIBUNWIND_TARGET_AARCH64) if ((encoding & UNWIND_ARM64_MODE_MASK) == UNWIND_ARM64_MODE_FRAME_PAUTH_LR) { _info.start_ip = rangeStart; >From 92f161ac8e9608b7756b06f1851ebe428b557320 Mon Sep 17 00:00:00 2001 From: Jon Roelofs <[email protected]> Date: Thu, 11 Jun 2026 16:29:12 -0700 Subject: [PATCH 3/6] clang-format --- libunwind/src/UnwindCursor.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libunwind/src/UnwindCursor.hpp b/libunwind/src/UnwindCursor.hpp index 9e39b6f8b6e7a..8707d0df09300 100644 --- a/libunwind/src/UnwindCursor.hpp +++ b/libunwind/src/UnwindCursor.hpp @@ -2104,8 +2104,8 @@ bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection( "encoding=0x%08X, lsda=0x%08llX for funcStart=0x%llX\n", (uint64_t) pc, encoding, (uint64_t) lsda, (uint64_t) funcStart); - // For ARM64 PAuth_LR frames, start_ip should be the pacibsppc address - // (rangeStart). For all other cases, start_ip should be the function start. + // For ARM64 PAuth_LR frames, start_ip should be the pacibsppc address + // (rangeStart). For all other cases, start_ip should be the function start. #if defined(_LIBUNWIND_TARGET_AARCH64) if ((encoding & UNWIND_ARM64_MODE_MASK) == UNWIND_ARM64_MODE_FRAME_PAUTH_LR) { _info.start_ip = rangeStart; >From 7449cc4be758b9f8ad8998cde78e1491679beaa5 Mon Sep 17 00:00:00 2001 From: Jon Roelofs <[email protected]> Date: Fri, 12 Jun 2026 14:16:52 -0700 Subject: [PATCH 4/6] un-clang-format an enum --- .../include/mach-o/compact_unwind_encoding.h | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/libunwind/include/mach-o/compact_unwind_encoding.h b/libunwind/include/mach-o/compact_unwind_encoding.h index 029b781287e02..214acc0330d59 100644 --- a/libunwind/include/mach-o/compact_unwind_encoding.h +++ b/libunwind/include/mach-o/compact_unwind_encoding.h @@ -284,27 +284,27 @@ enum { // 24-bits offset of DWARF FDE in __eh_frame section // enum { - UNWIND_ARM64_MODE_MASK = 0x0F000000, - UNWIND_ARM64_MODE_FRAMELESS = 0x02000000, - UNWIND_ARM64_MODE_DWARF = 0x03000000, - UNWIND_ARM64_MODE_FRAME = 0x04000000, - UNWIND_ARM64_MODE_FRAME_PAUTH_LR = 0x05000000, - - UNWIND_ARM64_PAUTH_LR_OFFSET_MASK = 0x00FFF000, - UNWIND_ARM64_PAUTH_LR_OFFSET_SHIFT = 12, - - UNWIND_ARM64_FRAME_X19_X20_PAIR = 0x00000001, - UNWIND_ARM64_FRAME_X21_X22_PAIR = 0x00000002, - UNWIND_ARM64_FRAME_X23_X24_PAIR = 0x00000004, - UNWIND_ARM64_FRAME_X25_X26_PAIR = 0x00000008, - UNWIND_ARM64_FRAME_X27_X28_PAIR = 0x00000010, - UNWIND_ARM64_FRAME_D8_D9_PAIR = 0x00000100, - UNWIND_ARM64_FRAME_D10_D11_PAIR = 0x00000200, - UNWIND_ARM64_FRAME_D12_D13_PAIR = 0x00000400, - UNWIND_ARM64_FRAME_D14_D15_PAIR = 0x00000800, - - UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK = 0x00FFF000, - UNWIND_ARM64_DWARF_SECTION_OFFSET = 0x00FFFFFF, + UNWIND_ARM64_MODE_MASK = 0x0F000000, + UNWIND_ARM64_MODE_FRAMELESS = 0x02000000, + UNWIND_ARM64_MODE_DWARF = 0x03000000, + UNWIND_ARM64_MODE_FRAME = 0x04000000, + UNWIND_ARM64_MODE_FRAME_PAUTH_LR = 0x05000000, + + UNWIND_ARM64_PAUTH_LR_OFFSET_MASK = 0x00FFF000, + UNWIND_ARM64_PAUTH_LR_OFFSET_SHIFT = 12, + + UNWIND_ARM64_FRAME_X19_X20_PAIR = 0x00000001, + UNWIND_ARM64_FRAME_X21_X22_PAIR = 0x00000002, + UNWIND_ARM64_FRAME_X23_X24_PAIR = 0x00000004, + UNWIND_ARM64_FRAME_X25_X26_PAIR = 0x00000008, + UNWIND_ARM64_FRAME_X27_X28_PAIR = 0x00000010, + UNWIND_ARM64_FRAME_D8_D9_PAIR = 0x00000100, + UNWIND_ARM64_FRAME_D10_D11_PAIR = 0x00000200, + UNWIND_ARM64_FRAME_D12_D13_PAIR = 0x00000400, + UNWIND_ARM64_FRAME_D14_D15_PAIR = 0x00000800, + + UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK = 0x00FFF000, + UNWIND_ARM64_DWARF_SECTION_OFFSET = 0x00FFFFFF, }; // For arm64 there are three modes for the compact unwind encoding: // UNWIND_ARM64_MODE_FRAME: >From f17e1540821efe359db1f75dd5d5137c1b3a75e2 Mon Sep 17 00:00:00 2001 From: Jon Roelofs <[email protected]> Date: Fri, 12 Jun 2026 16:29:01 -0700 Subject: [PATCH 5/6] tell clang-format to go away --- libunwind/include/mach-o/compact_unwind_encoding.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/libunwind/include/mach-o/compact_unwind_encoding.h b/libunwind/include/mach-o/compact_unwind_encoding.h index 214acc0330d59..d1770864cf647 100644 --- a/libunwind/include/mach-o/compact_unwind_encoding.h +++ b/libunwind/include/mach-o/compact_unwind_encoding.h @@ -41,11 +41,13 @@ typedef uint32_t compact_unwind_encoding_t; // architecture independent bits +// clang-format off enum { UNWIND_IS_NOT_FUNCTION_START = 0x80000000, UNWIND_HAS_LSDA = 0x40000000, UNWIND_PERSONALITY_MASK = 0x30000000, }; +// clang-format on @@ -67,6 +69,7 @@ enum { // 3-bits register count // 10-bits register permutation // +// clang-format off enum { UNWIND_X86_MODE_MASK = 0x0F000000, UNWIND_X86_MODE_EBP_FRAME = 0x01000000, @@ -84,7 +87,9 @@ enum { UNWIND_X86_DWARF_SECTION_OFFSET = 0x00FFFFFF, }; +// clang-format on +// clang-format off enum { UNWIND_X86_REG_NONE = 0, UNWIND_X86_REG_EBX = 1, @@ -94,6 +99,7 @@ enum { UNWIND_X86_REG_ESI = 5, UNWIND_X86_REG_EBP = 6, }; +// clang-format on // // For x86 there are four modes for the compact unwind encoding: @@ -202,6 +208,7 @@ enum { // 3-bits register count // 10-bits register permutation // +// clang-format off enum { UNWIND_X86_64_MODE_MASK = 0x0F000000, UNWIND_X86_64_MODE_RBP_FRAME = 0x01000000, @@ -219,7 +226,9 @@ enum { UNWIND_X86_64_DWARF_SECTION_OFFSET = 0x00FFFFFF, }; +// clang-format on +// clang-format off enum { UNWIND_X86_64_REG_NONE = 0, UNWIND_X86_64_REG_RBX = 1, @@ -229,6 +238,8 @@ enum { UNWIND_X86_64_REG_R15 = 5, UNWIND_X86_64_REG_RBP = 6, }; +// clang-format on + // // For x86_64 there are four modes for the compact unwind encoding: // UNWIND_X86_64_MODE_RBP_FRAME: @@ -283,6 +294,7 @@ enum { // DWARF: // 24-bits offset of DWARF FDE in __eh_frame section // +// clang-format off enum { UNWIND_ARM64_MODE_MASK = 0x0F000000, UNWIND_ARM64_MODE_FRAMELESS = 0x02000000, @@ -306,6 +318,8 @@ enum { UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK = 0x00FFF000, UNWIND_ARM64_DWARF_SECTION_OFFSET = 0x00FFFFFF, }; +// clang-format on +// // For arm64 there are three modes for the compact unwind encoding: // UNWIND_ARM64_MODE_FRAME: // This is a standard arm64 prolog where FP/LR are immediately pushed on the >From dfbfbaa341b8a4efae73018924f0efd64e9a87ae Mon Sep 17 00:00:00 2001 From: Jon Roelofs <[email protected]> Date: Mon, 15 Jun 2026 10:51:10 -0700 Subject: [PATCH 6/6] remove blank lines that clang-format insists on --- libunwind/include/mach-o/compact_unwind_encoding.h | 8 -------- 1 file changed, 8 deletions(-) diff --git a/libunwind/include/mach-o/compact_unwind_encoding.h b/libunwind/include/mach-o/compact_unwind_encoding.h index d1770864cf647..2bfa4dd7b13a1 100644 --- a/libunwind/include/mach-o/compact_unwind_encoding.h +++ b/libunwind/include/mach-o/compact_unwind_encoding.h @@ -39,7 +39,6 @@ // typedef uint32_t compact_unwind_encoding_t; - // architecture independent bits // clang-format off enum { @@ -49,9 +48,6 @@ enum { }; // clang-format on - - - // // x86 // @@ -188,9 +184,6 @@ enum { //} // - - - // // x86_64 // @@ -278,7 +271,6 @@ enum { // function. // - // ARM64 // // 1-bit: start _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
