Coverage Report

Created: 2025-12-27 06:12

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/keystone/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp
Line
Count
Source
1
//===-- PPCELFObjectWriter.cpp - PPC ELF Writer ---------------------------===//
2
//
3
//                     The LLVM Compiler Infrastructure
4
//
5
// This file is distributed under the University of Illinois Open Source
6
// License. See LICENSE.TXT for details.
7
//
8
//===----------------------------------------------------------------------===//
9
10
#include "MCTargetDesc/PPCMCTargetDesc.h"
11
#include "MCTargetDesc/PPCFixupKinds.h"
12
#include "MCTargetDesc/PPCMCExpr.h"
13
#include "llvm/ADT/STLExtras.h"
14
#include "llvm/MC/MCELFObjectWriter.h"
15
#include "llvm/MC/MCExpr.h"
16
#include "llvm/MC/MCSymbolELF.h"
17
#include "llvm/MC/MCValue.h"
18
#include "llvm/Support/ErrorHandling.h"
19
20
using namespace llvm_ks;
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 MCSymbol &Sym,
32
                                 unsigned Type) const override;
33
  };
34
}
35
36
PPCELFObjectWriter::PPCELFObjectWriter(bool Is64Bit, uint8_t OSABI)
37
5.77k
  : MCELFObjectTargetWriter(Is64Bit, OSABI,
38
5.77k
                            Is64Bit ?  ELF::EM_PPC64 : ELF::EM_PPC,
39
5.77k
                            /*HasRelocationAddend*/ true) {}
40
41
static MCSymbolRefExpr::VariantKind getAccessVariant(const MCValue &Target,
42
13.1k
                                                     const MCFixup &Fixup) {
43
13.1k
  const MCExpr *Expr = Fixup.getValue();
44
45
13.1k
  if (Expr->getKind() != MCExpr::Target)
46
13.0k
    return Target.getAccessVariant();
47
48
45
  switch (cast<PPCMCExpr>(Expr)->getKind()) {
49
0
  case PPCMCExpr::VK_PPC_None:
50
0
    return MCSymbolRefExpr::VK_None;
51
44
  case PPCMCExpr::VK_PPC_LO:
52
44
    return MCSymbolRefExpr::VK_PPC_LO;
53
1
  case PPCMCExpr::VK_PPC_HI:
54
1
    return MCSymbolRefExpr::VK_PPC_HI;
55
0
  case PPCMCExpr::VK_PPC_HA:
56
0
    return MCSymbolRefExpr::VK_PPC_HA;
57
0
  case PPCMCExpr::VK_PPC_HIGHERA:
58
0
    return MCSymbolRefExpr::VK_PPC_HIGHERA;
59
0
  case PPCMCExpr::VK_PPC_HIGHER:
60
0
    return MCSymbolRefExpr::VK_PPC_HIGHER;
61
0
  case PPCMCExpr::VK_PPC_HIGHEST:
62
0
    return MCSymbolRefExpr::VK_PPC_HIGHEST;
63
0
  case PPCMCExpr::VK_PPC_HIGHESTA:
64
0
    return MCSymbolRefExpr::VK_PPC_HIGHESTA;
65
45
  }
66
45
  llvm_unreachable("unknown PPCMCExpr kind");
67
45
}
68
69
unsigned PPCELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target,
70
                                          const MCFixup &Fixup,
