Skip to content

Commit 0004a38

Browse files
MaskRaynikic
authored andcommitted
[ELF] --emit-relocs: adjust offsets of .rel[a].eh_frame relocations
Two code paths may reach the EHFrame case in SectionBase::getOffset: * .eh_frame reference * relocation copy for --emit-relocs The first may be used by clang_rt.crtbegin.o and GCC crtbeginT.o to get the start address of the output .eh_frame. The relocation has an offset of 0 or (x86-64 PC-relative leaq for clang_rt.crtbegin.o) -4. The current code just returns `offset`, which handles this case well. The second is related to InputSection::copyRelocations on .eh_frame (used by --emit-relocs). .eh_frame pieces may be dropped due to GC/ICF, so we should convert the input offset to the output offset. Use the same way as MergeInputSection with a special case handling outSecOff==-1 for an invalid piece (see eh-frame-marker.s). This exposes an issue in mips64-eh-abs-reloc.s that we don't reliably handle anyway. Just add --no-check-dynamic-relocations to paper over it. Differential Revision: https://reviews.llvm.org/D122459
1 parent a040561 commit 0004a38

File tree

5 files changed

+33
-13
lines changed

5 files changed

+33
-13
lines changed

lld/ELF/InputSection.cpp

+21-4
Original file line numberDiff line numberDiff line change
@@ -165,11 +165,19 @@ uint64_t SectionBase::getOffset(uint64_t offset) const {
165165
case Regular:
166166
case Synthetic:
167167
return cast<InputSection>(this)->outSecOff + offset;
168-
case EHFrame:
169-
// The file crtbeginT.o has relocations pointing to the start of an empty
170-
// .eh_frame that is known to be the first in the link. It does that to
171-
// identify the start of the output .eh_frame.
168+
case EHFrame: {
169+
// Two code paths may reach here. First, clang_rt.crtbegin.o and GCC
170+
// crtbeginT.o may reference the start of an empty .eh_frame to identify the
171+
// start of the output .eh_frame. Just return offset.
172+
//
173+
// Second, InputSection::copyRelocations on .eh_frame. Some pieces may be
174+
// discarded due to GC/ICF. We should compute the output section offset.
175+
const EhInputSection *es = cast<EhInputSection>(this);
176+
if (!es->rawData.empty())
177+
if (InputSection *isec = es->getParent())
178+
return isec->outSecOff + es->getParentOffset(offset);
172179
return offset;
180+
}
173181
case Merge:
174182
const MergeInputSection *ms = cast<MergeInputSection>(this);
175183
if (InputSection *isec = ms->getParent())
@@ -1351,6 +1359,15 @@ void EhInputSection::split(ArrayRef<RelTy> rels) {
13511359
getObjMsg(d.data() - rawData.data()));
13521360
}
13531361

