PPCELFObjectWriter.cpp revision 360784
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
20using namespace llvm;
21
22namespace {
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
36PPCELFObjectWriter::PPCELFObjectWriter(bool Is64Bit, uint8_t OSABI)
37  : MCELFObjectTargetWriter(Is64Bit, OSABI,
38                            Is64Bit ?  ELF::EM_PPC64 : ELF::EM_PPC,
39                            /*HasRelocationAddend*/ true) {}
40
41static 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
73unsigned PPCELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target,
74                                          const MCFixup &Fixup,
75                                          bool IsPCRel) const {
76  MCSymbolRefExpr::VariantKind Modifier = getAccessVariant(Target, Fixup);
77
78  // determine the type of the relocation
79  unsigned Type;
80  if (IsPCRel) {
81    switch (Fixup.getTargetKind()) {
82    default:
83      llvm_unreachable("Unimplemented");
84    case PPC::fixup_ppc_br24:
85    case PPC::fixup_ppc_br24abs:
86      switch (Modifier) {
87      default: llvm_unreachable("Unsupported Modifier");
88      case MCSymbolRefExpr::VK_None:
89        Type = ELF::R_PPC_REL24;
90        break;
91      case MCSymbolRefExpr::VK_PLT:
92        Type = ELF::R_PPC_PLTREL24;
93        break;
94      case MCSymbolRefExpr::VK_PPC_LOCAL:
95        Type = ELF::R_PPC_LOCAL24PC;
96        break;
97      }
98      break;
99    case PPC::fixup_ppc_brcond14:
100    case PPC::fixup_ppc_brcond14abs:
101      Type = ELF::R_PPC_REL14;
102      break;
103    case PPC::fixup_ppc_half16:
104      switch (Modifier) {
105      default: llvm_unreachable("Unsupported Modifier");
106      case MCSymbolRefExpr::VK_None:
107        Type = ELF::R_PPC_REL16;
108        break;
109      case MCSymbolRefExpr::VK_PPC_LO:
110        Type = ELF::R_PPC_REL16_LO;
111        break;
112      case MCSymbolRefExpr::VK_PPC_HI:
113        Type = ELF::R_PPC_REL16_HI;
114        break;
115      case MCSymbolRefExpr::VK_PPC_HA:
116        Type = ELF::R_PPC_REL16_HA;
117        break;
118      }
119      break;
120    case PPC::fixup_ppc_half16ds:
121      Target.print(errs());
122      errs() << '\n';
123      report_fatal_error("Invalid PC-relative half16ds relocation");
124    case FK_Data_4:
125    case FK_PCRel_4:
126      Type = ELF::R_PPC_REL32;
127      break;
128    case FK_Data_8:
129    case FK_PCRel_8:
130      Type = ELF::R_PPC64_REL64;
131      break;
132    }
133  } else {
134    switch (Fixup.getTargetKind()) {
135      default: llvm_unreachable("invalid fixup kind!");
136    case FK_NONE:
137      Type = ELF::R_PPC_NONE;
138      break;
139    case PPC::fixup_ppc_br24abs:
140      Type = ELF::R_PPC_ADDR24;
141      break;
142    case PPC::fixup_ppc_brcond14abs:
143      Type = ELF::R_PPC_ADDR14; // XXX: or BRNTAKEN?_
144      break;
145    case PPC::fixup_ppc_half16:
146      switch (Modifier) {
147      default: llvm_unreachable("Unsupported Modifier");
148      case MCSymbolRefExpr::VK_None:
149        Type = ELF::R_PPC_ADDR16;
150        break;
151      case MCSymbolRefExpr::VK_PPC_LO:
152        Type = ELF::R_PPC_ADDR16_LO;
153        break;
154      case MCSymbolRefExpr::VK_PPC_HI:
155        Type = ELF::R_PPC_ADDR16_HI;
156        break;
157      case MCSymbolRefExpr::VK_PPC_HA:
158        Type = ELF::R_PPC_ADDR16_HA;
159        break;
160      case MCSymbolRefExpr::VK_PPC_HIGH:
161        Type = ELF::R_PPC64_ADDR16_HIGH;
162        break;
163      case MCSymbolRefExpr::VK_PPC_HIGHA:
164        Type = ELF::R_PPC64_ADDR16_HIGHA;
165        break;
166      case MCSymbolRefExpr::VK_PPC_HIGHER:
167        Type = ELF::R_PPC64_ADDR16_HIGHER;
168        break;
169      case MCSymbolRefExpr::VK_PPC_HIGHERA:
170        Type = ELF::R_PPC64_ADDR16_HIGHERA;
171        break;
172      case MCSymbolRefExpr::VK_PPC_HIGHEST:
173        Type = ELF::R_PPC64_ADDR16_HIGHEST;
174        break;
175      case MCSymbolRefExpr::VK_PPC_HIGHESTA:
176        Type = ELF::R_PPC64_ADDR16_HIGHESTA;
177        break;
178      case MCSymbolRefExpr::VK_GOT:
179        Type = ELF::R_PPC_GOT16;
180        break;
181      case MCSymbolRefExpr::VK_PPC_GOT_LO:
182        Type = ELF::R_PPC_GOT16_LO;
183        break;
184      case MCSymbolRefExpr::VK_PPC_GOT_HI:
185        Type = ELF::R_PPC_GOT16_HI;
186        break;
187      case MCSymbolRefExpr::VK_PPC_GOT_HA:
188        Type = ELF::R_PPC_GOT16_HA;
189        break;
190      case MCSymbolRefExpr::VK_PPC_TOC:
191        Type = ELF::R_PPC64_TOC16;
192        break;
193      case MCSymbolRefExpr::VK_PPC_TOC_LO:
194        Type = ELF::R_PPC64_TOC16_LO;
195        break;
196      case MCSymbolRefExpr::VK_PPC_TOC_HI:
197        Type = ELF::R_PPC64_TOC16_HI;
198        break;
199      case MCSymbolRefExpr::VK_PPC_TOC_HA:
200        Type = ELF::R_PPC64_TOC16_HA;
201        break;
202      case MCSymbolRefExpr::VK_TPREL:
203        Type = ELF::R_PPC_TPREL16;
204        break;
205      case MCSymbolRefExpr::VK_PPC_TPREL_LO:
206        Type = ELF::R_PPC_TPREL16_LO;
207        break;
208      case MCSymbolRefExpr::VK_PPC_TPREL_HI:
209        Type = ELF::R_PPC_TPREL16_HI;
210        break;
211      case MCSymbolRefExpr::VK_PPC_TPREL_HA:
212        Type = ELF::R_PPC_TPREL16_HA;
213        break;
214      case MCSymbolRefExpr::VK_PPC_TPREL_HIGH:
215        Type = ELF::R_PPC64_TPREL16_HIGH;
216        break;
217      case MCSymbolRefExpr::VK_PPC_TPREL_HIGHA:
218        Type = ELF::R_PPC64_TPREL16_HIGHA;
219        break;
220      case MCSymbolRefExpr::VK_PPC_TPREL_HIGHER:
221        Type = ELF::R_PPC64_TPREL16_HIGHER;
222        break;
223      case MCSymbolRefExpr::VK_PPC_TPREL_HIGHERA:
224        Type = ELF::R_PPC64_TPREL16_HIGHERA;
225        break;
226      case MCSymbolRefExpr::VK_PPC_TPREL_HIGHEST:
227        Type = ELF::R_PPC64_TPREL16_HIGHEST;
228        break;
229      case MCSymbolRefExpr::VK_PPC_TPREL_HIGHESTA:
230        Type = ELF::R_PPC64_TPREL16_HIGHESTA;
231        break;
232      case MCSymbolRefExpr::VK_DTPREL:
233        Type = ELF::R_PPC64_DTPREL16;
234        break;
235      case MCSymbolRefExpr::VK_PPC_DTPREL_LO:
236        Type = ELF::R_PPC64_DTPREL16_LO;
237        break;
238      case MCSymbolRefExpr::VK_PPC_DTPREL_HI:
239        Type = ELF::R_PPC64_DTPREL16_HI;
240        break;
241      case MCSymbolRefExpr::VK_PPC_DTPREL_HA:
242        Type = ELF::R_PPC64_DTPREL16_HA;
243        break;
244      case MCSymbolRefExpr::VK_PPC_DTPREL_HIGH:
245        Type = ELF::R_PPC64_DTPREL16_HIGH;
246        break;
247      case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHA:
248        Type = ELF::R_PPC64_DTPREL16_HIGHA;
249        break;
250      case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHER:
251        Type = ELF::R_PPC64_DTPREL16_HIGHER;
252        break;
253      case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHERA:
254        Type = ELF::R_PPC64_DTPREL16_HIGHERA;
255        break;
256      case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHEST:
257        Type = ELF::R_PPC64_DTPREL16_HIGHEST;
258        break;
259      case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHESTA:
260        Type = ELF::R_PPC64_DTPREL16_HIGHESTA;
261        break;
262      case MCSymbolRefExpr::VK_PPC_GOT_TLSGD:
263        if (is64Bit())
264          Type = ELF::R_PPC64_GOT_TLSGD16;
265        else
266          Type = ELF::R_PPC_GOT_TLSGD16;
267        break;
268      case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_LO:
269        Type = ELF::R_PPC64_GOT_TLSGD16_LO;
270        break;
271      case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HI:
272        Type = ELF::R_PPC64_GOT_TLSGD16_HI;
273        break;
274      case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HA:
275        Type = ELF::R_PPC64_GOT_TLSGD16_HA;
276        break;
277      case MCSymbolRefExpr::VK_PPC_GOT_TLSLD:
278        if (is64Bit())
279          Type = ELF::R_PPC64_GOT_TLSLD16;
280        else
281          Type = ELF::R_PPC_GOT_TLSLD16;
282        break;
283      case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO:
284        Type = ELF::R_PPC64_GOT_TLSLD16_LO;
285        break;
286      case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HI:
287        Type = ELF::R_PPC64_GOT_TLSLD16_HI;
288        break;
289      case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HA:
290        Type = ELF::R_PPC64_GOT_TLSLD16_HA;
291        break;
292      case MCSymbolRefExpr::VK_PPC_GOT_TPREL:
293        /* We don't have R_PPC64_GOT_TPREL16, but since GOT offsets
294           are always 4-aligned, we can use R_PPC64_GOT_TPREL16_DS.  */
295        Type = ELF::R_PPC64_GOT_TPREL16_DS;
296        break;
297      case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO:
298        /* We don't have R_PPC64_GOT_TPREL16_LO, but since GOT offsets
299           are always 4-aligned, we can use R_PPC64_GOT_TPREL16_LO_DS.  */
300        Type = ELF::R_PPC64_GOT_TPREL16_LO_DS;
301        break;
302      case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HI:
303        Type = ELF::R_PPC64_GOT_TPREL16_HI;
304        break;
305      case MCSymbolRefExpr::VK_PPC_GOT_DTPREL:
306        /* We don't have R_PPC64_GOT_DTPREL16, but since GOT offsets
307           are always 4-aligned, we can use R_PPC64_GOT_DTPREL16_DS.  */
308        Type = ELF::R_PPC64_GOT_DTPREL16_DS;
309        break;
310      case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO:
311        /* We don't have R_PPC64_GOT_DTPREL16_LO, but since GOT offsets
312           are always 4-aligned, we can use R_PPC64_GOT_DTPREL16_LO_DS.  */
313        Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS;
314        break;
315      case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HA:
316        Type = ELF::R_PPC64_GOT_TPREL16_HA;
317        break;
318      case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HI:
319        Type = ELF::R_PPC64_GOT_DTPREL16_HI;
320        break;
321      case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HA:
322        Type = ELF::R_PPC64_GOT_DTPREL16_HA;
323        break;
324      }
325      break;
326    case PPC::fixup_ppc_half16ds:
327      switch (Modifier) {
328      default: llvm_unreachable("Unsupported Modifier");
329      case MCSymbolRefExpr::VK_None:
330        Type = ELF::R_PPC64_ADDR16_DS;
331        break;
332      case MCSymbolRefExpr::VK_PPC_LO:
333        Type = ELF::R_PPC64_ADDR16_LO_DS;
334        break;
335      case MCSymbolRefExpr::VK_GOT:
336        Type = ELF::R_PPC64_GOT16_DS;
337        break;
338      case MCSymbolRefExpr::VK_PPC_GOT_LO:
339        Type = ELF::R_PPC64_GOT16_LO_DS;
340        break;
341      case MCSymbolRefExpr::VK_PPC_TOC:
342        Type = ELF::R_PPC64_TOC16_DS;
343        break;
344      case MCSymbolRefExpr::VK_PPC_TOC_LO:
345        Type = ELF::R_PPC64_TOC16_LO_DS;
346        break;
347      case MCSymbolRefExpr::VK_TPREL:
348        Type = ELF::R_PPC64_TPREL16_DS;
349        break;
350      case MCSymbolRefExpr::VK_PPC_TPREL_LO:
351        Type = ELF::R_PPC64_TPREL16_LO_DS;
352        break;
353      case MCSymbolRefExpr::VK_DTPREL:
354        Type = ELF::R_PPC64_DTPREL16_DS;
355        break;
356      case MCSymbolRefExpr::VK_PPC_DTPREL_LO:
357        Type = ELF::R_PPC64_DTPREL16_LO_DS;
358        break;
359      case MCSymbolRefExpr::VK_PPC_GOT_TPREL:
360        Type = ELF::R_PPC64_GOT_TPREL16_DS;
361        break;
362      case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO:
363        Type = ELF::R_PPC64_GOT_TPREL16_LO_DS;
364        break;
365      case MCSymbolRefExpr::VK_PPC_GOT_DTPREL:
366        Type = ELF::R_PPC64_GOT_DTPREL16_DS;
367        break;
368      case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO:
369        Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS;
370        break;
371      }
372      break;
373    case PPC::fixup_ppc_nofixup:
374      switch (Modifier) {
375      default: llvm_unreachable("Unsupported Modifier");
376      case MCSymbolRefExpr::VK_PPC_TLSGD:
377        if (is64Bit())
378          Type = ELF::R_PPC64_TLSGD;
379        else
380          Type = ELF::R_PPC_TLSGD;
381        break;
382      case MCSymbolRefExpr::VK_PPC_TLSLD:
383        if (is64Bit())
384          Type = ELF::R_PPC64_TLSLD;
385        else
386          Type = ELF::R_PPC_TLSLD;
387        break;
388      case MCSymbolRefExpr::VK_PPC_TLS:
389        if (is64Bit())
390          Type = ELF::R_PPC64_TLS;
391        else
392          Type = ELF::R_PPC_TLS;
393        break;
394      }
395      break;
396    case FK_Data_8:
397      switch (Modifier) {
398      default: llvm_unreachable("Unsupported Modifier");
399      case MCSymbolRefExpr::VK_PPC_TOCBASE:
400        Type = ELF::R_PPC64_TOC;
401        break;
402      case MCSymbolRefExpr::VK_None:
403        Type = ELF::R_PPC64_ADDR64;
404        break;
405      case MCSymbolRefExpr::VK_PPC_DTPMOD:
406        Type = ELF::R_PPC64_DTPMOD64;
407        break;
408      case MCSymbolRefExpr::VK_TPREL:
409        Type = ELF::R_PPC64_TPREL64;
410        break;
411      case MCSymbolRefExpr::VK_DTPREL:
412        Type = ELF::R_PPC64_DTPREL64;
413        break;
414      }
415      break;
416    case FK_Data_4:
417      Type = ELF::R_PPC_ADDR32;
418      break;
419    case FK_Data_2:
420      Type = ELF::R_PPC_ADDR16;
421      break;
422    }
423  }
424  return Type;
425}
426
427bool PPCELFObjectWriter::needsRelocateWithSymbol(const MCSymbol &Sym,
428                                                 unsigned Type) const {
429  switch (Type) {
430    default:
431      return false;
432
433    case ELF::R_PPC_REL24:
434      // If the target symbol has a local entry point, we must keep the
435      // target symbol to preserve that information for the linker.
436      // The "other" values are stored in the last 6 bits of the second byte.
437      // The traditional defines for STO values assume the full byte and thus
438      // the shift to pack it.
439      unsigned Other = cast<MCSymbolELF>(Sym).getOther() << 2;
440      return (Other & ELF::STO_PPC64_LOCAL_MASK) != 0;
441  }
442}
443
444std::unique_ptr<MCObjectTargetWriter>
445llvm::createPPCELFObjectWriter(bool Is64Bit, uint8_t OSABI) {
446  return std::make_unique<PPCELFObjectWriter>(Is64Bit, OSABI);
447}
448