Coverage Report

Created: 2025-11-11 06:44

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.58k
  : MCELFObjectTargetWriter(Is64Bit, OSABI,
38
5.58k
                            Is64Bit ?  ELF::EM_PPC64 : ELF::EM_PPC,
39
5.58k
                            /*HasRelocationAddend*/ true) {}
40
41
static MCSymbolRefExpr::VariantKind getAccessVariant(const MCValue &Target,
42
14.6k
                                                     const MCFixup &Fixup) {
43
14.6k
  const MCExpr *Expr = Fixup.getValue();
44
45
14.6k
  if (Expr->getKind() != MCExpr::Target)
46
14.6k
    return Target.getAccessVariant();
47
48
47
  switch (cast<PPCMCExpr>(Expr)->getKind()) {
49
0
  case PPCMCExpr::VK_PPC_None:
50
0
    return MCSymbolRefExpr::VK_None;
51
46
  case PPCMCExpr::VK_PPC_LO:
52
46
    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
47
  }
66
47
  llvm_unreachable("unknown PPCMCExpr kind");
67
47
}
68
69
unsigned PPCELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target,
70
                                          const MCFixup &Fixup,
71
14.6k
                                          bool IsPCRel) const {
72
14.6k
  MCSymbolRefExpr::VariantKind Modifier = getAccessVariant(Target, Fixup);
73
74
  // determine the type of the relocation
75
14.6k
  unsigned Type;
76
14.6k
  if (IsPCRel) {
77
1.13k
    switch ((unsigned)Fixup.getKind()) {
78
0
    default:
79
0
      llvm_unreachable("Unimplemented");
80
176
    case PPC::fixup_ppc_br24:
81
177
    case PPC::fixup_ppc_br24abs:
82
177
      switch (Modifier) {
83
0
      default: llvm_unreachable("Unsupported Modifier");
84
177
      case MCSymbolRefExpr::VK_None:
85
177
        Type = ELF::R_PPC_REL24;
86
177
        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
177
      }
94
177
      break;
95
257
    case PPC::fixup_ppc_brcond14:
96
257
    case PPC::fixup_ppc_brcond14abs:
97
257
      Type = ELF::R_PPC_REL14;
98
257
      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
605
    case FK_Data_4:
121
605
    case FK_PCRel_4:
122
605
      Type = ELF::R_PPC_REL32;
123
605
      break;
124
97
    case FK_Data_8:
125
97
    case FK_PCRel_8:
126
97
      Type = ELF::R_PPC64_REL64;
127
97
      break;
128
1.13k
    }
129
13.5k
  } else {
130
13.5k
    switch ((unsigned)Fixup.getKind()) {
131
0
      default: llvm_unreachable("invalid fixup kind!");
132
6
    case PPC::fixup_ppc_br24abs:
133
6
      Type = ELF::R_PPC_ADDR24;
134
6
      break;
135
62
    case PPC::fixup_ppc_brcond14abs:
136
62
      Type = ELF::R_PPC_ADDR14; // XXX: or BRNTAKEN?_
137
62
      break;
138
295
    case PPC::fixup_ppc_half16:
139
295
      switch (Modifier) {
140
0
      default: llvm_unreachable("Unsupported Modifier");
141
240
      case MCSymbolRefExpr::VK_None:
142
240
        Type = ELF::R_PPC_ADDR16;
143
240
        break;
144
46
      case MCSymbolRefExpr::VK_PPC_LO:
145
46
        Type = ELF::R_PPC_ADDR16_LO;
146
46
        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
295
      }
300
295
      break;
301
295
    case PPC::fixup_ppc_half16ds:
302
64
      switch (Modifier) {
303
0
      default: llvm_unreachable("Unsupported Modifier");
304
64
      case MCSymbolRefExpr::VK_None:
305
64
        Type = ELF::R_PPC64_ADDR16_DS;
306
64
        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
64
      }
347
64
      break;
348
64
    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
269
    case FK_Data_8:
372
269
      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
269
      case MCSymbolRefExpr::VK_None:
378
269
        Type = ELF::R_PPC64_ADDR64;
379
269
        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
269
      }
390
269
      break;
391
724
    case FK_Data_4:
392
724
      Type = ELF::R_PPC_ADDR32;
393
724
      break;
394
12.1k
    case FK_Data_2:
395
12.1k
      Type = ELF::R_PPC_ADDR16;
396
12.1k
      break;
397
13.5k
    }
398
13.5k
  }
399
14.6k
  return Type;
400
14.6k
}
401
402
bool PPCELFObjectWriter::needsRelocateWithSymbol(const MCSymbol &Sym,
403
13.5k
                                                 unsigned Type) const {
404
13.5k
  switch (Type) {
405
13.5k
    default:
406
13.5k
      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
13.5k
  }
417
13.5k
}
418
419
MCObjectWriter *llvm_ks::createPPCELFObjectWriter(raw_pwrite_stream &OS,
420
                                               bool Is64Bit,
421
                                               bool IsLittleEndian,
422
5.58k
                                               uint8_t OSABI) {
423
5.58k
  MCELFObjectTargetWriter *MOTW = new PPCELFObjectWriter(Is64Bit, OSABI);
424
5.58k
  return createELFObjectWriter(MOTW, OS, IsLittleEndian);
425
5.58k
}