Skip to content

Commit 2e2737c

Browse files
committed
[MC][MachO] Change addrsig format + ensure its size is properly set
There were two problems with the previous setup: 1. We weren't setting its size, which caused problems when `__llvm_addrsig` wasn't the last section. In particular, `__debug_line` (if created) is generated and placed after `__llvm_addrsig`, and would result in an invalid object file w/ overlapping sections being emitted. 2. The symbol indices could be invalidated if e.g. `llvm-strip` ran on the object file. See discussion [here][1]. To fix both these issues, we use symbol relocations instead of encoding symbol indices directly in the section contents. The section itself doesn't contain any data. That sidesteps the layout problem in addition to solving the second issue. The corresponding LLD change to read in this new format: {D128938}. It will fix the icf-safe.ll test failure on this diff. [1]: https://discourse.llvm.org/t/problems-with-mach-o-address-significance-table-generation/63392/ Reviewed By: #lld-macho, alx32 Differential Revision: https://reviews.llvm.org/D127637
1 parent 18f46f3 commit 2e2737c

File tree

4 files changed

+64
-32
lines changed

4 files changed

+64
-32
lines changed

llvm/include/llvm/MC/MCMachObjectWriter.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,9 +263,9 @@ class MachObjectWriter : public MCObjectWriter {
263263
const MCFragment &FB, bool InSet,
264264
bool IsPCRel) const override;
265265

266-
uint64_t writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
266+
void populateAddrSigSection(MCAssembler &Asm);
267267

268-
void writeAddrsigSection(MCAssembler &Asm);
268+
uint64_t writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
269269
};
270270

271271
/// Construct a new Mach-O writer instance.

llvm/lib/MC/MCMachOStreamer.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -583,15 +583,27 @@ MCStreamer *llvm::createMachOStreamer(MCContext &Context,
583583
return S;
584584
}
585585

586-
// Create the AddrSig section and first data fragment here as its layout needs
587-
// to be computed immediately after in order for it to be exported correctly.
586+
// The AddrSig section uses a series of relocations to refer to the symbols that
587+
// should be considered address-significant. The only interesting content of
588+
// these relocations is their symbol; the type, length etc will be ignored by
589+
// the linker. The reason we are not referring to the symbol indices directly is
590+
// that those indices will be invalidated by tools that update the symbol table.
591+
// Symbol relocations OTOH will have their indices updated by e.g. llvm-strip.
588592
void MCMachOStreamer::createAddrSigSection() {
589593
MCAssembler &Asm = getAssembler();
590594
MCObjectWriter &writer = Asm.getWriter();
591595
if (!writer.getEmitAddrsigSection())
592596
return;
597+
// Create the AddrSig section and first data fragment here as its layout needs
598+
// to be computed immediately after in order for it to be exported correctly.
593599
MCSection *AddrSigSection =
594600
Asm.getContext().getObjectFileInfo()->getAddrSigSection();
595601
Asm.registerSection(*AddrSigSection);
596-
new MCDataFragment(AddrSigSection);
602+
auto *Frag = new MCDataFragment(AddrSigSection);
603+
// We will generate a series of pointer-sized symbol relocations at offset
604+
// 0x0. Set the section size to be large enough to contain a single pointer
605+
// (instead of emitting a zero-sized section) so these relocations are
606+
// technically valid, even though we don't expect these relocations to
607+
// actually be applied by the linker.
608+
Frag->getContents().resize(8);
597609
}

llvm/lib/MC/MachObjectWriter.cpp

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -753,32 +753,27 @@ static MachO::LoadCommandType getLCFromMCVM(MCVersionMinType Type) {
753753
llvm_unreachable("Invalid mc version min type");
754754
}
755755

