Skip to content

Commit 9c8736f

Browse files
mykouHWMaskRay
authored andcommitted
[ELF] -r/--emit-relocs: Fix crash when processing .rela.text before .text (llvm#156354)
fixes llvm#156417 When the relocation section is placed before the relocated section and the relocated section is not defined in the linker script, an error will occur during the linking process. **Issue Cause:** In a.ro, `.rela.text` precedes its relocated `InputSection` `.text`. `addOrphanSections` doesn't handle this scenario. When it processes `.rela.text`, in the called `getOutputSectionName`, `rel->getOutputSection()` is nullptr (input `.text` doesn't yet have a parent output section), leading to an assertion failure. **Solution:** For --emit-relocs and -r, ensure the output section for `.text.foo` is created before the output section for `.rela.text.foo`. --------- Co-authored-by: Fangrui Song <i@maskray.me> (cherry picked from commit 507f394)
1 parent 15a3183 commit 9c8736f

File tree

2 files changed

+43
-8
lines changed

2 files changed

+43
-8
lines changed

lld/ELF/LinkerScript.cpp

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1021,10 +1021,6 @@ void LinkerScript::addOrphanSections() {
10211021
}
10221022
};
10231023

1024-
// For further --emit-reloc handling code we need target output section
1025-
// to be created before we create relocation output section, so we want
1026-
// to create target sections first. We do not want priority handling
1027-
// for synthetic sections because them are special.
10281024
size_t n = 0;
10291025
for (InputSectionBase *isec : ctx.inputSections) {
10301026
// Process InputSection and MergeInputSection.
@@ -1037,10 +1033,18 @@ void LinkerScript::addOrphanSections() {
10371033
if (ctx.arg.relocatable && (isec->flags & SHF_LINK_ORDER))
10381034
continue;
10391035

1040-
if (auto *sec = dyn_cast<InputSection>(isec))
1041-
if (InputSectionBase *rel = sec->getRelocatedSection())
1042-
if (auto *relIS = dyn_cast_or_null<InputSectionBase>(rel->parent))
1043-
add(relIS);
1036+
if (auto *sec = dyn_cast<InputSection>(isec)) {
1037+
if (InputSectionBase *relocated = sec->getRelocatedSection()) {
1038+
// For --emit-relocs and -r, ensure the output section for .text.foo
1039+
// is created before the output section for .rela.text.foo.
1040+
add(relocated);
1041+
// EhInputSection sections are not added to ctx.inputSections. If we see
1042+
// .rela.eh_frame, ensure the output section for the synthetic
1043+
// EhFrameSection is created first.
1044+
if (auto *p = dyn_cast_or_null<InputSectionBase>(relocated->parent))
1045+
add(p);
1046+
}
1047+
}
10441048
add(isec);
10451049
if (ctx.arg.relocatable)
10461050
for (InputSectionBase *depSec : isec->dependentSections)
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# REQUIRES: x86
2+
## Test that orphan section placement can handle a relocatable link where
3+
## the relocation section is seen before the relocated section.
4+
5+
# RUN: rm -rf %t && split-file %s %t && cd %t
6+
7+
# RUN: llvm-mc -filetype=obj -triple=x86_64 a.s -o a.o
8+
## In a.ro, .rela.text precedes its relocated section.
9+
# RUN: ld.lld -r a.o -T 1.lds -o a.ro
10+
# RUN: llvm-readelf -S a.ro | FileCheck %s
11+
# CHECK: .rela.text RELA
12+
# CHECK-NEXT: .text PROGBITS
13+
14+
# RUN: llvm-objcopy --rename-section .text=.com.text --rename-section .rela.text=.rela.com.text a.ro a1.o
15+
16+
## Regression test for #156354 , where we added an orphan RELA section before its relocated section.
17+
# RUN: ld.lld -r a1.o -o a1.ro
18+
# RUN: llvm-readelf -S a1.ro | FileCheck %s --check-prefix=CHECK1
19+
# CHECK1: .com.text PROGBITS
20+
# CHECK1-NEXT: .rela.com.text RELA
21+
22+
#--- a.s
23+
.globl foo
24+
foo:
25+
call foo
26+
27+
#--- 1.lds
28+
SECTIONS {
29+
.rela.text 0 : { *(.rela.text) }
30+
.text 0 : { *(.text) }
31+
}

0 commit comments

Comments
 (0)