1362+
// Return the offset in an output section for a given input offset.
1363+
uint64_t EhInputSection::getParentOffset(uint64_t offset) const {
1364+
const EhSectionPiece &piece = partition_point(
1365+
pieces, [=](EhSectionPiece p) { return p.inputOff <= offset; })[-1];
1366+
if (piece.outputOff == -1) // invalid piece
1367+
return offset - piece.inputOff;
1368+
return piece.outputOff + (offset - piece.inputOff);
1369+
}
1370+
13541371
static size_t findNull(StringRef s, size_t entSize) {
13551372
for (unsigned i = 0, n = s.size(); i != n; i += entSize) {
13561373
const char *b = s.begin() + i;

lld/ELF/InputSection.h

+1
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,7 @@ class EhInputSection : public InputSectionBase {
328328
SmallVector<EhSectionPiece, 0> pieces;
329329

330330
SyntheticSection *getParent() const;
331+
uint64_t getParentOffset(uint64_t offset) const;
331332
};
332333

333334
// This is a section that is added directly to an output section

lld/test/ELF/eh-frame-merge.s

+3-3
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@
1616

1717
# RELOC: Offset Info Type Symbol's Value Symbol's Name + Addend
1818
# RELOC-NEXT: {{0*}}[[#%x,OFF:]] [[#%x,]] R_X86_64_PC32 [[#%x,]] foo + 0
19-
# RELOC-NEXT: {{0*}}[[#%x,OFF+20]] [[#%x,]] R_X86_64_PC32 [[#%x,]] bar + 0
20-
# RELOC-NEXT: {{0*}}[[#OFF]] [[#%x,]] R_X86_64_PC32 [[#%x,]] foo + 1
21-
# RELOC-NEXT: {{0*}}[[#OFF+20]] [[#%x,]] R_X86_64_NONE 0{{$}}
19+
# RELOC-NEXT: {{0*}}[[#%x,OFF+24]] [[#%x,]] R_X86_64_PC32 [[#%x,]] bar + 0
20+
# RELOC-NEXT: {{0*}}[[#OFF+48]] [[#%x,]] R_X86_64_PC32 [[#%x,]] foo + 1
21+
# RELOC-NEXT: {{0*}}[[#%x,OFF-24]] [[#%x,]] R_X86_64_NONE 0{{$}}
2222

2323
# EH: Format: DWARF32
2424
# EH: 00000018 00000014 0000001c FDE cie=00000000 pc={{0*}}[[#%x,FOO:]]...

lld/test/ELF/ehframe-relocation.s

+6-4
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// RUN: echo '.cfi_startproc; .cfi_endproc' | llvm-mc -filetype=obj -triple=x86_64 - -o %t2.o
44
// RUN: ld.lld %t.o %t2.o -o %t
55
// RUN: llvm-readobj -S %t | FileCheck %s
6-
// RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s
6+
// RUN: llvm-objdump -d --print-imm-hex %t | FileCheck --check-prefix=DISASM %s
77

88
// CHECK: Name: .eh_frame
99
// CHECK-NEXT: Type: SHT_PROGBITS
@@ -15,15 +15,17 @@
1515
// CHECK-NEXT: Size: 52
1616
// CHECK-NOT: .eh_frame
1717

18-
// 0x200120 = 2097440
1918
// DISASM: Disassembly of section .text:
2019
// DISASM-EMPTY:
2120
// DISASM-NEXT: <_start>:
22-
// DISASM-NEXT: 201154: {{.*}} movq 2097440, %rax
21+
// DISASM-NEXT: movq 0x200120, %rax
22+
// DISASM-NEXT: leaq {{.*}}(%rip), %rax # {{.*}} <__EH_FRAME_LIST__>
2323

2424
.section .eh_frame,"a",@unwind
25+
__EH_FRAME_LIST__:
2526

2627
.section .text
2728
.globl _start
2829
_start:
29-
movq .eh_frame, %rax
30+
movq .eh_frame, %rax # addend=0
31+
leaq __EH_FRAME_LIST__(%rip), %rax # addend=-4, used by libclang_rt.crtbegin.o

lld/test/ELF/mips64-eh-abs-reloc.s

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22
# Having an R_MIPS_64 relocation in eh_frame would previously crash LLD
33
# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-freebsd %s -o %t.o
44
# RUN: llvm-readobj -r %t.o | FileCheck %s -check-prefix OBJ
5-
# RUN: ld.lld --eh-frame-hdr -shared -z notext -o %t.so %t.o
5+
# RUN: ld.lld --eh-frame-hdr -shared -z notext -o %t.so %t.o --no-check-dynamic-relocations
66
# RUN: llvm-readobj -r %t.so | FileCheck %s -check-prefix PIC-RELOCS
77

88
# Linking this as a PIE executable would also previously crash
99
# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-freebsd %S/Inputs/archive2.s -o %t-foo.o
1010
# -pie needs -z notext because of the R_MIPS_64 relocation
11-
# RUN: ld.lld --eh-frame-hdr -Bdynamic -pie -z notext -o %t-pie-dynamic.exe %t.o %t-foo.o
11+
# RUN: ld.lld --eh-frame-hdr -Bdynamic -pie -z notext -o %t-pie-dynamic.exe %t.o %t-foo.o --no-check-dynamic-relocations
1212
# RUN: llvm-readobj -r %t-pie-dynamic.exe | FileCheck %s -check-prefix PIC-RELOCS
1313

1414

0 commit comments

Comments
 (0)