[lld] 5a5a075 - [LLD][ELF][Hexagon] Support GDPLT transforms
Sid Manning via llvm-commits
llvm-commits at lists.llvm.org
Fri Mar 13 09:02:33 PDT 2020
Author: Sid Manning
Date: 2020-03-13T11:02:11-05:00
New Revision: 5a5a075c5b19b9024f53ecd03460c6e379798893
URL: https://github.com/llvm/llvm-project/commit/5a5a075c5b19b9024f53ecd03460c6e379798893
DIFF: https://github.com/llvm/llvm-project/commit/5a5a075c5b19b9024f53ecd03460c6e379798893.diff
LOG: [LLD][ELF][Hexagon] Support GDPLT transforms
Hexagon ABI specifies that call x at gdplt is transformed to call __tls_get_addr.
Example:
call x at gdplt
is changed to
call __tls_get_addr
When x is an external tls variable.
Differential Revision: https://reviews.llvm.org/D74443
Added:
lld/test/ELF/hexagon-tls-gd-xform.s
Modified:
lld/ELF/Arch/Hexagon.cpp
lld/ELF/Relocations.cpp
lld/ELF/Relocations.h
lld/ELF/Writer.cpp
Removed:
################################################################################
diff --git a/lld/ELF/Arch/Hexagon.cpp b/lld/ELF/Arch/Hexagon.cpp
index b1ec1579759d..730c47a88dfd 100644
--- a/lld/ELF/Arch/Hexagon.cpp
+++ b/lld/ELF/Arch/Hexagon.cpp
@@ -119,6 +119,7 @@ RelExpr Hexagon::getRelExpr(RelType type, const Symbol &s,
case R_HEX_PLT_B22_PCREL:
case R_HEX_B22_PCREL_X:
case R_HEX_B32_PCREL_X:
+ case R_HEX_GD_PLT_B22_PCREL:
return R_PLT_PC;
case R_HEX_IE_32_6_X:
case R_HEX_IE_16_X:
@@ -303,6 +304,7 @@ void Hexagon::relocate(uint8_t *loc, const Relocation &rel,
case R_HEX_B15_PCREL_X:
or32le(loc, applyMask(0x00df20fe, val & 0x3f));
break;
+ case R_HEX_GD_PLT_B22_PCREL:
case R_HEX_B22_PCREL:
case R_HEX_PLT_B22_PCREL:
checkInt(loc, val, 22, rel);
diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index 280173c5420e..59c9ecf0019d 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -1980,6 +1980,44 @@ bool ThunkCreator::createThunks(ArrayRef<OutputSection *> outputSections) {
return addressesChanged;
}
+// The following aid in the conversion of call x at GDPLT to call __tls_get_addr
+// hexagonNeedsTLSSymbol scans for relocations would require a call to
+// __tls_get_addr.
+// hexagonTLSSymbolUpdate rebinds the relocation to __tls_get_addr.
+bool hexagonNeedsTLSSymbol(ArrayRef<OutputSection *> outputSections) {
+ bool needTlsSymbol = false;
+ forEachInputSectionDescription(
+ outputSections, [&](OutputSection *os, InputSectionDescription *isd) {
+ for (InputSection *isec : isd->sections)
+ for (Relocation &rel : isec->relocations)
+ if (rel.sym->type == llvm::ELF::STT_TLS && rel.expr == R_PLT_PC) {
+ needTlsSymbol = true;
+ return;
+ }
+ });
+ return needTlsSymbol;
+}
+
+void hexagonTLSSymbolUpdate(ArrayRef<OutputSection *> outputSections) {
+ Symbol *sym = symtab->find("__tls_get_addr");
+ if (!sym)
+ return;
+ bool needEntry = true;
+ forEachInputSectionDescription(
+ outputSections, [&](OutputSection *os, InputSectionDescription *isd) {
+ for (InputSection *isec : isd->sections)
+ for (Relocation &rel : isec->relocations)
+ if (rel.sym->type == llvm::ELF::STT_TLS && rel.expr == R_PLT_PC) {
+ if (needEntry) {
+ addPltEntry(in.plt, in.gotPlt, in.relaPlt, target->pltRel,
+ *sym);
+ needEntry = false;
+ }
+ rel.sym = sym;
+ }
+ });
+}
+
template void scanRelocations<ELF32LE>(InputSectionBase &);
template void scanRelocations<ELF32BE>(InputSectionBase &);
template void scanRelocations<ELF64LE>(InputSectionBase &);
diff --git a/lld/ELF/Relocations.h b/lld/ELF/Relocations.h
index 4069fc5f4786..b3181b67ad0e 100644
--- a/lld/ELF/Relocations.h
+++ b/lld/ELF/Relocations.h
@@ -115,6 +115,9 @@ template <class ELFT> void scanRelocations(InputSectionBase &);
template <class ELFT> void reportUndefinedSymbols();
+void hexagonTLSSymbolUpdate(ArrayRef<OutputSection *> outputSections);
+bool hexagonNeedsTLSSymbol(ArrayRef<OutputSection *> outputSections);
+
class ThunkSection;
class Thunk;
struct InputSectionDescription;
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index c916f35cc2b4..e172b708afcf 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -1592,6 +1592,10 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
ARMErr657417Patcher a32p;
script->assignAddresses();
+ // Converts call x at GDPLT to call __tls_get_addr
+ if (config->emachine == EM_HEXAGON)
+ hexagonTLSSymbolUpdate(outputSections);
+
int assignPasses = 0;
for (;;) {
bool changed = target->needsThunks && tc.createThunks(outputSections);
@@ -1849,6 +1853,15 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
sec->addrExpr = [=] { return i->second; };
}
+ // With the outputSections available check for GDPLT relocations
+ // and add __tls_get_addr symbol if needed.
+ if (config->emachine == EM_HEXAGON && hexagonNeedsTLSSymbol(outputSections)) {
+ Symbol *sym = symtab->addSymbol(Undefined{
+ nullptr, "__tls_get_addr", STB_GLOBAL, STV_DEFAULT, STT_NOTYPE});
+ sym->isPreemptible = true;
+ partitions[0].dynSymTab->addSymbol(sym);
+ }
+
// This is a bit of a hack. A value of 0 means undef, so we set it
// to 1 to make __ehdr_start defined. The section number is not
// particularly relevant.
diff --git a/lld/test/ELF/hexagon-tls-gd-xform.s b/lld/test/ELF/hexagon-tls-gd-xform.s
new file mode 100644
index 000000000000..65aeb118fcb3
--- /dev/null
+++ b/lld/test/ELF/hexagon-tls-gd-xform.s
@@ -0,0 +1,47 @@
+# REQUIRES: hexagon
+# RUN: llvm-mc -filetype=obj -defsym GDPLT=1 -triple=hexagon-unknown-elf %s -o %t.o
+# RUN: llvm-mc -filetype=obj -triple=hexagon-unknown-elf %s -o %t1.o
+# RUN: ld.lld -shared %t.o -o %t.so
+# RUN: ld.lld -shared %t1.o -o %t1.so
+# RUN: llvm-objdump -d --no-show-raw-insn --print-imm-hex %t.so | \
+# RUN: FileCheck --check-prefix=CHECK_GDPLT %s
+# RUN: llvm-objdump -d --no-show-raw-insn --print-imm-hex %t1.so | FileCheck %s
+# RUN: llvm-readobj -r %t.so | FileCheck -check-prefix=RELA_GDPLT %s
+
+## Make sure __tls_get_addr is not present unless there is a GDPLT relocation.
+# RUN: llvm-readobj -r %t1.so | FileCheck -check-prefix=RELA \
+# RUN: --implicit-check-not="__tls_get_addr" %s
+
+.globl _start
+.type _start, @function
+
+_start:
+.ifdef GDPLT
+ call x at gdplt
+# CHECK_GDPLT: 101ec: { call 0x10220 }
+.else
+ call x
+# CHECK: 101b8: { call 0x101e0 }
+.endif
+
+# CHECK_GDPLT: 10220: { immext(#0x20040)
+# CHECK_GDPLT-NEXT: 10224: r14 = add(pc,##0x2007c) }
+# CHECK_GDPLT-NEXT: 10228: { r28 = memw(r14+#0x0) }
+# CHECK_GDPLT-NEXT: 1022c: { jumpr r28 }
+
+
+## Looking at the above check, 0x10220+0x2007c must equal the entry for
+## __tls_get_addr, 0x3029C
+
+# RELA_GDPLT: Relocations [
+# RELA_GDPLT-NEXT: Section (5) .rela.plt {
+# RELA_GDPLT-NEXT: 0x30298 R_HEX_JMP_SLOT x 0x0
+# RELA_GDPLT-NEXT: 0x3029C R_HEX_JMP_SLOT __tls_get_addr 0x0
+# RELA_GDPLT-NEXT: }
+# RELA_GDPLT-NEXT:]
+
+# RELA: Relocations [
+# RELA-NEXT: Section (5) .rela.plt {
+# RELA-NEXT: 0x30258 R_HEX_JMP_SLOT x 0x0
+# RELA-NEXT: }
+# RELA-NEXT:]
More information about the llvm-commits
mailing list