https://github.com/oontvoo updated https://github.com/llvm/llvm-project/pull/216895
>From 48bc3a4580675833dc69afcb8d6a4328644b6ce2 Mon Sep 17 00:00:00 2001 From: Vy Nguyen <[email protected]> Date: Thu, 14 May 2026 15:36:16 -0400 Subject: [PATCH 1/8] [codegen]Ensure __builtin_trap() has an unreachable --- clang/lib/CodeGen/CGBuiltin.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 20f99f489c55f..678985ebb55e1 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -4022,6 +4022,12 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, } case Builtin::BI__builtin_trap: EmitTrapCall(Intrinsic::trap); + if (Builder.GetInsertBlock()) { + Builder.CreateUnreachable(); + // Dummy block for the ret void - it'll be clened up + llvm::BasicBlock *DeadBB = createBasicBlock("dead.trap"); + EmitBlock(DeadBB); + } return RValue::get(nullptr); case Builtin::BI__builtin_verbose_trap: { llvm::DILocation *TrapLocation = Builder.getCurrentDebugLocation(); >From 8d9683bb815903f607fef8bb372f1033f1128ea8 Mon Sep 17 00:00:00 2001 From: Vy Nguyen <[email protected]> Date: Mon, 17 Aug 2026 21:17:55 -0400 Subject: [PATCH 2/8] [lld-macho]Allow folding functions with the same Dwarf FDE This is done by normalising the embedded reloc data during ICF comparison and hashing. (modified version of pr/213778) --- lld/MachO/ICF.cpp | 76 +++++++++++++++++++++----------- lld/test/MachO/fold-dwarf-lsda.s | 6 +-- 2 files changed, 52 insertions(+), 30 deletions(-) diff --git a/lld/MachO/ICF.cpp b/lld/MachO/ICF.cpp index 8e9eb1d4e7950..60df53327b834 100644 --- a/lld/MachO/ICF.cpp +++ b/lld/MachO/ICF.cpp @@ -91,6 +91,32 @@ ICF::ICF(std::vector<ConcatInputSection *> &inputs) { // FIXME(gkm): implement keep-unique attributes // FIXME(gkm): implement address-significance tables for MachO object files +static bool isFoldableWithAddendsRemoved(const ConcatInputSection *isec) { + return isCfStringSection(isec) || isClassRefsSection(isec) || + isSelRefsSection(isec) || isEhFrameSection(isec); +} + +// Make a normalized copy of a section's bytes by zeroing out the embedded relocs. +// Return it in the given &buf +static void getNormalizedData(const ConcatInputSection *isec, + SmallVectorImpl<uint8_t> &buf) { + buf.assign(isec->data.begin(), isec->data.end()); + for (const Relocation &r : isec->relocs) + target->relocateOne(buf.data() + r.offset, r, /*va=*/0, /*relocVA=*/0); +} + +static bool compareData(const ConcatInputSection *ia, + const ConcatInputSection *ib) { + if (ia->data == ib->data) + return true; + if (!isFoldableWithAddendsRemoved(ia)) + return false; + SmallVector<uint8_t, 64> bufA, bufB; + getNormalizedData(ia, bufA); + getNormalizedData(ib, bufB); + return bufA == bufB; +} + // Compare "non-moving" parts of two ConcatInputSections, namely everything // except references to other ConcatInputSections. bool ICF::equalsConstant(const ConcatInputSection *ia, @@ -100,7 +126,7 @@ bool ICF::equalsConstant(const ConcatInputSection *ia, // We can only fold within the same OutputSection. if (ia->parent != ib->parent) return false; - if (ia->data != ib->data) + if (!compareData(ia, ib)) return false; auto f = [](const Relocation &ra, const Relocation &rb) { if (ra.type != rb.type) @@ -573,9 +599,9 @@ void macho::foldIdenticalSections(bool onlyCfStrings) { // Reset the thunk counter for each run of ICF. icfThunkCounter = 0; for (ConcatInputSection *isec : inputSections) { - bool isFoldableWithAddendsRemoved = isCfStringSection(isec) || - isClassRefsSection(isec) || - isSelRefsSection(isec); + bool isUnconditionallyCoalescedData = isCfStringSection(isec) || + isClassRefsSection(isec) || + isSelRefsSection(isec); // NOTE: __objc_selrefs is typically marked as no_dead_strip by MC, but we // can still fold it. bool hasFoldableFlags = (isSelRefsSection(isec) || @@ -596,7 +622,6 @@ void macho::foldIdenticalSections(bool onlyCfStrings) { // Happens to match isFoldableWithAddendsRemoved today, but expresses a // different intent (ld64's coalescing semantics, not addend stripping), // so the two may diverge as either list grows. - bool isUnconditionallyCoalescedData = isFoldableWithAddendsRemoved; bool isSafeThunksCode = config->icfLevel == ICFLevel::safe_thunks && isCodeSec; bool keepUniqueAllowsFolding = @@ -604,7 +629,7 @@ void macho::foldIdenticalSections(bool onlyCfStrings) { // FIXME: consider non-code __text sections as foldable? bool isFoldable = (!onlyCfStrings || isCfStringSection(isec)) && - (isCodeSec || isFoldableWithAddendsRemoved || + (isCodeSec || isFoldableWithAddendsRemoved(isec) || isGccExceptTabSection(isec)) && keepUniqueAllowsFolding && !isec->hasAltEntry && !isec->shouldOmitFromOutput() && hasFoldableFlags; @@ -613,32 +638,33 @@ void macho::foldIdenticalSections(bool onlyCfStrings) { for (Defined *d : isec->symbols) if (d->unwindEntry()) foldable.push_back(d->unwindEntry()); - - // Some sections have embedded addends that foil ICF's hashing / equality - // checks. (We can ignore embedded addends when doing ICF because the same - // information gets recorded in our Reloc structs.) We therefore create a - // mutable copy of the section data and zero out the embedded addends - // before performing any hashing / equality checks. - if (isFoldableWithAddendsRemoved) { - // We have to do this copying serially as the BumpPtrAllocator is not - // thread-safe. FIXME: Make a thread-safe allocator. - MutableArrayRef<uint8_t> copy = isec->data.copy(bAlloc()); - for (const Relocation &r : isec->relocs) - target->relocateOne(copy.data() + r.offset, r, /*va=*/0, - /*relocVA=*/0); - isec->data = copy; - } - } else if (!isEhFrameSection(isec)) { - // EH frames are gathered as foldables from unwindEntry above; give a - // unique ID to everything else. + } else if (isEhFrameSection(isec)) { + // __eh_frame contains two types of records: FDEs and CIEs. + // Functions point to FDEs, which are already collected above via unwindEntry(). + // CIEs are shared headers and are not attached to individual functions. + // Collect only CIEs here so they can also be hashed and deduplicated. + auto *obj = dyn_cast_or_null<ObjFile>(isec->getFile()); + if (!onlyCfStrings && obj && !obj->fdes.contains(isec) && + !isec->shouldOmitFromOutput()) + foldable.push_back(isec); + } else { + // Give a unique ID to everything else. isec->icfEqClass[0] = ++icfUniqueID; } } parallelForEach(foldable, [](ConcatInputSection *isec) { assert(isec->icfEqClass[0] == 0); // don't overwrite a unique ID! + uint64_t hash; + if (isFoldableWithAddendsRemoved(isec)) { + SmallVector<uint8_t, 64> stackBuf; + getNormalizedData(isec, stackBuf); + hash = xxh3_64bits(stackBuf); + } else { + hash = xxh3_64bits(isec->data); + } // Turn-on the top bit to guarantee that valid hashes have no collisions // with the small-integer unique IDs for ICF-ineligible sections - isec->icfEqClass[0] = xxh3_64bits(isec->data) | (1ull << 31); + isec->icfEqClass[0] = hash | (1ull << 31); }); // Now that every input section is either hashed or marked as unique, run the // segregation algorithm to detect foldable subsections. diff --git a/lld/test/MachO/fold-dwarf-lsda.s b/lld/test/MachO/fold-dwarf-lsda.s index e651fa81b8b7a..0451bc8aae266 100644 --- a/lld/test/MachO/fold-dwarf-lsda.s +++ b/lld/test/MachO/fold-dwarf-lsda.s @@ -22,7 +22,7 @@ # POST: [[#%x,EXCEPT_ADDR:]] l O __TEXT,__gcc_except_tab GCC_except_table0 # POST: [[#%x,EXCEPT_ADDR]] l O __TEXT,__gcc_except_tab GCC_except_table1 # POST: [[#%.16x,F0_ADDR:]] g F __TEXT,__text _f0 -# POST: [[#%.16x,F1_ADDR:]] g F __TEXT,__text _f1 +# POST: [[#%.16x,F0_ADDR]] g F __TEXT,__text _f1 # POST: [[#%.16x,G_ADDR:]] g F __TEXT,__text _g # POST-LABEL: .eh_frame contents: @@ -32,10 +32,6 @@ # POST: Format: DWARF32 # POST: LSDA Address: [[#%.16x,EXCEPT_ADDR]] -# POST: {{.*}} FDE cie={{.+}} pc=[[#%x,F1_ADDR]]...{{.+}} -# POST Format: DWARF32 -# POST LSDA Address: [[#%.16x,EXCEPT_ADDR]] - .section __TEXT,__text,regular,pure_instructions .globl _f0 _f0: >From d8dcc9b5c3e50b2cee6dbc50187670367b7e99ff Mon Sep 17 00:00:00 2001 From: Vy Nguyen <[email protected]> Date: Tue, 18 Aug 2026 11:35:45 -0400 Subject: [PATCH 3/8] Revert "[codegen]Ensure __builtin_trap() has an unreachable" This reverts commit 48bc3a4580675833dc69afcb8d6a4328644b6ce2. --- clang/lib/CodeGen/CGBuiltin.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index efcc33ac1f564..3f7b090315f5e 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -4068,12 +4068,6 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, } case Builtin::BI__builtin_trap: EmitTrapCall(Intrinsic::trap); - if (Builder.GetInsertBlock()) { - Builder.CreateUnreachable(); - // Dummy block for the ret void - it'll be clened up - llvm::BasicBlock *DeadBB = createBasicBlock("dead.trap"); - EmitBlock(DeadBB); - } return RValue::get(nullptr); case Builtin::BI__builtin_verbose_trap: { llvm::DILocation *TrapLocation = Builder.getCurrentDebugLocation(); >From e3e70cdb8a2fe7181351bcefea3b5e16fe2a9dcf Mon Sep 17 00:00:00 2001 From: Vy Nguyen <[email protected]> Date: Tue, 18 Aug 2026 13:40:10 -0400 Subject: [PATCH 4/8] add tests --- lld/test/MachO/icf-fold-dwarf-frame.s | 173 ++++++++++++++++++++++++++ lld/test/MachO/icf.s | 10 +- 2 files changed, 176 insertions(+), 7 deletions(-) create mode 100644 lld/test/MachO/icf-fold-dwarf-frame.s diff --git a/lld/test/MachO/icf-fold-dwarf-frame.s b/lld/test/MachO/icf-fold-dwarf-frame.s new file mode 100644 index 0000000000000..34fdc3cc55f42 --- /dev/null +++ b/lld/test/MachO/icf-fold-dwarf-frame.s @@ -0,0 +1,173 @@ +# REQUIRES: aarch64 + +# RUN: llvm-mc -filetype=obj -triple=arm64-apple-macos11 %s -o %t.o +# RUN: %lld -arch arm64 %t.o -o %t.dylib -undefined dynamic_lookup --icf=all +# RUN: llvm-objdump --macho --syms --dwarf=frames --unwind-info %t.dylib | FileCheck %s + +# CHECK-LABEL: SYMBOL TABLE: +# CHECK-DAG: [[#%.16x,FOLD0:]] {{.*}} __TEXT,__text _foldA +# CHECK-DAG: [[#FOLD0]] {{.*}} __TEXT,__text _foldB +# CHECK-DAG: [[#FOLD0]] {{.*}} __TEXT,__text _foldC +# CHECK-NOT: [[#FOLD0]] {{.*}} __TEXT,__text _diffLSDA +# CHECK-NOT: [[#FOLD0]] {{.*}} __TEXT,__text _diffPersonality +# CHECK-NOT: [[#FOLD0]] {{.*}} __TEXT,__text _diffCFI +# CHECK-DAG: [[#%.16x,FOLD1:]] {{.*}} __TEXT,__gcc_except_tab GCC_except_table0 +# CHECK-DAG: [[#FOLD1]] {{.*}} __TEXT,__gcc_except_tab GCC_except_table1 +# CHECK-NOT: [[#FOLD1]] {{.*}} __TEXT,__gcc_except_tab GCC_except_table2 + +# CHECK-LABEL: Contents of __unwind_info section: + +# CHECK-LABEL: .eh_frame contents: +# CHECK: {{^}}[[#%.8x,CIE0:]] {{.*}} CIE +# CHECK: FDE cie=[[#%.8x,CIE0]] +# CHECK: FDE cie=[[#%.8x,CIE0]] +# CHECK: FDE cie=[[#%.8x,CIE0]] +# CHECK: FDE cie=[[#%.8x,CIE0]] +# CHECK: {{^}}[[#%.8x,CIE1:]] {{.*}} CIE +# CHECK: FDE cie=[[#%.8x,CIE1]] +# CHECK: FDE cie=[[#%.8x,CIE1]] + +# Due to padding, we need to emit a throwaway FDE for each personality, so that +# subsequent FDEs are the same size and can be folded +# TODO: Could we detect padding differences and fold anyway? +_padA: + .cfi_startproc + .cfi_personality 155, _p0 + .cfi_lsda 16, Lexception0 + str x30, [sp, #-16]! + .cfi_def_cfa_offset 16 + .cfi_offset w30, -16 + bl _may_throw + ldr x30, [sp], #16 + ret + .cfi_endproc + +_padB: + .cfi_startproc + .cfi_personality 155, _p1 + .cfi_lsda 16, Lexception0 + str x30, [sp, #-16]! + .cfi_def_cfa_offset 16 + .cfi_offset w30, -16 + bl _may_throw + ldr x30, [sp], #16 + ret + .cfi_endproc + +_foldA: + .cfi_startproc + .cfi_personality 155, _p0 + .cfi_lsda 16, Lexception0 + str x30, [sp, #-16]! + .cfi_def_cfa_offset 16 + .cfi_offset w30, -16 + bl _may_throw + ldr x30, [sp], #16 + ret + .cfi_endproc + +_foldB: + .cfi_startproc + .cfi_personality 155, _p0 + .cfi_lsda 16, Lexception0 + str x30, [sp, #-16]! + .cfi_def_cfa_offset 16 + .cfi_offset w30, -16 + bl _may_throw + ldr x30, [sp], #16 + ret + .cfi_endproc + +# LSDA points to a different symbol, but the contents are the same as Lexception1 so it can be folded +_foldC: + .cfi_startproc + .cfi_personality 155, _p0 + .cfi_lsda 16, Lexception1 + str x30, [sp, #-16]! + .cfi_def_cfa_offset 16 + .cfi_offset w30, -16 + bl _may_throw + ldr x30, [sp], #16 + ret + .cfi_endproc + +# Different LSDAs cannot be folded +_diffLSDA: + .cfi_startproc + .cfi_personality 155, _p0 + .cfi_lsda 16, Lexception2 + str x30, [sp, #-16]! + .cfi_def_cfa_offset 16 + .cfi_offset w30, -16 + bl _may_throw + ldr x30, [sp], #16 + ret + .cfi_endproc + +_diffPersonality: + .cfi_startproc + .cfi_personality 155, _p1 + .cfi_lsda 16, Lexception0 + str x30, [sp, #-16]! + .cfi_def_cfa_offset 16 + .cfi_offset w30, -16 + bl _may_throw + ldr x30, [sp], #16 + ret + .cfi_endproc + +_diffCFI: + .cfi_startproc + .cfi_personality 155, _p0 + .cfi_lsda 16, Lexception0 + str x30, [sp, #-16]! + .cfi_def_cfa_offset 160 + .cfi_offset w30, -160 + bl _may_throw + ldr x30, [sp], #16 + ret + .cfi_endproc + +.section __TEXT,__gcc_except_tab +.p2align 2 +GCC_except_table0: +Lexception0: + .byte 0xFF + .byte 0x9B + .uleb128 Lttbase0-Lttbaseref0 +Lttbaseref0: + .byte 1 + .uleb128 0 + .p2align 2 + .long 0 +Lttbase0: + +# Contents are identical to above. It should be folded +.p2align 2 +GCC_except_table1: +Lexception1: + .byte 0xFF + .byte 0x9B + .uleb128 Lttbase1-Lttbaseref1 +Lttbaseref1: + .byte 1 + .uleb128 0 + .p2align 2 + .long 0 +Lttbase1: + +.p2align 2 +GCC_except_table2: +Lexception2: + .byte 0xFF + .byte 0x9B + .uleb128 Lttbase2-Lttbaseref2 +Lttbaseref2: + .byte 1 + .uleb128 1 + .byte 0xAA + .p2align 2 + .long 0 +Lttbase2: + +.subsections_via_symbols diff --git a/lld/test/MachO/icf.s b/lld/test/MachO/icf.s index 68ed369188e91..9db2a864be836 100644 --- a/lld/test/MachO/icf.s +++ b/lld/test/MachO/icf.s @@ -40,8 +40,8 @@ # CHECK: [[#%x,HAS_UNWIND_4:]] l F __TEXT,__text _has_unwind_4 # CHECK: [[#%x,HAS_ABS_PERSONALITY_1:]] l F __TEXT,__text _has_abs_personality_1 # CHECK: [[#%x,HAS_ABS_PERSONALITY_2:]] l F __TEXT,__text _has_abs_personality_2 -# CHECK: [[#%x,HAS_EH_FRAME_1:]] l F __TEXT,__text _has_eh_frame_1 -# CHECK: [[#%x,HAS_EH_FRAME_2:]] l F __TEXT,__text _has_eh_frame_2 +# CHECK: [[#%x,HAS_EH_FRAME_2:]] l F __TEXT,__text _has_eh_frame_1 +# CHECK: [[#%x,HAS_EH_FRAME_2]] l F __TEXT,__text _has_eh_frame_2 # CHECK: [[#%x,HAS_EH_FRAME_3:]] l F __TEXT,__text _has_eh_frame_3 # CHECK: [[#%x,MUTALLY_RECURSIVE_2:]] l F __TEXT,__text _mutually_recursive_1 # CHECK: [[#%x,MUTALLY_RECURSIVE_2]] l F __TEXT,__text _mutually_recursive_2 @@ -55,8 +55,6 @@ # CHECK: [[#%x,GCC_EXCEPT_0]] l O __TEXT,__gcc_except_tab GCC_except_table1 # CHECK: [[#%x,GCC_EXCEPT_2:]] l O __TEXT,__gcc_except_tab GCC_except_table2 -## Check that we don't accidentally dedup distinct EH frames. -# CHECK: FDE {{.*}} pc=[[#%x,HAS_EH_FRAME_1]] # CHECK: FDE {{.*}} pc=[[#%x,HAS_EH_FRAME_2]] # CHECK: FDE {{.*}} pc=[[#%x,HAS_EH_FRAME_3]] @@ -89,7 +87,7 @@ # CHECK: callq 0x[[#%x,HAS_UNWIND_4]] <_has_unwind_4> # CHECK: callq 0x[[#%x,HAS_ABS_PERSONALITY_1]] <_has_abs_personality_1> # CHECK: callq 0x[[#%x,HAS_ABS_PERSONALITY_2]] <_has_abs_personality_2> -# CHECK: callq 0x[[#%x,HAS_EH_FRAME_1]] <_has_eh_frame_1> +# CHECK: callq 0x[[#%x,HAS_EH_FRAME_2]] <_has_eh_frame_2> # CHECK: callq 0x[[#%x,HAS_EH_FRAME_2]] <_has_eh_frame_2> # CHECK: callq 0x[[#%x,HAS_EH_FRAME_3]] <_has_eh_frame_3> # CHECK: callq 0x[[#%x,MUTALLY_RECURSIVE_2]] <_mutually_recursive_2> @@ -261,8 +259,6 @@ _has_abs_personality_2: _abs_personality_1 = 0x1 _abs_personality_2 = 0x2 -## In theory _has_eh_frame_{1, 2} can be dedup'ed, but we don't support this -## yet. _has_eh_frame_1: .cfi_startproc .cfi_def_cfa_offset 8 >From b6594941d8d0d1ea69cce0334891ecf0bb89a389 Mon Sep 17 00:00:00 2001 From: Vy Nguyen <[email protected]> Date: Tue, 18 Aug 2026 20:21:19 -0400 Subject: [PATCH 5/8] Apply suggestion from @ellishg Co-authored-by: Ellis Hoag <[email protected]> --- lld/MachO/ICF.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lld/MachO/ICF.cpp b/lld/MachO/ICF.cpp index 60df53327b834..ac540e31d761e 100644 --- a/lld/MachO/ICF.cpp +++ b/lld/MachO/ICF.cpp @@ -107,6 +107,8 @@ static void getNormalizedData(const ConcatInputSection *isec, static bool compareData(const ConcatInputSection *ia, const ConcatInputSection *ib) { + if (ia->data.size() != ib->data.size()) + return false; if (ia->data == ib->data) return true; if (!isFoldableWithAddendsRemoved(ia)) >From 95e3d3a1ef31360e34f129b04d06c9702c99e58d Mon Sep 17 00:00:00 2001 From: Vy Nguyen <[email protected]> Date: Tue, 18 Aug 2026 20:57:42 -0400 Subject: [PATCH 6/8] fix crash on arm64 and add assert --- lld/MachO/ICF.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lld/MachO/ICF.cpp b/lld/MachO/ICF.cpp index ac540e31d761e..0b9d3e9faf723 100644 --- a/lld/MachO/ICF.cpp +++ b/lld/MachO/ICF.cpp @@ -101,8 +101,11 @@ static bool isFoldableWithAddendsRemoved(const ConcatInputSection *isec) { static void getNormalizedData(const ConcatInputSection *isec, SmallVectorImpl<uint8_t> &buf) { buf.assign(isec->data.begin(), isec->data.end()); - for (const Relocation &r : isec->relocs) - target->relocateOne(buf.data() + r.offset, r, /*va=*/0, /*relocVA=*/0); + for (const Relocation &r : isec->relocs) { + size_t size = 1ULL << r.length; + if (r.offset + size <= buf.size()) + memset(buf.data() + r.offset, 0, size); + } } static bool compareData(const ConcatInputSection *ia, @@ -113,6 +116,8 @@ static bool compareData(const ConcatInputSection *ia, return true; if (!isFoldableWithAddendsRemoved(ia)) return false; + assert(isFoldableWithAddendsRemoved(ib)); + SmallVector<uint8_t, 64> bufA, bufB; getNormalizedData(ia, bufA); getNormalizedData(ib, bufB); >From 5256e0d16863cfe24739f1a8cedf798931416a40 Mon Sep 17 00:00:00 2001 From: Vy Nguyen <[email protected]> Date: Wed, 19 Aug 2026 02:15:27 -0400 Subject: [PATCH 7/8] format --- lld/MachO/ICF.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/lld/MachO/ICF.cpp b/lld/MachO/ICF.cpp index 0b9d3e9faf723..5730d37aa20a0 100644 --- a/lld/MachO/ICF.cpp +++ b/lld/MachO/ICF.cpp @@ -96,10 +96,10 @@ static bool isFoldableWithAddendsRemoved(const ConcatInputSection *isec) { isSelRefsSection(isec) || isEhFrameSection(isec); } -// Make a normalized copy of a section's bytes by zeroing out the embedded relocs. -// Return it in the given &buf +// Make a normalized copy of a section's bytes by zeroing out the embedded +// relocs. Return it in the given &buf static void getNormalizedData(const ConcatInputSection *isec, - SmallVectorImpl<uint8_t> &buf) { + SmallVectorImpl<uint8_t> &buf) { buf.assign(isec->data.begin(), isec->data.end()); for (const Relocation &r : isec->relocs) { size_t size = 1ULL << r.length; @@ -647,9 +647,10 @@ void macho::foldIdenticalSections(bool onlyCfStrings) { foldable.push_back(d->unwindEntry()); } else if (isEhFrameSection(isec)) { // __eh_frame contains two types of records: FDEs and CIEs. - // Functions point to FDEs, which are already collected above via unwindEntry(). - // CIEs are shared headers and are not attached to individual functions. - // Collect only CIEs here so they can also be hashed and deduplicated. + // Functions point to FDEs, which are already collected above via + // unwindEntry(). CIEs are shared headers and are not attached to + // individual functions. Collect only CIEs here so they can also be hashed + // and deduplicated. auto *obj = dyn_cast_or_null<ObjFile>(isec->getFile()); if (!onlyCfStrings && obj && !obj->fdes.contains(isec) && !isec->shouldOmitFromOutput()) >From c8295a307059f342a6149dc77df2fed6a29dfc8c Mon Sep 17 00:00:00 2001 From: Vy Nguyen <[email protected]> Date: Wed, 19 Aug 2026 21:44:02 -0400 Subject: [PATCH 8/8] handle offset zero --- lld/MachO/ICF.cpp | 5 ++++- lld/MachO/InputFiles.cpp | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lld/MachO/ICF.cpp b/lld/MachO/ICF.cpp index 5730d37aa20a0..609449ed6c646 100644 --- a/lld/MachO/ICF.cpp +++ b/lld/MachO/ICF.cpp @@ -101,10 +101,13 @@ static bool isFoldableWithAddendsRemoved(const ConcatInputSection *isec) { static void getNormalizedData(const ConcatInputSection *isec, SmallVectorImpl<uint8_t> &buf) { buf.assign(isec->data.begin(), isec->data.end()); - for (const Relocation &r : isec->relocs) { + for (size_t i = 0; i < isec->relocs.size(); ++i) { + const Relocation &r = isec->relocs[i]; size_t size = 1ULL << r.length; if (r.offset + size <= buf.size()) memset(buf.data() + r.offset, 0, size); + if (target->hasAttr(r.type, RelocAttrBits::SUBTRAHEND)) + ++i; // Skip the paired minuend relocation } } diff --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp index a9a57daf05d7e..5279eb0e1fea7 100644 --- a/lld/MachO/InputFiles.cpp +++ b/lld/MachO/InputFiles.cpp @@ -643,6 +643,9 @@ void ObjFile::parseRelocations(ArrayRef<SectionHeader> sectionHeaders, relInfo.r_address == minuendInfo.r_address); Relocation p; p.type = minuendInfo.r_type; + p.pcrel = minuendInfo.r_pcrel; + p.length = minuendInfo.r_length; + p.offset = r.offset; if (minuendInfo.r_extern) { p.referent = symbols[minuendInfo.r_symbolnum]; p.addend = totalAddend; _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