71
13.1k
                                          bool IsPCRel) const {
72
13.1k
  MCSymbolRefExpr::VariantKind Modifier = getAccessVariant(Target, Fixup);
73
74
  // determine the type of the relocation
75
13.1k
  unsigned Type;
76
13.1k
  if (IsPCRel) {
77
1.09k
    switch ((unsigned)Fixup.getKind()) {
78
0
    default:
79
0
      llvm_unreachable("Unimplemented");
80
119
    case PPC::fixup_ppc_br24:
81
120
    case PPC::fixup_ppc_br24abs:
82
120
      switch (Modifier) {
83
0
      default: llvm_unreachable("Unsupported Modifier");
84
120
      case MCSymbolRefExpr::VK_None:
85
120
        Type = ELF::R_PPC_REL24;
86
120
        break;
87
0
      case MCSymbolRefExpr::VK_PLT:
88
0
        Type = ELF::R_PPC_PLTREL24;
89
0
        break;
90
0
      case MCSymbolRefExpr::VK_PPC_LOCAL:
91
0
        Type = ELF::R_PPC_LOCAL24PC;
92
0
        break;
93
120
      }
94
120
      break;
95
282
    case PPC::fixup_ppc_brcond14:
96
283
    case PPC::fixup_ppc_brcond14abs:
97
283
      Type = ELF::R_PPC_REL14;
98
283
      break;
99
0
    case PPC::fixup_ppc_half16:
100
0
      switch (Modifier) {
101
0
      default: llvm_unreachable("Unsupported Modifier");
102
0
      case MCSymbolRefExpr::VK_None:
103
0
        Type = ELF::R_PPC_REL16;
104
0
        break;
105
0
      case MCSymbolRefExpr::VK_PPC_LO:
106
0
        Type = ELF::R_PPC_REL16_LO;
107
0
        break;
108
0
      case MCSymbolRefExpr::VK_PPC_HI:
109
0
        Type = ELF::R_PPC_REL16_HI;
110
0
        break;
111
0
      case MCSymbolRefExpr::VK_PPC_HA:
112
0
        Type = ELF::R_PPC_REL16_HA;
113
0
        break;
114
0
      }
115
0
      break;
116
0
    case PPC::fixup_ppc_half16ds:
117
0
      Target.print(errs());
118
0
      errs() << '\n';
119
0
      report_fatal_error("Invalid PC-relative half16ds relocation");
120
647
    case FK_Data_4:
121
647
    case FK_PCRel_4:
122
647
      Type = ELF::R_PPC_REL32;
123
647
      break;
124
42
    case FK_Data_8:
125
42
    case FK_PCRel_8:
126
42
      Type = ELF::R_PPC64_REL64;
127
42
      break;
128
1.09k
    }
129
12.0k
  } else {
130
12.0k
    switch ((unsigned)Fixup.getKind()) {
131
0
      default: llvm_unreachable("invalid fixup kind!");
132
9
    case PPC::fixup_ppc_br24abs:
133
9
      Type = ELF::R_PPC_ADDR24;
134
9
      break;
135
59
    case PPC::fixup_ppc_brcond14abs:
136
59
      Type = ELF::R_PPC_ADDR14; // XXX: or BRNTAKEN?_
137
59
      break;
138
296
    case PPC::fixup_ppc_half16:
139
296
      switch (Modifier) {
140
0
      default: llvm_unreachable("Unsupported Modifier");
141
243
      case MCSymbolRefExpr::VK_None:
142
243
        Type = ELF::R_PPC_ADDR16;
143
243
        break;
144
44
      case MCSymbolRefExpr::VK_PPC_LO:
145
44
        Type = ELF::R_PPC_ADDR16_LO;
146
44
        break;
147
1
      case MCSymbolRefExpr::VK_PPC_HI:
148
1
        Type = ELF::R_PPC_ADDR16_HI;
149
1
        break;
150
0
      case MCSymbolRefExpr::VK_PPC_HA:
151
0
        Type = ELF::R_PPC_ADDR16_HA;
152
0
        break;
153
0
      case MCSymbolRefExpr::VK_PPC_HIGHER:
154
0
        Type = ELF::R_PPC64_ADDR16_HIGHER;
155
0
        break;
156
0
      case MCSymbolRefExpr::VK_PPC_HIGHERA:
157
0
        Type = ELF::R_PPC64_ADDR16_HIGHERA;
158
0
        break;
159
0
      case MCSymbolRefExpr::VK_PPC_HIGHEST:
160
0
        Type = ELF::R_PPC64_ADDR16_HIGHEST;
161
0
        break;
162
0
      case MCSymbolRefExpr::VK_PPC_HIGHESTA:
163
0
        Type = ELF::R_PPC64_ADDR16_HIGHESTA;
164
0
        break;
165
0
      case MCSymbolRefExpr::VK_GOT:
166
0
        Type = ELF::R_PPC_GOT16;
167
0
        break;
168
0
      case MCSymbolRefExpr::VK_PPC_GOT_LO:
169
0
        Type = ELF::R_PPC_GOT16_LO;
170
0
        break;
171
0
      case MCSymbolRefExpr::VK_PPC_GOT_HI:
172
0
        Type = ELF::R_PPC_GOT16_HI;
173
0
        break;
174
0
      case MCSymbolRefExpr::VK_PPC_GOT_HA:
175
0
        Type = ELF::R_PPC_GOT16_HA;
176
0
        break;
177
0
      case MCSymbolRefExpr::VK_PPC_TOC:
178
0
        Type = ELF::R_PPC64_TOC16;
179
0
        break;
180
0
      case MCSymbolRefExpr::VK_PPC_TOC_LO:
181
0
        Type = ELF::R_PPC64_TOC16_LO;
182
0
        break;
183
0
      case MCSymbolRefExpr::VK_PPC_TOC_HI:
184
0
        Type = ELF::R_PPC64_TOC16_HI;
185
0
        break;
186
0
      case MCSymbolRefExpr::VK_PPC_TOC_HA:
187
0
        Type = ELF::R_PPC64_TOC16_HA;
188
0
        break;
189
0
      case MCSymbolRefExpr::VK_PPC_TPREL:
190
0
        Type = ELF::R_PPC_TPREL16;
191
0
        break;
192
0
      case MCSymbolRefExpr::VK_PPC_TPREL_LO:
193
0
        Type = ELF::R_PPC_TPREL16_LO;
194
0
        break;
195
0
      case MCSymbolRefExpr::VK_PPC_TPREL_HI:
196
0
        Type = ELF::R_PPC_TPREL16_HI;
197
0
        break;
198
0
      case MCSymbolRefExpr::VK_PPC_TPREL_HA:
199
0
        Type = ELF::R_PPC_TPREL16_HA;
200
0
        break;
201
0
      case MCSymbolRefExpr::VK_PPC_TPREL_HIGHER:
202
0
        Type = ELF::R_PPC64_TPREL16_HIGHER;
203
0
        break;
204
0
      case MCSymbolRefExpr::VK_PPC_TPREL_HIGHERA:
205
0
        Type = ELF::R_PPC64_TPREL16_HIGHERA;
206
0
        break;
207
0
      case MCSymbolRefExpr::VK_PPC_TPREL_HIGHEST:
208
0
        Type = ELF::R_PPC64_TPREL16_HIGHEST;
209
0
        break;
210
0
      case MCSymbolRefExpr::VK_PPC_TPREL_HIGHESTA:
211
0
        Type = ELF::R_PPC64_TPREL16_HIGHESTA;
212
0
        break;
213
8
      case MCSymbolRefExpr::VK_PPC_DTPREL:
214
8
        Type = ELF::R_PPC64_DTPREL16;
215
8
        break;
216
0
      case MCSymbolRefExpr::VK_PPC_DTPREL_LO:
217
0
        Type = ELF::R_PPC64_DTPREL16_LO;
218
0
        break;
219
0
      case MCSymbolRefExpr::VK_PPC_DTPREL_HI:
220
0
        Type = ELF::R_PPC64_DTPREL16_HI;
221
0
        break;
222
0
      case MCSymbolRefExpr::VK_PPC_DTPREL_HA:
223
0
        Type = ELF::R_PPC64_DTPREL16_HA;
224
0
        break;
225
0
      case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHER:
226
0
        Type = ELF::R_PPC64_DTPREL16_HIGHER;
227
0
        break;
228
0
      case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHERA:
229
0
        Type = ELF::R_PPC64_DTPREL16_HIGHERA;
230
0
        break;
231
0
      case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHEST:
232
0
        Type = ELF::R_PPC64_DTPREL16_HIGHEST;
233
0
        break;
234
0
      case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHESTA:
235
0
        Type = ELF::R_PPC64_DTPREL16_HIGHESTA;
236
0
        break;
237
0
      case MCSymbolRefExpr::VK_PPC_GOT_TLSGD:
238
0
        if (is64Bit())
239
0
          Type = ELF::R_PPC64_GOT_TLSGD16;
240
0
        else
241
0
          Type = ELF::R_PPC_GOT_TLSGD16;
242
0
        break;
243
0
      case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_LO:
244
0
        Type = ELF::R_PPC64_GOT_TLSGD16_LO;
245
0
        break;
246
0
      case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HI:
247
0
        Type = ELF::R_PPC64_GOT_TLSGD16_HI;
248
0
        break;
249
0
      case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HA:
250
0
        Type = ELF::R_PPC64_GOT_TLSGD16_HA;
251
0
        break;
252
0
      case MCSymbolRefExpr::VK_PPC_GOT_TLSLD:
253
0
        if (is64Bit())
254
0
          Type = ELF::R_PPC64_GOT_TLSLD16;
255
0
        else
256
0
          Type = ELF::R_PPC_GOT_TLSLD16;
257
0
        break;
258
0
      case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO:
259
0
        Type = ELF::R_PPC64_GOT_TLSLD16_LO;
260
0
        break;
261
0
      case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HI:
262
0
        Type = ELF::R_PPC64_GOT_TLSLD16_HI;
263
0
        break;
264
0
      case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HA:
265
0
        Type = ELF::R_PPC64_GOT_TLSLD16_HA;
266
0
        break;
267
0
      case MCSymbolRefExpr::VK_PPC_GOT_TPREL:
268
        /* We don't have R_PPC64_GOT_TPREL16, but since GOT offsets
269
           are always 4-aligned, we can use R_PPC64_GOT_TPREL16_DS.  */
270
0
        Type = ELF::R_PPC64_GOT_TPREL16_DS;
271
0
        break;
272
0
      case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO:
273
        /* We don't have R_PPC64_GOT_TPREL16_LO, but since GOT offsets
274
           are always 4-aligned, we can use R_PPC64_GOT_TPREL16_LO_DS.  */
275
0
        Type = ELF::R_PPC64_GOT_TPREL16_LO_DS;
276
0
        break;
277
0
      case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HI:
278
0
        Type = ELF::R_PPC64_GOT_TPREL16_HI;
279
0
        break;
280
0
      case MCSymbolRefExpr::VK_PPC_GOT_DTPREL:
281
        /* We don't have R_PPC64_GOT_DTPREL16, but since GOT offsets
282
           are always 4-aligned, we can use R_PPC64_GOT_DTPREL16_DS.  */
283
0
        Type = ELF::R_PPC64_GOT_DTPREL16_DS;
284
0
        break;
285
0
      case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO:
286
        /* We don't have R_PPC64_GOT_DTPREL16_LO, but since GOT offsets
287
           are always 4-aligned, we can use R_PPC64_GOT_DTPREL16_LO_DS.  */
288
0
        Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS;
289
0
        break;
290
0
      case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HA:
291
0
        Type = ELF::R_PPC64_GOT_TPREL16_HA;
292
0
        break;
293
0
      case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HI:
294
0
        Type = ELF::R_PPC64_GOT_DTPREL16_HI;
295
0
        break;
296
0
      case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HA:
297
0
        Type = ELF::R_PPC64_GOT_DTPREL16_HA;
298
0
        break;
299
296
      }
300
296
      break;
301
296
    case PPC::fixup_ppc_half16ds:
302
41
      switch (Modifier) {
303
0
      default: llvm_unreachable("Unsupported Modifier");
304
41
      case MCSymbolRefExpr::VK_None:
305
41
        Type = ELF::R_PPC64_ADDR16_DS;
306
41
        break;
307
0
      case MCSymbolRefExpr::VK_PPC_LO:
308
0
        Type = ELF::R_PPC64_ADDR16_LO_DS;
309
0
        break;
310
0
      case MCSymbolRefExpr::VK_GOT:
311
0
        Type = ELF::R_PPC64_GOT16_DS;
312
0
        break;
313
0
      case MCSymbolRefExpr::VK_PPC_GOT_LO:
314
0
        Type = ELF::R_PPC64_GOT16_LO_DS;
315
0
        break;
316
0
      case MCSymbolRefExpr::VK_PPC_TOC:
317
0
        Type = ELF::R_PPC64_TOC16_DS;
318
0
        break;
319
0
      case MCSymbolRefExpr::VK_PPC_TOC_LO:
320
0
        Type = ELF::R_PPC64_TOC16_LO_DS;
321
0
        break;
322
0
      case MCSymbolRefExpr::VK_PPC_TPREL:
323
0
        Type = ELF::R_PPC64_TPREL16_DS;
324
0
        break;
325
0
      case MCSymbolRefExpr::VK_PPC_TPREL_LO:
326
0
        Type = ELF::R_PPC64_TPREL16_LO_DS;
327
0
        break;
328
0
      case MCSymbolRefExpr::VK_PPC_DTPREL:
329
0
        Type = ELF::R_PPC64_DTPREL16_DS;
330
0
        break;
331
0
      case MCSymbolRefExpr::VK_PPC_DTPREL_LO:
332
0
        Type = ELF::R_PPC64_DTPREL16_LO_DS;
333
0
        break;
334
0
      case MCSymbolRefExpr::VK_PPC_GOT_TPREL:
335
0
        Type = ELF::R_PPC64_GOT_TPREL16_DS;
336
0
        break;
337
0
      case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO:
338
0
        Type = ELF::R_PPC64_GOT_TPREL16_LO_DS;
339
0
        break;
340
0
      case MCSymbolRefExpr::VK_PPC_GOT_DTPREL:
341
0
        Type = ELF::R_PPC64_GOT_DTPREL16_DS;
342
0
        break;
343
0
      case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO:
344
0
        Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS;
345
0
        break;
346
41
      }
347
41
      break;
348
41
    case PPC::fixup_ppc_nofixup:
349
0
      switch (Modifier) {
350
0
      default: llvm_unreachable("Unsupported Modifier");
351
0
      case MCSymbolRefExpr::VK_PPC_TLSGD:
352
0
        if (is64Bit())
353
0
          Type = ELF::R_PPC64_TLSGD;
354
0
        else
355
0
          Type = ELF::R_PPC_TLSGD;
356
0
        break;
357
0
      case MCSymbolRefExpr::VK_PPC_TLSLD:
358
0
        if (is64Bit())
359
0
          Type = ELF::R_PPC64_TLSLD;
360
0
        else
361
0
          Type = ELF::R_PPC_TLSLD;
362
0
        break;
363
0
      case MCSymbolRefExpr::VK_PPC_TLS:
364
0
        if (is64Bit())
365
0
          Type = ELF::R_PPC64_TLS;
366
0
        else
367
0
          Type = ELF::R_PPC_TLS;
368
0
        break;
369
0
      }
370
0
      break;
371
225
    case FK_Data_8:
372
225
      switch (Modifier) {
373
0
      default: llvm_unreachable("Unsupported Modifier");
374
0
      case MCSymbolRefExpr::VK_PPC_TOCBASE:
375
0
        Type = ELF::R_PPC64_TOC;
376
0
        break;
377
225
      case MCSymbolRefExpr::VK_None:
378
225
        Type = ELF::R_PPC64_ADDR64;
379
225
        break;
380
0
      case MCSymbolRefExpr::VK_PPC_DTPMOD:
381
0
        Type = ELF::R_PPC64_DTPMOD64;
382
0
        break;
383
0
      case MCSymbolRefExpr::VK_PPC_TPREL:
384
0
        Type = ELF::R_PPC64_TPREL64;
385
0
        break;
386
0
      case MCSymbolRefExpr::VK_PPC_DTPREL:
387
0
        Type = ELF::R_PPC64_DTPREL64;
388
0
        break;
389
225
      }
390
225
      break;
391
619
    case FK_Data_4:
392
619
      Type = ELF::R_PPC_ADDR32;
393
619
      break;
394
10.7k
    case FK_Data_2:
395
10.7k
      Type = ELF::R_PPC_ADDR16;
396
10.7k
      break;
397
12.0k
    }
398
12.0k
  }
399
13.1k
  return Type;
400
13.1k
}
401
402
bool PPCELFObjectWriter::needsRelocateWithSymbol(const MCSymbol &Sym,
403
12.0k
                                                 unsigned Type) const {
404
12.0k
  switch (Type) {
405
12.0k
    default:
406
12.0k
      return false;
407
408
0
    case ELF::R_PPC_REL24:
409
      // If the target symbol has a local entry point, we must keep the
410
      // target symbol to preserve that information for the linker.
411
      // The "other" values are stored in the last 6 bits of the second byte.
412
      // The traditional defines for STO values assume the full byte and thus
413
      // the shift to pack it.
414
0
      unsigned Other = cast<MCSymbolELF>(Sym).getOther() << 2;
415
0
      return (Other & ELF::STO_PPC64_LOCAL_MASK) != 0;
416
12.0k
  }
417
12.0k
}
418
419
MCObjectWriter *llvm_ks::createPPCELFObjectWriter(raw_pwrite_stream &OS,
420
                                               bool Is64Bit,
421
                                               bool IsLittleEndian,
422
5.77k
                                               uint8_t OSABI) {
423
5.77k
  MCELFObjectTargetWriter *MOTW = new PPCELFObjectWriter(Is64Bit, OSABI);
424
5.77k
  return createELFObjectWriter(MOTW, OS, IsLittleEndian);
425
5.77k
}