756-
// Encode addrsig data as symbol indexes in variable length encoding.
757-
void MachObjectWriter::writeAddrsigSection(MCAssembler &Asm) {
756+
void MachObjectWriter::populateAddrSigSection(MCAssembler &Asm) {
758757
MCSection *AddrSigSection =
759758
Asm.getContext().getObjectFileInfo()->getAddrSigSection();
760-
MCSection::FragmentListType &fragmentList = AddrSigSection->getFragmentList();
761-
if (!fragmentList.size())
762-
return;
763-
764-
assert(fragmentList.size() == 1);
765-
MCFragment *pFragment = &*fragmentList.begin();
766-
MCDataFragment *pDataFragment = dyn_cast_or_null<MCDataFragment>(pFragment);
767-
assert(pDataFragment);
768-
769-
raw_svector_ostream OS(pDataFragment->getContents());
770-
for (const MCSymbol *sym : this->getAddrsigSyms())
771-
encodeULEB128(sym->getIndex(), OS);
759+
unsigned Log2Size = is64Bit() ? 3 : 2;
760+
for (const MCSymbol *S : getAddrsigSyms()) {
761+
MachO::any_relocation_info MRE;
762+
MRE.r_word0 = 0;
763+
MRE.r_word1 = (Log2Size << 25) | (MachO::GENERIC_RELOC_VANILLA << 28);
764+
addRelocation(S, AddrSigSection, MRE);
765+
}
772766
}
773767

774768
uint64_t MachObjectWriter::writeObject(MCAssembler &Asm,
775769
const MCAsmLayout &Layout) {
776770
uint64_t StartOffset = W.OS.tell();
777771

772+
populateAddrSigSection(Asm);
773+
778774
// Compute symbol table information and bind symbol indices.
779775
computeSymbolTable(Asm, LocalSymbolData, ExternalSymbolData,
780776
UndefinedSymbolData);
781-
writeAddrsigSection(Asm);
782777

783778
if (!Asm.CGProfile.empty()) {
784779
MCSection *CGProfileSection = Asm.getContext().getMachOSection(

llvm/test/CodeGen/AArch64/addrsig-macho.ll

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
; RUN: llc -filetype=asm %s -o - -mtriple arm64-apple-ios -addrsig | FileCheck %s
22
; RUN: llc -filetype=obj %s -o %t -mtriple arm64-apple-ios -addrsig
3-
; RUN: llvm-readobj --hex-dump='__llvm_addrsig' %t | FileCheck %s --check-prefix=OBJ
3+
; RUN: llvm-objdump --macho --section-headers %t | FileCheck %s --check-prefix=SECTIONS
4+
; RUN: llvm-objdump --macho --reloc %t | FileCheck %s --check-prefix=RELOCS
45

56
; CHECK: .addrsig{{$}}
67
; CHECK-NEXT: .addrsig_sym _func03_takeaddr
@@ -11,8 +12,23 @@
1112
; CHECK-NEXT: .addrsig_sym _a1
1213
; CHECK-NEXT: .addrsig_sym _i1
1314

14-
; OBJ: Hex dump of section '__llvm_addrsig':
15-
; OBJ-NEXT:0x{{[0-9a-f]*}}
15+
; The __debug_line section (which should be generated for the given input file)
16+
; should appear immediately after the addrsig section. Use it to make sure
17+
; addrsig's section size has been properly set during section layout. This
18+
; catches a regression where the next section would overlap addrsig's
19+
; contents.
20+
; SECTIONS: __llvm_addrsig 00000008 [[#%.16x,ADDR:]]
21+
; SECTIONS-NEXT: __debug_line {{[[:xdigit:]]+}} [[#%.16x,8+ADDR]]
22+
23+
; RELOCS: Relocation information (__DATA,__llvm_addrsig) 7 entries
24+
; RELOCS: address pcrel length extern type scattered symbolnum/value
25+
; RELOCS: 00000000 False ?( 3) True UNSIGND False _i1
26+
; RELOCS: 00000000 False ?( 3) True UNSIGND False _a1
27+
; RELOCS: 00000000 False ?( 3) True UNSIGND False _g1
28+
; RELOCS: 00000000 False ?( 3) True UNSIGND False _result
29+
; RELOCS: 00000000 False ?( 3) True UNSIGND False _metadata_f2
30+
; RELOCS: 00000000 False ?( 3) True UNSIGND False _f1
31+
; RELOCS: 00000000 False ?( 3) True UNSIGND False _func03_takeaddr
1632

1733
target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
1834
target triple = "arm64-apple-ios7.0.0"
@@ -38,7 +54,7 @@ entry:
3854
}
3955

4056
; Function Attrs: minsize nofree noinline norecurse nounwind optsize ssp uwtable
41-
define void @func03_takeaddr() #0 {
57+
define void @func03_takeaddr() #0 !dbg !9 {
4258
entry:
4359
%0 = load volatile i32, ptr @result, align 4
4460
%add = add nsw i32 %0, 1
@@ -72,8 +88,8 @@ define void()* @f1() {
7288
%a2 = bitcast i32* @a2 to i8*
7389
%i1 = bitcast void()* @i1 to i8*
7490
%i2 = bitcast void()* @i2 to i8*
75-
call void @llvm.dbg.value(metadata i8* bitcast (void()* @metadata_f1 to i8*), metadata !5, metadata !DIExpression()), !dbg !7
76-
call void @llvm.dbg.value(metadata i8* bitcast (void()* @metadata_f2 to i8*), metadata !5, metadata !DIExpression()), !dbg !7
91+
call void @llvm.dbg.value(metadata i8* bitcast (void()* @metadata_f1 to i8*), metadata !6, metadata !DIExpression()), !dbg !8
92+
call void @llvm.dbg.value(metadata i8* bitcast (void()* @metadata_f2 to i8*), metadata !6, metadata !DIExpression()), !dbg !8
7793
call void @f4(i8* bitcast (void()* @metadata_f2 to i8*))
7894
unreachable
7995
}
@@ -108,9 +124,18 @@ declare void @f3() unnamed_addr
108124
declare void @llvm.dbg.value(metadata, metadata, metadata)
109125

110126
attributes #0 = { noinline }
111-
112-
!3 = distinct !DISubprogram(scope: null, isLocal: false, isDefinition: true, isOptimized: false)
113-
!4 = !DILocation(line: 0, scope: !3)
114-
!5 = !DILocalVariable(scope: !6)
115-
!6 = distinct !DISubprogram(scope: null, isLocal: false, isDefinition: true, isOptimized: false)
116-
!7 = !DILocation(line: 0, scope: !6, inlinedAt: !4)
127+
!llvm.dbg.cu = !{!0}
128+
!llvm.module.flags = !{!2, !3}
129+
130+
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, emissionKind: FullDebug)
131+
!1 = !DIFile(filename: "test.c", directory: "/tmp")
132+
!2 = !{i32 7, !"Dwarf Version", i32 4}
133+
!3 = !{i32 2, !"Debug Info Version", i32 3}
134+
135+
!4 = distinct !DISubprogram(scope: null, isLocal: false, isDefinition: true, isOptimized: false, unit: !0)
136+
!5 = !DILocation(line: 0, scope: !4)
137+
!6 = !DILocalVariable(scope: !7)
138+
!7 = distinct !DISubprogram(scope: null, isLocal: false, isDefinition: true, isOptimized: false, unit: !0)
139+
!8 = !DILocation(line: 0, scope: !7, inlinedAt: !5)
140+
!9 = distinct !DISubprogram(scope: null, file: !1, line: 1, type: !10, unit: !0)
141+
!10 = !DISubroutineType(types: !{})

0 commit comments

Comments
 (0)