forked from OSchip/llvm-project
[ELF][PPC32] Support .got2 in an output section description
I added `PPC32Got2Section` D62464 to support .got2 but did not implement .got2 in another output section. PR52799 has a linker script placing .got2 in .rodata, which causes a null pointer dereference because a MergeSyntheticSection's file is nullptr. Add the support.
This commit is contained in:
parent
f103ee2e9e
commit
bf45624ba0
|
@ -41,6 +41,7 @@ namespace elf {
|
|||
|
||||
using llvm::object::Archive;
|
||||
|
||||
class InputSection;
|
||||
class Symbol;
|
||||
|
||||
// If --reproduce is specified, all input files are written to this tar archive.
|
||||
|
@ -114,13 +115,13 @@ public:
|
|||
|
||||
SmallVector<Symbol *, 0> symbols;
|
||||
|
||||
// .got2 in the current file. This is used by PPC32 -fPIC/-fPIE to compute
|
||||
// offsets in PLT call stubs.
|
||||
InputSection *ppc32Got2 = nullptr;
|
||||
|
||||
// Index of MIPS GOT built for this file.
|
||||
uint32_t mipsGotIndex = -1;
|
||||
|
||||
// outSecOff of .got2 in the current file. This is used by PPC32 -fPIC/-fPIE
|
||||
// to compute offsets in PLT call stubs.
|
||||
uint32_t ppc32Got2OutSecOff = 0;
|
||||
|
||||
// groupId is used for --warn-backrefs which is an optional error
|
||||
// checking feature. All files within the same --{start,end}-group or
|
||||
// --{start,end}-lib get the same group ID. Otherwise, each file gets a new
|
||||
|
|
|
@ -474,13 +474,13 @@ void InputSection::copyRelocations(uint8_t *buf, ArrayRef<RelTy> rels) {
|
|||
else if (config->relocatable && type != target->noneRel)
|
||||
sec->relocations.push_back({R_ABS, type, rel.r_offset, addend, &sym});
|
||||
} else if (config->emachine == EM_PPC && type == R_PPC_PLTREL24 &&
|
||||
p->r_addend >= 0x8000) {
|
||||
p->r_addend >= 0x8000 && sec->file->ppc32Got2) {
|
||||
// Similar to R_MIPS_GPREL{16,32}. If the addend of R_PPC_PLTREL24
|
||||
// indicates that r30 is relative to the input section .got2
|
||||
// (r_addend>=0x8000), after linking, r30 should be relative to the output
|
||||
// section .got2 . To compensate for the shift, adjust r_addend by
|
||||
// ppc32Got2OutSecOff.
|
||||
p->r_addend += sec->file->ppc32Got2OutSecOff;
|
||||
// ppc32Got->outSecOff.
|
||||
p->r_addend += sec->file->ppc32Got2->outSecOff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3620,14 +3620,12 @@ void PPC32Got2Section::finalizeContents() {
|
|||
// .got2 . This function computes outSecOff of each .got2 to be used in
|
||||
// PPC32PltCallStub::writeTo(). The purpose of this empty synthetic section is
|
||||
// to collect input sections named ".got2".
|
||||
uint32_t offset = 0;
|
||||
for (SectionCommand *cmd : getParent()->commands)
|
||||
if (auto *isd = dyn_cast<InputSectionDescription>(cmd)) {
|
||||
for (InputSection *isec : isd->sections) {
|
||||
if (isec == this)
|
||||
continue;
|
||||
isec->file->ppc32Got2OutSecOff = offset;
|
||||
offset += (uint32_t)isec->getSize();
|
||||
// isec->file may be nullptr for MergeSyntheticSection.
|
||||
if (isec != this && isec->file)
|
||||
isec->file->ppc32Got2 = isec;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -806,8 +806,9 @@ void elf::writePPC32PltCallStub(uint8_t *buf, uint64_t gotPltVA,
|
|||
// The stub loads an address relative to r30 (.got2+Addend). Addend is
|
||||
// almost always 0x8000. The address of .got2 is different in another object
|
||||
// file, so a stub cannot be shared.
|
||||
offset = gotPltVA - (in.ppc32Got2->getParent()->getVA() +
|
||||
file->ppc32Got2OutSecOff + addend);
|
||||
offset = gotPltVA -
|
||||
(in.ppc32Got2->getParent()->getVA() +
|
||||
(file->ppc32Got2 ? file->ppc32Got2->outSecOff : 0) + addend);
|
||||
} else {
|
||||
// The stub loads an address relative to _GLOBAL_OFFSET_TABLE_ (which is
|
||||
// currently the address of .got).
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
# REQUIRES: ppc
|
||||
## Test .got2 placed in a different output section.
|
||||
|
||||
# RUN: rm -rf %t && split-file %s %t
|
||||
# RUN: llvm-mc -filetype=obj -triple=powerpc %t/a.s -o %t/a.o
|
||||
# RUN: llvm-mc -filetype=obj -triple=powerpc %t/b.s -o %t/b.o
|
||||
# RUN: ld.lld -shared -T %t/t %t/a.o %t/b.o -o %t/a.so
|
||||
# RUN: llvm-readobj -r %t/a.so | FileCheck --check-prefix=RELOC %s
|
||||
# RUN: llvm-readelf -S %t/a.so | FileCheck --check-prefix=SEC %s
|
||||
|
||||
# RELOC: .rela.plt {
|
||||
# RELOC-NEXT: 0x1A4 R_PPC_JMP_SLOT f 0x0
|
||||
# RELOC-NEXT: }
|
||||
|
||||
# SEC: .got PROGBITS 0000018c
|
||||
# SEC-NEXT: .rodata PROGBITS 00000198
|
||||
|
||||
## .got2+0x8000-0xb0 = .rodata+4+0x8000-0xb0 = 0x198+4+0x8000-0xb0 = 65536*1-32532
|
||||
# CHECK: <_start>:
|
||||
# CHECK-NEXT: bcl 20, 31, 0x
|
||||
# CHECK-NEXT: b0: mflr 30
|
||||
# CHECK-NEXT: addis 30, 30, 1
|
||||
# CHECK-NEXT: addi 30, 30, -32532
|
||||
# CHECK-NEXT: bl {{.*}} <00008000.got2.plt_pic32.f>
|
||||
|
||||
## &.got[2] - (.got2+0x8000) = &.got[2] - (.rodata+4+0x8000) = 0x1A4 - (0x198+4+0x8000) = -32760
|
||||
# CHECK: <00008000.got2.plt_pic32.f>:
|
||||
# CHECK-NEXT: lwz 11, -32760(30)
|
||||
# CHECK-NEXT: mtctr 11
|
||||
# CHECK-NEXT: bctr
|
||||
# CHECK-NEXT: nop
|
||||
|
||||
#--- a.s
|
||||
.section .rodata.cst4,"aM",@progbits,4
|
||||
.long 1
|
||||
|
||||
.section .got2,"aw"
|
||||
.long f
|
||||
|
||||
.text
|
||||
.globl _start, f, g
|
||||
_start:
|
||||
bcl 20,31,.L
|
||||
.L:
|
||||
mflr 30
|
||||
addis 30, 30, .got2+0x8000-.L@ha
|
||||
addi 30, 30, .got2+0x8000-.L@l
|
||||
bl f+0x8000@plt
|
||||
|
||||
#--- b.s
|
||||
.section .got2,"aw"
|
||||
.globl f
|
||||
f:
|
||||
bl f+0x8000@plt
|
||||
|
||||
#--- t
|
||||
SECTIONS {
|
||||
.rodata : { *(.rodata .rodata.*) *(.got2) }
|
||||
}
|
|
@ -3,10 +3,11 @@
|
|||
## If r_addend indicates .got2, adjust it by the local .got2's output section offset.
|
||||
|
||||
# RUN: llvm-mc -filetype=obj -triple=powerpc %s -o %t.o
|
||||
# RUN: ld.lld -r %t.o %t.o -o %t
|
||||
# RUN: echo 'bl f+0x8000@plt' | llvm-mc -filetype=obj -triple=powerpc - -o %t2.o
|
||||
# RUN: ld.lld -r %t.o %t.o %t2.o -o %t
|
||||
# RUN: llvm-readobj -r %t | FileCheck %s
|
||||
|
||||
# RUN: ld.lld -shared --emit-relocs %t.o %t.o -o %t.so
|
||||
# RUN: ld.lld -shared --emit-relocs %t.o %t.o %t2.o -o %t.so
|
||||
# RUN: llvm-readobj -r %t.so | FileCheck %s
|
||||
|
||||
# CHECK: .rela.adjust {
|
||||
|
@ -23,6 +24,11 @@
|
|||
# CHECK-NEXT: R_PPC_PLTREL24 foo 0x0
|
||||
# CHECK-NEXT: R_PPC_PLTREL24 foo 0x0
|
||||
# CHECK-NEXT: }
|
||||
## %t2.o has an invalid relocation with r_addend=0x8000. Test we don't crash.
|
||||
## The addend doesn't matter.
|
||||
# CHECK-NEXT: .rela.text {
|
||||
# CHECK-NEXT: R_PPC_PLTREL24 f 0x8000
|
||||
# CHECK-NEXT: }
|
||||
.section .got2,"aw"
|
||||
.long 0
|
||||
|
||||
|
|
Loading…
Reference in New Issue