1ece8a530Spatrick //===-- Hexagon.cpp -------------------------------------------------------===//
2ece8a530Spatrick //
3ece8a530Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4ece8a530Spatrick // See https://llvm.org/LICENSE.txt for license information.
5ece8a530Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6ece8a530Spatrick //
7ece8a530Spatrick //===----------------------------------------------------------------------===//
8ece8a530Spatrick
9ece8a530Spatrick #include "InputFiles.h"
10ece8a530Spatrick #include "Symbols.h"
11ece8a530Spatrick #include "SyntheticSections.h"
12ece8a530Spatrick #include "Target.h"
13ece8a530Spatrick #include "lld/Common/ErrorHandler.h"
14ece8a530Spatrick #include "llvm/BinaryFormat/ELF.h"
15ece8a530Spatrick #include "llvm/Support/Endian.h"
16ece8a530Spatrick
17ece8a530Spatrick using namespace llvm;
18ece8a530Spatrick using namespace llvm::object;
19ece8a530Spatrick using namespace llvm::support::endian;
20ece8a530Spatrick using namespace llvm::ELF;
21bb684c34Spatrick using namespace lld;
22bb684c34Spatrick using namespace lld::elf;
23ece8a530Spatrick
24ece8a530Spatrick namespace {
25ece8a530Spatrick class Hexagon final : public TargetInfo {
26ece8a530Spatrick public:
27ece8a530Spatrick Hexagon();
28ece8a530Spatrick uint32_t calcEFlags() const override;
29ece8a530Spatrick RelExpr getRelExpr(RelType type, const Symbol &s,
30ece8a530Spatrick const uint8_t *loc) const override;
31ece8a530Spatrick RelType getDynRel(RelType type) const override;
32bb684c34Spatrick void relocate(uint8_t *loc, const Relocation &rel,
33bb684c34Spatrick uint64_t val) const override;
34ece8a530Spatrick void writePltHeader(uint8_t *buf) const override;
35ece8a530Spatrick void writePlt(uint8_t *buf, const Symbol &sym,
36ece8a530Spatrick uint64_t pltEntryAddr) const override;
37ece8a530Spatrick };
38ece8a530Spatrick } // namespace
39ece8a530Spatrick
Hexagon()40ece8a530Spatrick Hexagon::Hexagon() {
41ece8a530Spatrick pltRel = R_HEX_JMP_SLOT;
42ece8a530Spatrick relativeRel = R_HEX_RELATIVE;
43ece8a530Spatrick gotRel = R_HEX_GLOB_DAT;
44ece8a530Spatrick symbolicRel = R_HEX_32;
45ece8a530Spatrick
46*dfe94b16Srobert gotBaseSymInGotPlt = true;
47ece8a530Spatrick // The zero'th GOT entry is reserved for the address of _DYNAMIC. The
48ece8a530Spatrick // next 3 are reserved for the dynamic loader.
49ece8a530Spatrick gotPltHeaderEntriesNum = 4;
50ece8a530Spatrick
51ece8a530Spatrick pltEntrySize = 16;
52ece8a530Spatrick pltHeaderSize = 32;
53ece8a530Spatrick
54ece8a530Spatrick // Hexagon Linux uses 64K pages by default.
55ece8a530Spatrick defaultMaxPageSize = 0x10000;
56ece8a530Spatrick tlsGotRel = R_HEX_TPREL_32;
57bb684c34Spatrick tlsModuleIndexRel = R_HEX_DTPMOD_32;
58bb684c34Spatrick tlsOffsetRel = R_HEX_DTPREL_32;
59ece8a530Spatrick }
60ece8a530Spatrick
calcEFlags() const61ece8a530Spatrick uint32_t Hexagon::calcEFlags() const {
62*dfe94b16Srobert assert(!ctx.objectFiles.empty());
63ece8a530Spatrick
64ece8a530Spatrick // The architecture revision must always be equal to or greater than
65ece8a530Spatrick // greatest revision in the list of inputs.
66ece8a530Spatrick uint32_t ret = 0;
67*dfe94b16Srobert for (InputFile *f : ctx.objectFiles) {
681cf9926bSpatrick uint32_t eflags = cast<ObjFile<ELF32LE>>(f)->getObj().getHeader().e_flags;
69ece8a530Spatrick if (eflags > ret)
70ece8a530Spatrick ret = eflags;
71ece8a530Spatrick }
72ece8a530Spatrick return ret;
73ece8a530Spatrick }
74ece8a530Spatrick
applyMask(uint32_t mask,uint32_t data)75ece8a530Spatrick static uint32_t applyMask(uint32_t mask, uint32_t data) {
76ece8a530Spatrick uint32_t result = 0;
77ece8a530Spatrick size_t off = 0;
78ece8a530Spatrick
79ece8a530Spatrick for (size_t bit = 0; bit != 32; ++bit) {
80ece8a530Spatrick uint32_t valBit = (data >> off) & 1;
81ece8a530Spatrick uint32_t maskBit = (mask >> bit) & 1;
82ece8a530Spatrick if (maskBit) {
83ece8a530Spatrick result |= (valBit << bit);
84ece8a530Spatrick ++off;
85ece8a530Spatrick }
86ece8a530Spatrick }
87ece8a530Spatrick return result;
88ece8a530Spatrick }
89ece8a530Spatrick
getRelExpr(RelType type,const Symbol & s,const uint8_t * loc) const90ece8a530Spatrick RelExpr Hexagon::getRelExpr(RelType type, const Symbol &s,
91ece8a530Spatrick const uint8_t *loc) const {
92ece8a530Spatrick switch (type) {
93ece8a530Spatrick case R_HEX_NONE:
94ece8a530Spatrick return R_NONE;
95ece8a530Spatrick case R_HEX_6_X:
96ece8a530Spatrick case R_HEX_8_X:
97ece8a530Spatrick case R_HEX_9_X:
98ece8a530Spatrick case R_HEX_10_X:
99ece8a530Spatrick case R_HEX_11_X:
100ece8a530Spatrick case R_HEX_12_X:
101ece8a530Spatrick case R_HEX_16_X:
102ece8a530Spatrick case R_HEX_32:
103ece8a530Spatrick case R_HEX_32_6_X:
104ece8a530Spatrick case R_HEX_HI16:
105ece8a530Spatrick case R_HEX_LO16:
106bb684c34Spatrick case R_HEX_DTPREL_32:
107ece8a530Spatrick return R_ABS;
108ece8a530Spatrick case R_HEX_B9_PCREL:
109ece8a530Spatrick case R_HEX_B13_PCREL:
110ece8a530Spatrick case R_HEX_B15_PCREL:
111ece8a530Spatrick case R_HEX_6_PCREL_X:
112ece8a530Spatrick case R_HEX_32_PCREL:
113ece8a530Spatrick return R_PC;
114ece8a530Spatrick case R_HEX_B9_PCREL_X:
115ece8a530Spatrick case R_HEX_B15_PCREL_X:
116ece8a530Spatrick case R_HEX_B22_PCREL:
117ece8a530Spatrick case R_HEX_PLT_B22_PCREL:
118ece8a530Spatrick case R_HEX_B22_PCREL_X:
119ece8a530Spatrick case R_HEX_B32_PCREL_X:
120bb684c34Spatrick case R_HEX_GD_PLT_B22_PCREL:
121bb684c34Spatrick case R_HEX_GD_PLT_B22_PCREL_X:
122bb684c34Spatrick case R_HEX_GD_PLT_B32_PCREL_X:
123ece8a530Spatrick return R_PLT_PC;
124ece8a530Spatrick case R_HEX_IE_32_6_X:
125ece8a530Spatrick case R_HEX_IE_16_X:
126ece8a530Spatrick case R_HEX_IE_HI16:
127ece8a530Spatrick case R_HEX_IE_LO16:
128ece8a530Spatrick return R_GOT;
129bb684c34Spatrick case R_HEX_GD_GOT_11_X:
130bb684c34Spatrick case R_HEX_GD_GOT_16_X:
131bb684c34Spatrick case R_HEX_GD_GOT_32_6_X:
132bb684c34Spatrick return R_TLSGD_GOTPLT;
133ece8a530Spatrick case R_HEX_GOTREL_11_X:
134ece8a530Spatrick case R_HEX_GOTREL_16_X:
135ece8a530Spatrick case R_HEX_GOTREL_32_6_X:
136ece8a530Spatrick case R_HEX_GOTREL_HI16:
137ece8a530Spatrick case R_HEX_GOTREL_LO16:
138ece8a530Spatrick return R_GOTPLTREL;
139ece8a530Spatrick case R_HEX_GOT_11_X:
140ece8a530Spatrick case R_HEX_GOT_16_X:
141ece8a530Spatrick case R_HEX_GOT_32_6_X:
142ece8a530Spatrick return R_GOTPLT;
143ece8a530Spatrick case R_HEX_IE_GOT_11_X:
144ece8a530Spatrick case R_HEX_IE_GOT_16_X:
145ece8a530Spatrick case R_HEX_IE_GOT_32_6_X:
146ece8a530Spatrick case R_HEX_IE_GOT_HI16:
147ece8a530Spatrick case R_HEX_IE_GOT_LO16:
148ece8a530Spatrick return R_GOTPLT;
149ece8a530Spatrick case R_HEX_TPREL_11_X:
150ece8a530Spatrick case R_HEX_TPREL_16:
151ece8a530Spatrick case R_HEX_TPREL_16_X:
152ece8a530Spatrick case R_HEX_TPREL_32_6_X:
153ece8a530Spatrick case R_HEX_TPREL_HI16:
154ece8a530Spatrick case R_HEX_TPREL_LO16:
1551cf9926bSpatrick return R_TPREL;
156ece8a530Spatrick default:
157ece8a530Spatrick error(getErrorLocation(loc) + "unknown relocation (" + Twine(type) +
158ece8a530Spatrick ") against symbol " + toString(s));
159ece8a530Spatrick return R_NONE;
160ece8a530Spatrick }
161ece8a530Spatrick }
162ece8a530Spatrick
163ece8a530Spatrick // There are (arguably too) many relocation masks for the DSP's
164ece8a530Spatrick // R_HEX_6_X type. The table below is used to select the correct mask
165ece8a530Spatrick // for the given instruction.
166ece8a530Spatrick struct InstructionMask {
167ece8a530Spatrick uint32_t cmpMask;
168ece8a530Spatrick uint32_t relocMask;
169ece8a530Spatrick };
170ece8a530Spatrick static const InstructionMask r6[] = {
171ece8a530Spatrick {0x38000000, 0x0000201f}, {0x39000000, 0x0000201f},
172ece8a530Spatrick {0x3e000000, 0x00001f80}, {0x3f000000, 0x00001f80},
173ece8a530Spatrick {0x40000000, 0x000020f8}, {0x41000000, 0x000007e0},
174ece8a530Spatrick {0x42000000, 0x000020f8}, {0x43000000, 0x000007e0},
175ece8a530Spatrick {0x44000000, 0x000020f8}, {0x45000000, 0x000007e0},
176ece8a530Spatrick {0x46000000, 0x000020f8}, {0x47000000, 0x000007e0},
177ece8a530Spatrick {0x6a000000, 0x00001f80}, {0x7c000000, 0x001f2000},
178ece8a530Spatrick {0x9a000000, 0x00000f60}, {0x9b000000, 0x00000f60},
179ece8a530Spatrick {0x9c000000, 0x00000f60}, {0x9d000000, 0x00000f60},
180ece8a530Spatrick {0x9f000000, 0x001f0100}, {0xab000000, 0x0000003f},
181ece8a530Spatrick {0xad000000, 0x0000003f}, {0xaf000000, 0x00030078},
182ece8a530Spatrick {0xd7000000, 0x006020e0}, {0xd8000000, 0x006020e0},
183ece8a530Spatrick {0xdb000000, 0x006020e0}, {0xdf000000, 0x006020e0}};
184ece8a530Spatrick
isDuplex(uint32_t insn)185*dfe94b16Srobert static bool isDuplex(uint32_t insn) {
186*dfe94b16Srobert // Duplex forms have a fixed mask and parse bits 15:14 are always
187*dfe94b16Srobert // zero. Non-duplex insns will always have at least one bit set in the
188*dfe94b16Srobert // parse field.
189*dfe94b16Srobert return (0xC000 & insn) == 0;
190*dfe94b16Srobert }
191*dfe94b16Srobert
findMaskR6(uint32_t insn)192*dfe94b16Srobert static uint32_t findMaskR6(uint32_t insn) {
193bb684c34Spatrick if (isDuplex(insn))
194ece8a530Spatrick return 0x03f00000;
195ece8a530Spatrick
196ece8a530Spatrick for (InstructionMask i : r6)
197ece8a530Spatrick if ((0xff000000 & insn) == i.cmpMask)
198ece8a530Spatrick return i.relocMask;
199ece8a530Spatrick
200*dfe94b16Srobert error("unrecognized instruction for 6_X relocation: 0x" +
201ece8a530Spatrick utohexstr(insn));
202ece8a530Spatrick return 0;
203ece8a530Spatrick }
204ece8a530Spatrick
findMaskR8(uint32_t insn)205ece8a530Spatrick static uint32_t findMaskR8(uint32_t insn) {
206ece8a530Spatrick if ((0xff000000 & insn) == 0xde000000)
207ece8a530Spatrick return 0x00e020e8;
208ece8a530Spatrick if ((0xff000000 & insn) == 0x3c000000)
209ece8a530Spatrick return 0x0000207f;
210ece8a530Spatrick return 0x00001fe0;
211ece8a530Spatrick }
212ece8a530Spatrick
findMaskR11(uint32_t insn)213ece8a530Spatrick static uint32_t findMaskR11(uint32_t insn) {
214ece8a530Spatrick if ((0xff000000 & insn) == 0xa1000000)
215ece8a530Spatrick return 0x060020ff;
216ece8a530Spatrick return 0x06003fe0;
217ece8a530Spatrick }
218ece8a530Spatrick
findMaskR16(uint32_t insn)219ece8a530Spatrick static uint32_t findMaskR16(uint32_t insn) {
220ece8a530Spatrick if ((0xff000000 & insn) == 0x48000000)
221ece8a530Spatrick return 0x061f20ff;
222ece8a530Spatrick if ((0xff000000 & insn) == 0x49000000)
223ece8a530Spatrick return 0x061f3fe0;
224ece8a530Spatrick if ((0xff000000 & insn) == 0x78000000)
225ece8a530Spatrick return 0x00df3fe0;
226ece8a530Spatrick if ((0xff000000 & insn) == 0xb0000000)
227ece8a530Spatrick return 0x0fe03fe0;
228ece8a530Spatrick
229bb684c34Spatrick if (isDuplex(insn))
230bb684c34Spatrick return 0x03f00000;
231bb684c34Spatrick
232*dfe94b16Srobert for (InstructionMask i : r6)
233*dfe94b16Srobert if ((0xff000000 & insn) == i.cmpMask)
234*dfe94b16Srobert return i.relocMask;
235*dfe94b16Srobert
236*dfe94b16Srobert error("unrecognized instruction for 16_X type: 0x" +
237ece8a530Spatrick utohexstr(insn));
238ece8a530Spatrick return 0;
239ece8a530Spatrick }
240ece8a530Spatrick
or32le(uint8_t * p,int32_t v)241ece8a530Spatrick static void or32le(uint8_t *p, int32_t v) { write32le(p, read32le(p) | v); }
242ece8a530Spatrick
relocate(uint8_t * loc,const Relocation & rel,uint64_t val) const243bb684c34Spatrick void Hexagon::relocate(uint8_t *loc, const Relocation &rel,
244bb684c34Spatrick uint64_t val) const {
245bb684c34Spatrick switch (rel.type) {
246ece8a530Spatrick case R_HEX_NONE:
247ece8a530Spatrick break;
248ece8a530Spatrick case R_HEX_6_PCREL_X:
249ece8a530Spatrick case R_HEX_6_X:
250ece8a530Spatrick or32le(loc, applyMask(findMaskR6(read32le(loc)), val));
251ece8a530Spatrick break;
252ece8a530Spatrick case R_HEX_8_X:
253ece8a530Spatrick or32le(loc, applyMask(findMaskR8(read32le(loc)), val));
254ece8a530Spatrick break;
255ece8a530Spatrick case R_HEX_9_X:
256ece8a530Spatrick or32le(loc, applyMask(0x00003fe0, val & 0x3f));
257ece8a530Spatrick break;
258ece8a530Spatrick case R_HEX_10_X:
259ece8a530Spatrick or32le(loc, applyMask(0x00203fe0, val & 0x3f));
260ece8a530Spatrick break;
261ece8a530Spatrick case R_HEX_11_X:
262bb684c34Spatrick case R_HEX_GD_GOT_11_X:
263ece8a530Spatrick case R_HEX_IE_GOT_11_X:
264ece8a530Spatrick case R_HEX_GOT_11_X:
265ece8a530Spatrick case R_HEX_GOTREL_11_X:
266ece8a530Spatrick case R_HEX_TPREL_11_X:
267ece8a530Spatrick or32le(loc, applyMask(findMaskR11(read32le(loc)), val & 0x3f));
268ece8a530Spatrick break;
269ece8a530Spatrick case R_HEX_12_X:
270ece8a530Spatrick or32le(loc, applyMask(0x000007e0, val));
271ece8a530Spatrick break;
272ece8a530Spatrick case R_HEX_16_X: // These relocs only have 6 effective bits.
273ece8a530Spatrick case R_HEX_IE_16_X:
274ece8a530Spatrick case R_HEX_IE_GOT_16_X:
275bb684c34Spatrick case R_HEX_GD_GOT_16_X:
276ece8a530Spatrick case R_HEX_GOT_16_X:
277ece8a530Spatrick case R_HEX_GOTREL_16_X:
278ece8a530Spatrick case R_HEX_TPREL_16_X:
279ece8a530Spatrick or32le(loc, applyMask(findMaskR16(read32le(loc)), val & 0x3f));
280ece8a530Spatrick break;
281ece8a530Spatrick case R_HEX_TPREL_16:
282ece8a530Spatrick or32le(loc, applyMask(findMaskR16(read32le(loc)), val & 0xffff));
283ece8a530Spatrick break;
284ece8a530Spatrick case R_HEX_32:
285ece8a530Spatrick case R_HEX_32_PCREL:
286bb684c34Spatrick case R_HEX_DTPREL_32:
287ece8a530Spatrick or32le(loc, val);
288ece8a530Spatrick break;
289ece8a530Spatrick case R_HEX_32_6_X:
290bb684c34Spatrick case R_HEX_GD_GOT_32_6_X:
291ece8a530Spatrick case R_HEX_GOT_32_6_X:
292ece8a530Spatrick case R_HEX_GOTREL_32_6_X:
293ece8a530Spatrick case R_HEX_IE_GOT_32_6_X:
294ece8a530Spatrick case R_HEX_IE_32_6_X:
295ece8a530Spatrick case R_HEX_TPREL_32_6_X:
296ece8a530Spatrick or32le(loc, applyMask(0x0fff3fff, val >> 6));
297ece8a530Spatrick break;
298ece8a530Spatrick case R_HEX_B9_PCREL:
299bb684c34Spatrick checkInt(loc, val, 11, rel);
300ece8a530Spatrick or32le(loc, applyMask(0x003000fe, val >> 2));
301ece8a530Spatrick break;
302ece8a530Spatrick case R_HEX_B9_PCREL_X:
303ece8a530Spatrick or32le(loc, applyMask(0x003000fe, val & 0x3f));
304ece8a530Spatrick break;
305ece8a530Spatrick case R_HEX_B13_PCREL:
306bb684c34Spatrick checkInt(loc, val, 15, rel);
307ece8a530Spatrick or32le(loc, applyMask(0x00202ffe, val >> 2));
308ece8a530Spatrick break;
309ece8a530Spatrick case R_HEX_B15_PCREL:
310bb684c34Spatrick checkInt(loc, val, 17, rel);
311ece8a530Spatrick or32le(loc, applyMask(0x00df20fe, val >> 2));
312ece8a530Spatrick break;
313ece8a530Spatrick case R_HEX_B15_PCREL_X:
314ece8a530Spatrick or32le(loc, applyMask(0x00df20fe, val & 0x3f));
315ece8a530Spatrick break;
316ece8a530Spatrick case R_HEX_B22_PCREL:
317bb684c34Spatrick case R_HEX_GD_PLT_B22_PCREL:
318ece8a530Spatrick case R_HEX_PLT_B22_PCREL:
319bb684c34Spatrick checkInt(loc, val, 22, rel);
320ece8a530Spatrick or32le(loc, applyMask(0x1ff3ffe, val >> 2));
321ece8a530Spatrick break;
322ece8a530Spatrick case R_HEX_B22_PCREL_X:
323bb684c34Spatrick case R_HEX_GD_PLT_B22_PCREL_X:
324ece8a530Spatrick or32le(loc, applyMask(0x1ff3ffe, val & 0x3f));
325ece8a530Spatrick break;
326ece8a530Spatrick case R_HEX_B32_PCREL_X:
327bb684c34Spatrick case R_HEX_GD_PLT_B32_PCREL_X:
328ece8a530Spatrick or32le(loc, applyMask(0x0fff3fff, val >> 6));
329ece8a530Spatrick break;
330ece8a530Spatrick case R_HEX_GOTREL_HI16:
331ece8a530Spatrick case R_HEX_HI16:
332ece8a530Spatrick case R_HEX_IE_GOT_HI16:
333ece8a530Spatrick case R_HEX_IE_HI16:
334ece8a530Spatrick case R_HEX_TPREL_HI16:
335ece8a530Spatrick or32le(loc, applyMask(0x00c03fff, val >> 16));
336ece8a530Spatrick break;
337ece8a530Spatrick case R_HEX_GOTREL_LO16:
338ece8a530Spatrick case R_HEX_LO16:
339ece8a530Spatrick case R_HEX_IE_GOT_LO16:
340ece8a530Spatrick case R_HEX_IE_LO16:
341ece8a530Spatrick case R_HEX_TPREL_LO16:
342ece8a530Spatrick or32le(loc, applyMask(0x00c03fff, val));
343ece8a530Spatrick break;
344ece8a530Spatrick default:
345ece8a530Spatrick llvm_unreachable("unknown relocation");
346ece8a530Spatrick }
347ece8a530Spatrick }
348ece8a530Spatrick
writePltHeader(uint8_t * buf) const349ece8a530Spatrick void Hexagon::writePltHeader(uint8_t *buf) const {
350ece8a530Spatrick const uint8_t pltData[] = {
351ece8a530Spatrick 0x00, 0x40, 0x00, 0x00, // { immext (#0)
352ece8a530Spatrick 0x1c, 0xc0, 0x49, 0x6a, // r28 = add (pc, ##GOT0@PCREL) } # @GOT0
353ece8a530Spatrick 0x0e, 0x42, 0x9c, 0xe2, // { r14 -= add (r28, #16) # offset of GOTn
354ece8a530Spatrick 0x4f, 0x40, 0x9c, 0x91, // r15 = memw (r28 + #8) # object ID at GOT2
355ece8a530Spatrick 0x3c, 0xc0, 0x9c, 0x91, // r28 = memw (r28 + #4) }# dynamic link at GOT1
356ece8a530Spatrick 0x0e, 0x42, 0x0e, 0x8c, // { r14 = asr (r14, #2) # index of PLTn
357ece8a530Spatrick 0x00, 0xc0, 0x9c, 0x52, // jumpr r28 } # call dynamic linker
358ece8a530Spatrick 0x0c, 0xdb, 0x00, 0x54, // trap0(#0xdb) # bring plt0 into 16byte alignment
359ece8a530Spatrick };
360ece8a530Spatrick memcpy(buf, pltData, sizeof(pltData));
361ece8a530Spatrick
362ece8a530Spatrick // Offset from PLT0 to the GOT.
363ece8a530Spatrick uint64_t off = in.gotPlt->getVA() - in.plt->getVA();
364bb684c34Spatrick relocateNoSym(buf, R_HEX_B32_PCREL_X, off);
365bb684c34Spatrick relocateNoSym(buf + 4, R_HEX_6_PCREL_X, off);
366ece8a530Spatrick }
367ece8a530Spatrick
writePlt(uint8_t * buf,const Symbol & sym,uint64_t pltEntryAddr) const368ece8a530Spatrick void Hexagon::writePlt(uint8_t *buf, const Symbol &sym,
369ece8a530Spatrick uint64_t pltEntryAddr) const {
370ece8a530Spatrick const uint8_t inst[] = {
371ece8a530Spatrick 0x00, 0x40, 0x00, 0x00, // { immext (#0)
372ece8a530Spatrick 0x0e, 0xc0, 0x49, 0x6a, // r14 = add (pc, ##GOTn@PCREL) }
373ece8a530Spatrick 0x1c, 0xc0, 0x8e, 0x91, // r28 = memw (r14)
374ece8a530Spatrick 0x00, 0xc0, 0x9c, 0x52, // jumpr r28
375ece8a530Spatrick };
376ece8a530Spatrick memcpy(buf, inst, sizeof(inst));
377ece8a530Spatrick
378ece8a530Spatrick uint64_t gotPltEntryAddr = sym.getGotPltVA();
379bb684c34Spatrick relocateNoSym(buf, R_HEX_B32_PCREL_X, gotPltEntryAddr - pltEntryAddr);
380bb684c34Spatrick relocateNoSym(buf + 4, R_HEX_6_PCREL_X, gotPltEntryAddr - pltEntryAddr);
381ece8a530Spatrick }
382ece8a530Spatrick
getDynRel(RelType type) const383ece8a530Spatrick RelType Hexagon::getDynRel(RelType type) const {
384ece8a530Spatrick if (type == R_HEX_32)
385ece8a530Spatrick return type;
386ece8a530Spatrick return R_HEX_NONE;
387ece8a530Spatrick }
388ece8a530Spatrick
getHexagonTargetInfo()389bb684c34Spatrick TargetInfo *elf::getHexagonTargetInfo() {
390ece8a530Spatrick static Hexagon target;
391ece8a530Spatrick return ⌖
392ece8a530Spatrick }
393