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