Index: ELF/Arch/Hexagon.cpp =================================================================== --- ELF/Arch/Hexagon.cpp +++ ELF/Arch/Hexagon.cpp @@ -9,6 +9,7 @@ #include "InputFiles.h" #include "Symbols.h" +#include "SyntheticSections.h" #include "Target.h" #include "lld/Common/ErrorHandler.h" #include "llvm/BinaryFormat/ELF.h" @@ -30,10 +31,18 @@ RelExpr getRelExpr(RelType Type, const Symbol &S, const uint8_t *Loc) const override; void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override; + void writePltHeader(uint8_t *Buf) const override; + void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr, + int32_t Index, unsigned RelOff) const override; }; } // namespace Hexagon::Hexagon() { + PltRel = R_HEX_JMP_SLOT; + RelativeRel = R_HEX_RELATIVE; + PltEntrySize = 16; + PltHeaderSize = 32; + // Hexagon Linux uses 64K pages by default. DefaultMaxPageSize = 0x10000; NoneRel = R_HEX_NONE; @@ -65,11 +74,12 @@ case R_HEX_B13_PCREL: case R_HEX_B15_PCREL: case R_HEX_B15_PCREL_X: + case R_HEX_6_PCREL_X: + return R_PC; case R_HEX_B22_PCREL: case R_HEX_B22_PCREL_X: case R_HEX_B32_PCREL_X: - case R_HEX_6_PCREL_X: - return R_PC; + return R_PLT_PC; default: return R_ABS; } @@ -168,7 +178,7 @@ case R_HEX_12_X: or32le(Loc, applyMask(0x000007e0, Val)); break; - case R_HEX_16_X: // This reloc only has 6 effective bits. + case R_HEX_16_X: // This reloc only has 6 effective bits. or32le(Loc, applyMask(findMaskR16(read32le(Loc)), Val & 0x3f)); break; case R_HEX_32: @@ -213,6 +223,40 @@ } } +void Hexagon::writePltHeader(uint8_t *Buf) const { + const uint8_t PltData[] = { + 0x00, 0x40, 0x00, 0x00, // { immext (#0) + 0x1c, 0xc0, 0x49, 0x6a, // r28 = add (pc, ##GOT0@PCREL) } # @GOT0 + 0x0e, 0x42, 0x9c, 0xe2, // { r14 -= add (r28, #16) # offset of GOTn + 0x4f, 0x40, 0x9c, 0x91, // r15 = memw (r28 + #8) # object ID at GOT2 + + 0x3c, 0xc0, 0x9c, 0x91, // r28 = memw (r28 + #4) }# dynamic link at GOT1 + 0x0e, 0x42, 0x0e, 0x8c, // { r14 = asr (r14, #2) # index of PLTn + 0x00, 0xc0, 0x9c, 0x52, // jumpr r28 } # call dynamic linker + 0x00, 0xc0, 0x00, 0x7f, // nop # bring plt0 into 16-byte alignment + }; + memcpy(Buf, PltData, sizeof(PltData)); + + // offset from PLT0 to the GOT. + relocateOne(Buf, R_HEX_B32_PCREL_X, In.GotPlt->getVA() - In.Plt->getVA()); + relocateOne(Buf + 4, R_HEX_6_PCREL_X, + In.GotPlt->getVA() - In.Plt->getVA()); +} +void Hexagon::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, + uint64_t PltEntryAddr, int32_t Index, + unsigned RelOff) const { + const uint8_t Inst[] = { + 0x00, 0x40, 0x00, 0x00, // { immext (#0) + 0x0e, 0xc0, 0x49, 0x6a, // r14 = add (pc, ##GOTn@PCREL) } + 0x1c, 0xc0, 0x8e, 0x91, // r28 = memw (r14) + 0x00, 0xc0, 0x9c, 0x52, // jumpr r28 + }; + memcpy(Buf, Inst, sizeof(Inst)); + + relocateOne(Buf, R_HEX_B32_PCREL_X, GotPltEntryAddr - PltEntryAddr); + relocateOne(Buf + 4, R_HEX_6_PCREL_X, GotPltEntryAddr - PltEntryAddr); +} + TargetInfo *elf::getHexagonTargetInfo() { static Hexagon Target; return &Target; Index: ELF/Driver.cpp =================================================================== --- ELF/Driver.cpp +++ ELF/Driver.cpp @@ -989,8 +989,9 @@ // You cannot choose which one, Rel or Rela, you want to use. Instead each // ABI defines which one you need to use. The following expression expresses // that. - Config->IsRela = M == EM_AARCH64 || M == EM_AMDGPU || M == EM_PPC || - M == EM_PPC64 || M == EM_RISCV || M == EM_X86_64; + Config->IsRela = M == EM_AARCH64 || M == EM_AMDGPU || M == EM_HEXAGON || + M == EM_PPC || M == EM_PPC64 || M == EM_RISCV || + M == EM_X86_64; // If the output uses REL relocations we must store the dynamic relocation // addends to the output sections. We also store addends for RELA relocations Index: test/ELF/Inputs/hexagon-shared.s =================================================================== --- /dev/null +++ test/ELF/Inputs/hexagon-shared.s @@ -0,0 +1,3 @@ +.global bar +bar: + jumpr lr Index: test/ELF/hexagon-shared.s =================================================================== --- /dev/null +++ test/ELF/hexagon-shared.s @@ -0,0 +1,23 @@ +# REQUIRES: hexagon +# RUN: llvm-mc -filetype=obj -triple=hexagon-unknown-elf %s -o %t +# RUN: llvm-mc -filetype=obj -triple=hexagon-unknown-elf %S/Inputs/hexagon-shared.s -o %t2 +# RUN: ld.lld -shared %t2 -o %t3 +# RUN: ld.lld -shared %t %t3 -o %t4 +# RUN: llvm-objdump -d -j .plt %t4 | FileCheck %s + +.global foo +foo: +call ##bar + +# CHECK: { immext(#65472 +# CHECK: r28 = add(pc,##65520) } +# CHECK: { r14 -= add(r28,#16) +# CHECK: r15 = memw(r28+#8) +# CHECK: r28 = memw(r28+#4) } +# CHECK: { r14 = asr(r14,#2) +# CHECK: jumpr r28 } +# CHECK: nop +# CHECK: immext(#65472) +# CHECK: r14 = add(pc,##65488) } +# CHECK: r28 = memw(r14+#0) } +# CHECK: jumpr r28 }