From 261eec5fa5deae96a454835092a09098ced277a6 Mon Sep 17 00:00:00 2001 From: Sid Manning Date: Thu, 4 Oct 2018 14:54:17 +0000 Subject: [PATCH] [ELF][HEXAGON] Add support for GOT relocations. The GOT is referenced through the symbol _GLOBAL_OFFSET_TABLE_ . The relocation added calculates the offset into the global offset table for the entry of a symbol. In order to get the correct TargetVA I needed to create an new relocation expression, HEXAGON_GOT. It does Sym.getGotVA() - In.GotPlt->getVA(). Differential Revision: https://reviews.llvm.org/D52744 llvm-svn: 343784 --- lld/ELF/Arch/Hexagon.cpp | 12 ++++++++++++ lld/ELF/InputSection.cpp | 2 ++ lld/ELF/Relocations.cpp | 18 +++++++++--------- lld/ELF/Relocations.h | 1 + lld/test/ELF/hexagon-shared.s | 23 +++++++++++++++++------ 5 files changed, 41 insertions(+), 15 deletions(-) diff --git a/lld/ELF/Arch/Hexagon.cpp b/lld/ELF/Arch/Hexagon.cpp index b448f61..9933192 100644 --- a/lld/ELF/Arch/Hexagon.cpp +++ b/lld/ELF/Arch/Hexagon.cpp @@ -40,6 +40,13 @@ public: Hexagon::Hexagon() { PltRel = R_HEX_JMP_SLOT; RelativeRel = R_HEX_RELATIVE; + GotRel = R_HEX_GLOB_DAT; + GotEntrySize = 4; + // The zero'th GOT entry is reserved for the address of _DYNAMIC. The + // next 3 are reserved for the dynamic loader. + GotPltHeaderEntriesNum = 4; + GotPltEntrySize = 4; + PltEntrySize = 16; PltHeaderSize = 32; @@ -82,6 +89,9 @@ RelExpr Hexagon::getRelExpr(RelType Type, const Symbol &S, case R_HEX_B22_PCREL_X: case R_HEX_B32_PCREL_X: return R_PLT_PC; + case R_HEX_GOT_11_X: + case R_HEX_GOT_32_6_X: + return R_HEXAGON_GOT; default: return R_ABS; } @@ -175,6 +185,7 @@ void Hexagon::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { or32le(Loc, applyMask(0x00203fe0, Val & 0x3f)); break; case R_HEX_11_X: + case R_HEX_GOT_11_X: or32le(Loc, applyMask(findMaskR11(read32le(Loc)), Val & 0x3f)); break; case R_HEX_12_X: @@ -188,6 +199,7 @@ void Hexagon::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { or32le(Loc, Val); break; case R_HEX_32_6_X: + case R_HEX_GOT_32_6_X: or32le(Loc, applyMask(0x0fff3fff, Val >> 6)); break; case R_HEX_B9_PCREL: diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index ddb968a..69d83d0 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -545,6 +545,8 @@ static uint64_t getRelocTargetVA(const InputFile *File, RelType Type, int64_t A, case R_GOT_PC: case R_RELAX_TLS_GD_TO_IE: return Sym.getGotVA() + A - P; + case R_HEXAGON_GOT: + return Sym.getGotVA() - In.GotPlt->getVA(); case R_MIPS_GOTREL: return Sym.getVA(A) - In.MipsGot->getGp(File); case R_MIPS_GOT_GP: diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index a902f0f..bbb37e3 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -331,9 +331,9 @@ static bool needsPlt(RelExpr Expr) { // returns false for TLS variables even though they need GOT, because // TLS variables uses GOT differently than the regular variables. static bool needsGot(RelExpr Expr) { - return isRelExprOneOf(Expr); + return isRelExprOneOf(Expr); } // True if this expression is of the form Sym - X, where X is a position in the @@ -357,12 +357,12 @@ static bool isStaticLinkTimeConstant(RelExpr E, RelType Type, const Symbol &Sym, InputSectionBase &S, uint64_t RelOff) { // These expressions always compute a constant if (isRelExprOneOf< - R_GOT_FROM_END, R_GOT_OFF, R_TLSLD_GOT_OFF, R_MIPS_GOT_LOCAL_PAGE, - R_MIPS_GOTREL, R_MIPS_GOT_OFF, R_MIPS_GOT_OFF32, R_MIPS_GOT_GP_PC, - R_MIPS_TLSGD, R_GOT_PAGE_PC, R_GOT_PC, R_GOTONLY_PC, - R_GOTONLY_PC_FROM_END, R_PLT_PC, R_TLSGD_GOT, R_TLSGD_GOT_FROM_END, - R_TLSGD_PC, R_PPC_CALL_PLT, R_TLSDESC_CALL, R_TLSDESC_PAGE, R_HINT, - R_TLSLD_HINT, R_TLSIE_HINT>(E)) + R_GOT_FROM_END, R_GOT_OFF, R_HEXAGON_GOT, R_TLSLD_GOT_OFF, + R_MIPS_GOT_LOCAL_PAGE, R_MIPS_GOTREL, R_MIPS_GOT_OFF, + R_MIPS_GOT_OFF32, R_MIPS_GOT_GP_PC, R_MIPS_TLSGD, R_GOT_PAGE_PC, + R_GOT_PC, R_GOTONLY_PC, R_GOTONLY_PC_FROM_END, R_PLT_PC, R_TLSGD_GOT, + R_TLSGD_GOT_FROM_END, R_TLSGD_PC, R_PPC_CALL_PLT, R_TLSDESC_CALL, + R_TLSDESC_PAGE, R_HINT, R_TLSLD_HINT, R_TLSIE_HINT>(E)) return true; // These never do, except if the entire file is position dependent or if diff --git a/lld/ELF/Relocations.h b/lld/ELF/Relocations.h index 081f13b..d482b4e 100644 --- a/lld/ELF/Relocations.h +++ b/lld/ELF/Relocations.h @@ -43,6 +43,7 @@ enum RelExpr { R_GOT_OFF, R_GOT_PAGE_PC, R_GOT_PC, + R_HEXAGON_GOT, R_HINT, R_MIPS_GOTREL, R_MIPS_GOT_GP, diff --git a/lld/test/ELF/hexagon-shared.s b/lld/test/ELF/hexagon-shared.s index 33d9a7a..9d65b4e 100644 --- a/lld/test/ELF/hexagon-shared.s +++ b/lld/test/ELF/hexagon-shared.s @@ -3,19 +3,27 @@ # RUN: llvm-mc -filetype=obj -triple=hexagon-unknown-elf %S/Inputs/hexagon-shared.s -o %t2.o # RUN: ld.lld -shared %t2.o -soname %t3.so -o %t3.so # RUN: ld.lld -shared %t %t3.so -soname %t4.so -o %t4.so -# RUN: llvm-objdump -d -j=.plt %t4.so | FileCheck --check-prefix=PLT %s -# RUN: llvm-objdump -d -j=.text %t4.so | FileCheck --check-prefix=TEXT %s +# RUN: llvm-objdump -d -j .plt %t4.so | FileCheck --check-prefix=PLT %s +# RUN: llvm-objdump -d -j .text %t4.so | FileCheck --check-prefix=TEXT %s +# RUN: llvm-objdump -D -j .got %t4.so | FileCheck --check-prefix=GOT %s .global foo foo: + # _HEX_32_PCREL .word _DYNAMIC - . call ##bar + # R_HEX_PLT_B22_PCREL call bar@PLT +# R_HEX_GOT_11_X and R_HEX_GOT_32_6_X +r2=add(pc,##_GLOBAL_OFFSET_TABLE_@PCREL) +r0 = memw (r2+##bar@GOT) +jumpr r0 + # PLT: { immext(#65472 -# PLT: r28 = add(pc,##65520) } +# PLT: r28 = add(pc,##65488) } # PLT: { r14 -= add(r28,#16) # PLT: r15 = memw(r28+#8) # PLT: r28 = memw(r28+#4) } @@ -23,9 +31,12 @@ call bar@PLT # PLT: jumpr r28 } # PLT: { trap0(#219) } # PLT: immext(#65472) -# PLT: r14 = add(pc,##65488) } +# PLT: r14 = add(pc,##65472) } # PLT: r28 = memw(r14+#0) } # PLT: jumpr r28 } -# TEXT: 10000: 00 00 01 00 00010000 -# TEXT: { call 0x10030 } +# TEXT: 10000: 00 00 02 00 00020000 +# TEXT: { call 0x10050 } + +# GOT: .got: +# GOT: 30080: 00 00 00 00 00000000 -- 2.7.4