[lld] bf45624 - [ELF][PPC32] Support .got2 in an output section description

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 23 11:32:49 PST 2021


Author: Fangrui Song
Date: 2021-12-23T11:32:44-08:00
New Revision: bf45624ba07f8bd65f38db872c89d8c0e4ffd5fe

URL: https://github.com/llvm/llvm-project/commit/bf45624ba07f8bd65f38db872c89d8c0e4ffd5fe
DIFF: https://github.com/llvm/llvm-project/commit/bf45624ba07f8bd65f38db872c89d8c0e4ffd5fe.diff

LOG: [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.

Added: 
    lld/test/ELF/linkerscript/ppc32-got2.s

Modified: 
    lld/ELF/InputFiles.h
    lld/ELF/InputSection.cpp
    lld/ELF/SyntheticSections.cpp
    lld/ELF/Thunks.cpp
    lld/test/ELF/ppc32-relocatable-got2.s

Removed: 
    


################################################################################
diff  --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h
index 1fee39371cca5..a031ef94c14da 100644
--- a/lld/ELF/InputFiles.h
+++ b/lld/ELF/InputFiles.h
@@ -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 @@ class InputFile {
 
   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

diff  --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index 56a3510e41bb0..df8cc5f221a0b 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -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;
     }
   }
 }

diff  --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 9bf6118ebc3fd..872dd0e612afc 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -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;
       }
     }
 }

diff  --git a/lld/ELF/Thunks.cpp b/lld/ELF/Thunks.cpp
index 85a0a67d613ca..38de4db191f45 100644
--- a/lld/ELF/Thunks.cpp
+++ b/lld/ELF/Thunks.cpp
@@ -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 
diff erent 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).

diff  --git a/lld/test/ELF/linkerscript/ppc32-got2.s b/lld/test/ELF/linkerscript/ppc32-got2.s
new file mode 100644
index 0000000000000..1e232fa2c3c45
--- /dev/null
+++ b/lld/test/ELF/linkerscript/ppc32-got2.s
@@ -0,0 +1,59 @@
+# REQUIRES: ppc
+## Test .got2 placed in a 
diff erent 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", at 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 at ha
+  addi 30, 30, .got2+0x8000-.L at l
+  bl f+0x8000 at plt
+
+#--- b.s
+.section .got2,"aw"
+.globl f
+f:
+  bl f+0x8000 at plt
+
+#--- t
+SECTIONS {
+  .rodata : { *(.rodata .rodata.*) *(.got2) }
+}

diff  --git a/lld/test/ELF/ppc32-relocatable-got2.s b/lld/test/ELF/ppc32-relocatable-got2.s
index 06ccb39b6a4aa..85a0764ffe5af 100644
--- a/lld/test/ELF/ppc32-relocatable-got2.s
+++ b/lld/test/ELF/ppc32-relocatable-got2.s
@@ -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 at 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
 


        


More information about the llvm-commits mailing list