Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp
35293 views
1
//===-- PPCELFObjectWriter.cpp - PPC ELF Writer ---------------------------===//
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 "MCTargetDesc/PPCFixupKinds.h"
10
#include "MCTargetDesc/PPCMCExpr.h"
11
#include "MCTargetDesc/PPCMCTargetDesc.h"
12
#include "llvm/ADT/STLExtras.h"
13
#include "llvm/MC/MCELFObjectWriter.h"
14
#include "llvm/MC/MCExpr.h"
15
#include "llvm/MC/MCObjectWriter.h"
16
#include "llvm/MC/MCSymbolELF.h"
17
#include "llvm/MC/MCValue.h"
18
#include "llvm/Support/ErrorHandling.h"
19
20
using namespace llvm;
21
22
namespace {
23
class PPCELFObjectWriter : public MCELFObjectTargetWriter {
24
public:
25
PPCELFObjectWriter(bool Is64Bit, uint8_t OSABI);
26
27
protected:
28
unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
29
const MCFixup &Fixup, bool IsPCRel) const override;
30
31
bool needsRelocateWithSymbol(const MCValue &Val, const MCSymbol &Sym,
32
unsigned Type) const override;
33
};
34
}
35
36
PPCELFObjectWriter::PPCELFObjectWriter(bool Is64Bit, uint8_t OSABI)
37
: MCELFObjectTargetWriter(Is64Bit, OSABI,
38
Is64Bit ? ELF::EM_PPC64 : ELF::EM_PPC,
39
/*HasRelocationAddend*/ true) {}
40
41
static MCSymbolRefExpr::VariantKind getAccessVariant(const MCValue &Target,
42
const MCFixup &Fixup) {
43
const MCExpr *Expr = Fixup.getValue();
44
45
if (Expr->getKind() != MCExpr::Target)
46
return Target.getAccessVariant();
47
48
switch (cast<PPCMCExpr>(Expr)->getKind()) {
49
case PPCMCExpr::VK_PPC_None:
50
return MCSymbolRefExpr::VK_None;
51
case PPCMCExpr::VK_PPC_LO:
52
return MCSymbolRefExpr::VK_PPC_LO;
53
case PPCMCExpr::VK_PPC_HI:
54
return MCSymbolRefExpr::VK_PPC_HI;
55
case PPCMCExpr::VK_PPC_HA:
56
return MCSymbolRefExpr::VK_PPC_HA;
57
case PPCMCExpr::VK_PPC_HIGH:
58
return MCSymbolRefExpr::VK_PPC_HIGH;
59
case PPCMCExpr::VK_PPC_HIGHA:
60
return MCSymbolRefExpr::VK_PPC_HIGHA;
61
case PPCMCExpr::VK_PPC_HIGHERA:
62
return MCSymbolRefExpr::VK_PPC_HIGHERA;
63
case PPCMCExpr::VK_PPC_HIGHER:
64
return MCSymbolRefExpr::VK_PPC_HIGHER;
65
case PPCMCExpr::VK_PPC_HIGHEST:
66
return MCSymbolRefExpr::VK_PPC_HIGHEST;
67
case PPCMCExpr::VK_PPC_HIGHESTA:
68
return MCSymbolRefExpr::VK_PPC_HIGHESTA;
69
}
70
llvm_unreachable("unknown PPCMCExpr kind");
71
}
72
73
unsigned PPCELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target,
74
const MCFixup &Fixup,
75
bool IsPCRel) const {
76
MCFixupKind Kind = Fixup.getKind();
77
if (Kind >= FirstLiteralRelocationKind)
78
return Kind - FirstLiteralRelocationKind;
79
MCSymbolRefExpr::VariantKind Modifier = getAccessVariant(Target, Fixup);
80
81
// determine the type of the relocation
82
unsigned Type;
83
if (IsPCRel) {
84
switch (Fixup.getTargetKind()) {
85
default:
86
llvm_unreachable("Unimplemented");
87
case PPC::fixup_ppc_br24:
88
case PPC::fixup_ppc_br24abs:
89
case PPC::fixup_ppc_br24_notoc:
90
switch (Modifier) {
91
default: llvm_unreachable("Unsupported Modifier");
92
case MCSymbolRefExpr::VK_None:
93
Type = ELF::R_PPC_REL24;
94
break;
95
case MCSymbolRefExpr::VK_PLT:
96
Type = ELF::R_PPC_PLTREL24;
97
break;
98
case MCSymbolRefExpr::VK_PPC_LOCAL:
99
Type = ELF::R_PPC_LOCAL24PC;
100
break;
101
case MCSymbolRefExpr::VK_PPC_NOTOC:
102
Type = ELF::R_PPC64_REL24_NOTOC;
103
break;
104
}
105
break;
106
case PPC::fixup_ppc_brcond14:
107
case PPC::fixup_ppc_brcond14abs:
108
Type = ELF::R_PPC_REL14;
109
break;
110
case PPC::fixup_ppc_half16:
111
switch (Modifier) {
112
default: llvm_unreachable("Unsupported Modifier");
113
case MCSymbolRefExpr::VK_None:
114
Type = ELF::R_PPC_REL16;
115
break;
116
case MCSymbolRefExpr::VK_PPC_LO:
117
Type = ELF::R_PPC_REL16_LO;
118
break;
119
case MCSymbolRefExpr::VK_PPC_HI:
120
Type = ELF::R_PPC_REL16_HI;
121
break;
122
case MCSymbolRefExpr::VK_PPC_HA:
123
Type = ELF::R_PPC_REL16_HA;
124
break;
125
}
126
break;
127
case PPC::fixup_ppc_half16ds:
128
case PPC::fixup_ppc_half16dq:
129
Target.print(errs());
130
errs() << '\n';
131
report_fatal_error("Invalid PC-relative half16ds relocation");
132
case PPC::fixup_ppc_pcrel34:
133
switch (Modifier) {
134
default:
135
llvm_unreachable("Unsupported Modifier for fixup_ppc_pcrel34");
136
case MCSymbolRefExpr::VK_PCREL:
137
Type = ELF::R_PPC64_PCREL34;
138
break;
139
case MCSymbolRefExpr::VK_PPC_GOT_PCREL:
140
Type = ELF::R_PPC64_GOT_PCREL34;
141
break;
142
case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_PCREL:
143
Type = ELF::R_PPC64_GOT_TLSGD_PCREL34;
144
break;
145
case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_PCREL:
146
Type = ELF::R_PPC64_GOT_TLSLD_PCREL34;
147
break;
148
case MCSymbolRefExpr::VK_PPC_GOT_TPREL_PCREL:
149
Type = ELF::R_PPC64_GOT_TPREL_PCREL34;
150
break;
151
}
152
break;
153
case FK_Data_4:
154
case FK_PCRel_4:
155
Type = ELF::R_PPC_REL32;
156
break;
157
case FK_Data_8:
158
case FK_PCRel_8:
159
Type = ELF::R_PPC64_REL64;
160
break;
161
}
162
} else {
163
switch (Fixup.getTargetKind()) {
164
default: llvm_unreachable("invalid fixup kind!");
165
case PPC::fixup_ppc_br24abs:
166
Type = ELF::R_PPC_ADDR24;
167
break;
168
case PPC::fixup_ppc_brcond14abs:
169
Type = ELF::R_PPC_ADDR14; // XXX: or BRNTAKEN?_
170
break;
171
case PPC::fixup_ppc_half16:
172
switch (Modifier) {
173
default: llvm_unreachable("Unsupported Modifier");
174
case MCSymbolRefExpr::VK_None:
175
Type = ELF::R_PPC_ADDR16;
176
break;
177
case MCSymbolRefExpr::VK_PPC_LO:
178
Type = ELF::R_PPC_ADDR16_LO;
179
break;
180
case MCSymbolRefExpr::VK_PPC_HI:
181
Type = ELF::R_PPC_ADDR16_HI;
182
break;
183
case MCSymbolRefExpr::VK_PPC_HA:
184
Type = ELF::R_PPC_ADDR16_HA;
185
break;
186
case MCSymbolRefExpr::VK_PPC_HIGH:
187
Type = ELF::R_PPC64_ADDR16_HIGH;
188
break;
189
case MCSymbolRefExpr::VK_PPC_HIGHA:
190
Type = ELF::R_PPC64_ADDR16_HIGHA;
191
break;
192
case MCSymbolRefExpr::VK_PPC_HIGHER:
193
Type = ELF::R_PPC64_ADDR16_HIGHER;
194
break;
195
case MCSymbolRefExpr::VK_PPC_HIGHERA:
196
Type = ELF::R_PPC64_ADDR16_HIGHERA;
197
break;
198
case MCSymbolRefExpr::VK_PPC_HIGHEST:
199
Type = ELF::R_PPC64_ADDR16_HIGHEST;
200
break;
201
case MCSymbolRefExpr::VK_PPC_HIGHESTA:
202
Type = ELF::R_PPC64_ADDR16_HIGHESTA;
203
break;
204
case MCSymbolRefExpr::VK_GOT:
205
Type = ELF::R_PPC_GOT16;
206
break;
207
case MCSymbolRefExpr::VK_PPC_GOT_LO:
208
Type = ELF::R_PPC_GOT16_LO;
209
break;
210
case MCSymbolRefExpr::VK_PPC_GOT_HI:
211
Type = ELF::R_PPC_GOT16_HI;
212
break;
213
case MCSymbolRefExpr::VK_PPC_GOT_HA:
214
Type = ELF::R_PPC_GOT16_HA;
215
break;
216
case MCSymbolRefExpr::VK_PPC_TOC:
217
Type = ELF::R_PPC64_TOC16;
218
break;
219
case MCSymbolRefExpr::VK_PPC_TOC_LO:
220
Type = ELF::R_PPC64_TOC16_LO;
221
break;
222
case MCSymbolRefExpr::VK_PPC_TOC_HI:
223
Type = ELF::R_PPC64_TOC16_HI;
224
break;
225
case MCSymbolRefExpr::VK_PPC_TOC_HA:
226
Type = ELF::R_PPC64_TOC16_HA;
227
break;
228
case MCSymbolRefExpr::VK_TPREL:
229
Type = ELF::R_PPC_TPREL16;
230
break;
231
case MCSymbolRefExpr::VK_PPC_TPREL_LO:
232
Type = ELF::R_PPC_TPREL16_LO;
233
break;
234
case MCSymbolRefExpr::VK_PPC_TPREL_HI:
235
Type = ELF::R_PPC_TPREL16_HI;
236
break;
237
case MCSymbolRefExpr::VK_PPC_TPREL_HA:
238
Type = ELF::R_PPC_TPREL16_HA;
239
break;
240
case MCSymbolRefExpr::VK_PPC_TPREL_HIGH:
241
Type = ELF::R_PPC64_TPREL16_HIGH;
242
break;
243
case MCSymbolRefExpr::VK_PPC_TPREL_HIGHA:
244
Type = ELF::R_PPC64_TPREL16_HIGHA;
245
break;
246
case MCSymbolRefExpr::VK_PPC_TPREL_HIGHER:
247
Type = ELF::R_PPC64_TPREL16_HIGHER;
248
break;
249
case MCSymbolRefExpr::VK_PPC_TPREL_HIGHERA:
250
Type = ELF::R_PPC64_TPREL16_HIGHERA;
251
break;
252
case MCSymbolRefExpr::VK_PPC_TPREL_HIGHEST:
253
Type = ELF::R_PPC64_TPREL16_HIGHEST;
254
break;
255
case MCSymbolRefExpr::VK_PPC_TPREL_HIGHESTA:
256
Type = ELF::R_PPC64_TPREL16_HIGHESTA;
257
break;
258
case MCSymbolRefExpr::VK_DTPREL:
259
Type = ELF::R_PPC64_DTPREL16;
260
break;
261
case MCSymbolRefExpr::VK_PPC_DTPREL_LO:
262
Type = ELF::R_PPC64_DTPREL16_LO;
263
break;
264
case MCSymbolRefExpr::VK_PPC_DTPREL_HI:
265
Type = ELF::R_PPC64_DTPREL16_HI;
266
break;
267
case MCSymbolRefExpr::VK_PPC_DTPREL_HA:
268
Type = ELF::R_PPC64_DTPREL16_HA;
269
break;
270
case MCSymbolRefExpr::VK_PPC_DTPREL_HIGH:
271
Type = ELF::R_PPC64_DTPREL16_HIGH;
272
break;
273
case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHA:
274
Type = ELF::R_PPC64_DTPREL16_HIGHA;
275
break;
276
case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHER:
277
Type = ELF::R_PPC64_DTPREL16_HIGHER;
278
break;
279
case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHERA:
280
Type = ELF::R_PPC64_DTPREL16_HIGHERA;
281
break;
282
case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHEST:
283
Type = ELF::R_PPC64_DTPREL16_HIGHEST;
284
break;
285
case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHESTA:
286
Type = ELF::R_PPC64_DTPREL16_HIGHESTA;
287
break;
288
case MCSymbolRefExpr::VK_PPC_GOT_TLSGD:
289
if (is64Bit())
290
Type = ELF::R_PPC64_GOT_TLSGD16;
291
else
292
Type = ELF::R_PPC_GOT_TLSGD16;
293
break;
294
case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_LO:
295
Type = ELF::R_PPC64_GOT_TLSGD16_LO;
296
break;
297
case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HI:
298
Type = ELF::R_PPC64_GOT_TLSGD16_HI;
299
break;
300
case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HA:
301
Type = ELF::R_PPC64_GOT_TLSGD16_HA;
302
break;
303
case MCSymbolRefExpr::VK_PPC_GOT_TLSLD:
304
if (is64Bit())
305
Type = ELF::R_PPC64_GOT_TLSLD16;
306
else
307
Type = ELF::R_PPC_GOT_TLSLD16;
308
break;
309
case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO:
310
Type = ELF::R_PPC64_GOT_TLSLD16_LO;
311
break;
312
case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HI:
313
Type = ELF::R_PPC64_GOT_TLSLD16_HI;
314
break;
315
case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HA:
316
Type = ELF::R_PPC64_GOT_TLSLD16_HA;
317
break;
318
case MCSymbolRefExpr::VK_PPC_GOT_TPREL:
319
/* We don't have R_PPC64_GOT_TPREL16, but since GOT offsets
320
are always 4-aligned, we can use R_PPC64_GOT_TPREL16_DS. */
321
Type = ELF::R_PPC64_GOT_TPREL16_DS;
322
break;
323
case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO:
324
/* We don't have R_PPC64_GOT_TPREL16_LO, but since GOT offsets
325
are always 4-aligned, we can use R_PPC64_GOT_TPREL16_LO_DS. */
326
Type = ELF::R_PPC64_GOT_TPREL16_LO_DS;
327
break;
328
case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HI:
329
Type = ELF::R_PPC64_GOT_TPREL16_HI;
330
break;
331
case MCSymbolRefExpr::VK_PPC_GOT_DTPREL:
332
/* We don't have R_PPC64_GOT_DTPREL16, but since GOT offsets
333
are always 4-aligned, we can use R_PPC64_GOT_DTPREL16_DS. */
334
Type = ELF::R_PPC64_GOT_DTPREL16_DS;
335
break;
336
case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO:
337
/* We don't have R_PPC64_GOT_DTPREL16_LO, but since GOT offsets
338
are always 4-aligned, we can use R_PPC64_GOT_DTPREL16_LO_DS. */
339
Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS;
340
break;
341
case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HA:
342
Type = ELF::R_PPC64_GOT_TPREL16_HA;
343
break;
344
case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HI:
345
Type = ELF::R_PPC64_GOT_DTPREL16_HI;
346
break;
347
case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HA:
348
Type = ELF::R_PPC64_GOT_DTPREL16_HA;
349
break;
350
}
351
break;
352
case PPC::fixup_ppc_half16ds:
353
case PPC::fixup_ppc_half16dq:
354
switch (Modifier) {
355
default: llvm_unreachable("Unsupported Modifier");
356
case MCSymbolRefExpr::VK_None:
357
Type = ELF::R_PPC64_ADDR16_DS;
358
break;
359
case MCSymbolRefExpr::VK_PPC_LO:
360
Type = ELF::R_PPC64_ADDR16_LO_DS;
361
break;
362
case MCSymbolRefExpr::VK_GOT:
363
Type = ELF::R_PPC64_GOT16_DS;
364
break;
365
case MCSymbolRefExpr::VK_PPC_GOT_LO:
366
Type = ELF::R_PPC64_GOT16_LO_DS;
367
break;
368
case MCSymbolRefExpr::VK_PPC_TOC:
369
Type = ELF::R_PPC64_TOC16_DS;
370
break;
371
case MCSymbolRefExpr::VK_PPC_TOC_LO:
372
Type = ELF::R_PPC64_TOC16_LO_DS;
373
break;
374
case MCSymbolRefExpr::VK_TPREL:
375
Type = ELF::R_PPC64_TPREL16_DS;
376
break;
377
case MCSymbolRefExpr::VK_PPC_TPREL_LO:
378
Type = ELF::R_PPC64_TPREL16_LO_DS;
379
break;
380
case MCSymbolRefExpr::VK_DTPREL:
381
Type = ELF::R_PPC64_DTPREL16_DS;
382
break;
383
case MCSymbolRefExpr::VK_PPC_DTPREL_LO:
384
Type = ELF::R_PPC64_DTPREL16_LO_DS;
385
break;
386
case MCSymbolRefExpr::VK_PPC_GOT_TPREL:
387
Type = ELF::R_PPC64_GOT_TPREL16_DS;
388
break;
389
case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO:
390
Type = ELF::R_PPC64_GOT_TPREL16_LO_DS;
391
break;
392
case MCSymbolRefExpr::VK_PPC_GOT_DTPREL:
393
Type = ELF::R_PPC64_GOT_DTPREL16_DS;
394
break;
395
case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO:
396
Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS;
397
break;
398
}
399
break;
400
case PPC::fixup_ppc_nofixup:
401
switch (Modifier) {
402
default: llvm_unreachable("Unsupported Modifier");
403
case MCSymbolRefExpr::VK_PPC_TLSGD:
404
if (is64Bit())
405
Type = ELF::R_PPC64_TLSGD;
406
else
407
Type = ELF::R_PPC_TLSGD;
408
break;
409
case MCSymbolRefExpr::VK_PPC_TLSLD:
410
if (is64Bit())
411
Type = ELF::R_PPC64_TLSLD;
412
else
413
Type = ELF::R_PPC_TLSLD;
414
break;
415
case MCSymbolRefExpr::VK_PPC_TLS:
416
if (is64Bit())
417
Type = ELF::R_PPC64_TLS;
418
else
419
Type = ELF::R_PPC_TLS;
420
break;
421
case MCSymbolRefExpr::VK_PPC_TLS_PCREL:
422
Type = ELF::R_PPC64_TLS;
423
break;
424
}
425
break;
426
case PPC::fixup_ppc_imm34:
427
switch (Modifier) {
428
default:
429
report_fatal_error("Unsupported Modifier for fixup_ppc_imm34.");
430
case MCSymbolRefExpr::VK_DTPREL:
431
Type = ELF::R_PPC64_DTPREL34;
432
break;
433
case MCSymbolRefExpr::VK_TPREL:
434
Type = ELF::R_PPC64_TPREL34;
435
break;
436
}
437
break;
438
case FK_Data_8:
439
switch (Modifier) {
440
default: llvm_unreachable("Unsupported Modifier");
441
case MCSymbolRefExpr::VK_PPC_TOCBASE:
442
Type = ELF::R_PPC64_TOC;
443
break;
444
case MCSymbolRefExpr::VK_None:
445
Type = ELF::R_PPC64_ADDR64;
446
break;
447
case MCSymbolRefExpr::VK_PPC_DTPMOD:
448
Type = ELF::R_PPC64_DTPMOD64;
449
break;
450
case MCSymbolRefExpr::VK_TPREL:
451
Type = ELF::R_PPC64_TPREL64;
452
break;
453
case MCSymbolRefExpr::VK_DTPREL:
454
Type = ELF::R_PPC64_DTPREL64;
455
break;
456
}
457
break;
458
case FK_Data_4:
459
switch (Modifier) {
460
case MCSymbolRefExpr::VK_DTPREL:
461
Type = ELF::R_PPC_DTPREL32;
462
break;
463
default:
464
Type = ELF::R_PPC_ADDR32;
465
}
466
break;
467
case FK_Data_2:
468
Type = ELF::R_PPC_ADDR16;
469
break;
470
}
471
}
472
return Type;
473
}
474
475
bool PPCELFObjectWriter::needsRelocateWithSymbol(const MCValue &,
476
const MCSymbol &Sym,
477
unsigned Type) const {
478
switch (Type) {
479
default:
480
return false;
481
482
case ELF::R_PPC_REL24:
483
case ELF::R_PPC64_REL24_NOTOC:
484
// If the target symbol has a local entry point, we must keep the
485
// target symbol to preserve that information for the linker.
486
// The "other" values are stored in the last 6 bits of the second byte.
487
// The traditional defines for STO values assume the full byte and thus
488
// the shift to pack it.
489
unsigned Other = cast<MCSymbolELF>(Sym).getOther() << 2;
490
return (Other & ELF::STO_PPC64_LOCAL_MASK) != 0;
491
}
492
}
493
494
std::unique_ptr<MCObjectTargetWriter>
495
llvm::createPPCELFObjectWriter(bool Is64Bit, uint8_t OSABI) {
496
return std::make_unique<PPCELFObjectWriter>(Is64Bit, OSABI);
497
}
498
499