Index: ELF/Arch/Hexagon.cpp =================================================================== --- ELF/Arch/Hexagon.cpp +++ ELF/Arch/Hexagon.cpp @@ -30,10 +30,19 @@ 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 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; + GotEntrySize = 8; + GotPltEntrySize = 8; + PltEntrySize = 16; + PltHeaderSize = 0; // MUSL isn't lazy so there is no reason to make a header. + // Hexagon Linux uses 64K pages by default. DefaultMaxPageSize = 0x10000; } @@ -64,11 +73,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; } @@ -212,6 +222,20 @@ } } +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 @@ -990,9 +990,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 = - (Config->Is64 || IsX32 || Machine == EM_PPC || Machine == EM_RISCV) && - Machine != EM_MIPS; + Config->IsRela = (Config->Is64 || IsX32 || Machine == EM_PPC || + Machine == EM_RISCV || Machine == EM_HEXAGON) && + Machine != EM_MIPS; // 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,4 @@ + +.global bar +bar: + jumpr lr Index: test/ELF/hexagon-shared.s =================================================================== --- /dev/null +++ test/ELF/hexagon-shared.s @@ -0,0 +1,15 @@ +# 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(#65536) +# CHECK: r14 = add(pc,##65544) } +# CHECK: r28 = memw(r14+#0) } +# CHECK: jumpr r28 }