Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions lld/MachO/InputFiles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -411,10 +411,14 @@ void ObjFile::parseSections(ArrayRef<SectionHeader> sectionHeaders) {
auto *isec = make<ConcatInputSection>(section, data, align);
if (isDebugSection(isec->getFlags()) &&
isec->getSegName() == segment_names::dwarf) {
// Instead of emitting DWARF sections, we emit STABS symbols to the
// object files that contain them. We filter them out early to avoid
// parsing their relocations unnecessarily.
// Keep debug sections in debugSections for diagnostic purposes
debugSections.push_back(isec);
Comment on lines +414 to 415
Copy link
Contributor

Choose a reason for hiding this comment

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

it is not used for diagnostic purposes, it's used to initialize the DwarfObject so we can emit STABS properly. I actually think we can remove debugSections entirely now that we are keeping references to the DWARF InputSections in sections. We can have DwarfObject::create re-traverse sections in order to find the relevant ones.

// Add DWARF sections to subsections so their relocations are processed,
// but mark them dead so they aren't emitted (MachO uses STABS, not DWARF).
// This fixes crashes with section-relative relocations (e.g., DW_FORM_strp)
// while maintaining MachO's traditional STABS-only debug output.
Comment on lines +418 to +419
Copy link
Contributor

Choose a reason for hiding this comment

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

"fixes crashes" here will not make sense to future readers who did not know how the code looked like before. let's explain it directly here; my understanding is that we cannot simply drop the sections here because it would result in a "dangling reference" issue if other sections contain relocations that point to this one

Copy link
Contributor

Choose a reason for hiding this comment

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

(if that's not right, please explain a bit more what the crash is. what's the stack trace?)

isec->live = false;
section.subsections.push_back({0, isec});
} else {
section.subsections.push_back({0, isec});
}
Expand Down
63 changes: 63 additions & 0 deletions lld/test/MachO/dwarf-strp-relocations.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# REQUIRES: x86
# RUN: rm -rf %t; split-file %s %t

# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/test.s -o %t/test.o
# RUN: %lld -dylib %t/test.o -o %t/test.dylib
# RUN: llvm-objdump --section-headers %t/test.dylib | FileCheck %s

## Test that lld can handle section-relative relocations in DWARF sections,
## specifically DW_FORM_strp which creates X86_64_RELOC_UNSIGNED relocations
## to the __debug_str section. This previously caused linker crashes with
## "malformed relocation" errors on macOS.
##
## The test verifies that:
## 1. The link completes successfully without crashing (key requirement)
## 2. DWARF sections are processed for relocations but not emitted to output
## (MachO traditionally uses STABS, not DWARF, for debug info)
##
## Negative checks ensure DWARF sections are NOT in the final binary, preventing
## regression where they might be accidentally emitted.

# CHECK-NOT: __debug_info
# CHECK-NOT: __debug_abbrev
# CHECK-NOT: __debug_str

#--- test.s
.section __TEXT,__text,regular,pure_instructions
.globl _main
_main:
movl $42, %eax
retq

.section __DWARF,__debug_abbrev,regular,debug
Labbrev_begin:
.byte 1 ## Abbrev code
.byte 17 ## DW_TAG_compile_unit
.byte 1 ## DW_CHILDREN_yes
.byte 37 ## DW_AT_producer
.byte 14 ## DW_FORM_strp (string table pointer!)
.byte 3 ## DW_AT_name
.byte 14 ## DW_FORM_strp
.byte 0 ## End attributes
.byte 0
.byte 0 ## End abbrev table

.section __DWARF,__debug_info,regular,debug
Linfo_begin:
.long Linfo_end - Linfo_begin - 4 ## Length
.short 4 ## DWARF version 4
.long 0 ## Abbrev offset
.byte 8 ## Address size
.byte 1 ## Abbrev code
## These .long directives create section-relative relocations (X86_64_RELOC_UNSIGNED)
## to the __debug_str section. This is the critical test case.
.long Lproducer - Ldebug_str ## DW_AT_producer (section-relative!)
.long Lfilename - Ldebug_str ## DW_AT_name (section-relative!)
Linfo_end:

.section __DWARF,__debug_str,regular,debug
Ldebug_str:
Lproducer:
.asciz "Test Producer 1.0"
Lfilename:
.asciz "test.c"