blob: cd90ca1bcd690956782a2da1719053029d70f8d4 [file] [log] [blame]
Rafael Espindola38a400d2011-12-22 01:57:09 +00001//===-- 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
Rafael Espindola38a400d2011-12-22 01:57:09 +000010#include "MCTargetDesc/PPCMCTargetDesc.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000011#include "MCTargetDesc/PPCFixupKinds.h"
Rafael Espindola38a400d2011-12-22 01:57:09 +000012#include "llvm/MC/MCELFObjectWriter.h"
Adhemerval Zanellaf2aceda2012-10-25 12:27:42 +000013#include "llvm/MC/MCExpr.h"
14#include "llvm/MC/MCValue.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000015#include "llvm/Support/ErrorHandling.h"
Rafael Espindola38a400d2011-12-22 01:57:09 +000016
17using namespace llvm;
18
19namespace {
20 class PPCELFObjectWriter : public MCELFObjectTargetWriter {
21 public:
22 PPCELFObjectWriter(bool Is64Bit, uint8_t OSABI);
23
24 virtual ~PPCELFObjectWriter();
25 protected:
Adhemerval Zanellaf2aceda2012-10-25 12:27:42 +000026 virtual unsigned getRelocTypeInner(const MCValue &Target,
27 const MCFixup &Fixup,
28 bool IsPCRel) const;
Rafael Espindola38a400d2011-12-22 01:57:09 +000029 virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup,
30 bool IsPCRel, bool IsRelocWithSymbol,
31 int64_t Addend) const;
Adhemerval Zanellaf2aceda2012-10-25 12:27:42 +000032 virtual const MCSymbol *undefinedExplicitRelSym(const MCValue &Target,
33 const MCFixup &Fixup,
34 bool IsPCRel) const;
Rafael Espindola38a400d2011-12-22 01:57:09 +000035 virtual void adjustFixupOffset(const MCFixup &Fixup, uint64_t &RelocOffset);
36 };
37}
38
39PPCELFObjectWriter::PPCELFObjectWriter(bool Is64Bit, uint8_t OSABI)
40 : MCELFObjectTargetWriter(Is64Bit, OSABI,
41 Is64Bit ? ELF::EM_PPC64 : ELF::EM_PPC,
Rafael Espindola25009622011-12-22 18:38:06 +000042 /*HasRelocationAddend*/ true) {}
Rafael Espindola38a400d2011-12-22 01:57:09 +000043
44PPCELFObjectWriter::~PPCELFObjectWriter() {
45}
46
Adhemerval Zanellaf2aceda2012-10-25 12:27:42 +000047unsigned PPCELFObjectWriter::getRelocTypeInner(const MCValue &Target,
48 const MCFixup &Fixup,
49 bool IsPCRel) const
50{
51 MCSymbolRefExpr::VariantKind Modifier = Target.isAbsolute() ?
52 MCSymbolRefExpr::VK_None : Target.getSymA()->getKind();
53
Rafael Espindola38a400d2011-12-22 01:57:09 +000054 // determine the type of the relocation
55 unsigned Type;
56 if (IsPCRel) {
57 switch ((unsigned)Fixup.getKind()) {
58 default:
59 llvm_unreachable("Unimplemented");
60 case PPC::fixup_ppc_br24:
61 Type = ELF::R_PPC_REL24;
62 break;
63 case FK_PCRel_4:
64 Type = ELF::R_PPC_REL32;
65 break;
66 }
67 } else {
68 switch ((unsigned)Fixup.getKind()) {
69 default: llvm_unreachable("invalid fixup kind!");
70 case PPC::fixup_ppc_br24:
71 Type = ELF::R_PPC_ADDR24;
72 break;
73 case PPC::fixup_ppc_brcond14:
Adhemerval Zanellaf2aceda2012-10-25 12:27:42 +000074 Type = ELF::R_PPC_ADDR14; // XXX: or BRNTAKEN?_
Rafael Espindola38a400d2011-12-22 01:57:09 +000075 break;
76 case PPC::fixup_ppc_ha16:
Ulrich Weigand85578502012-11-13 19:24:36 +000077 switch (Modifier) {
78 default: llvm_unreachable("Unsupported Modifier");
79 case MCSymbolRefExpr::VK_PPC_TPREL16_HA:
80 Type = ELF::R_PPC_TPREL16_HA;
81 break;
Bill Schmidt24b8dd62012-12-12 19:29:35 +000082 case MCSymbolRefExpr::VK_PPC_DTPREL16_HA:
83 Type = ELF::R_PPC64_DTPREL16_HA;
84 break;
Ulrich Weigand85578502012-11-13 19:24:36 +000085 case MCSymbolRefExpr::VK_None:
86 Type = ELF::R_PPC_ADDR16_HA;
87 break;
Bill Schmidt34627e32012-11-27 17:35:46 +000088 case MCSymbolRefExpr::VK_PPC_TOC16_HA:
89 Type = ELF::R_PPC64_TOC16_HA;
90 break;
Bill Schmidt9f0b4ec2012-12-14 17:02:38 +000091 case MCSymbolRefExpr::VK_PPC_GOT_TPREL16_HA:
92 Type = ELF::R_PPC64_GOT_TPREL16_HA;
93 break;
Bill Schmidtc56f1d32012-12-11 20:30:11 +000094 case MCSymbolRefExpr::VK_PPC_GOT_TLSGD16_HA:
95 Type = ELF::R_PPC64_GOT_TLSGD16_HA;
96 break;
Bill Schmidt24b8dd62012-12-12 19:29:35 +000097 case MCSymbolRefExpr::VK_PPC_GOT_TLSLD16_HA:
98 Type = ELF::R_PPC64_GOT_TLSLD16_HA;
99 break;
Ulrich Weigand85578502012-11-13 19:24:36 +0000100 }
Rafael Espindola38a400d2011-12-22 01:57:09 +0000101 break;
102 case PPC::fixup_ppc_lo16:
Ulrich Weigand85578502012-11-13 19:24:36 +0000103 switch (Modifier) {
104 default: llvm_unreachable("Unsupported Modifier");
105 case MCSymbolRefExpr::VK_PPC_TPREL16_LO:
106 Type = ELF::R_PPC_TPREL16_LO;
107 break;
Bill Schmidt24b8dd62012-12-12 19:29:35 +0000108 case MCSymbolRefExpr::VK_PPC_DTPREL16_LO:
109 Type = ELF::R_PPC64_DTPREL16_LO;
110 break;
Ulrich Weigand85578502012-11-13 19:24:36 +0000111 case MCSymbolRefExpr::VK_None:
112 Type = ELF::R_PPC_ADDR16_LO;
113 break;
Bill Schmidt34627e32012-11-27 17:35:46 +0000114 case MCSymbolRefExpr::VK_PPC_TOC16_LO:
115 Type = ELF::R_PPC64_TOC16_LO;
116 break;
Bill Schmidtc56f1d32012-12-11 20:30:11 +0000117 case MCSymbolRefExpr::VK_PPC_GOT_TLSGD16_LO:
118 Type = ELF::R_PPC64_GOT_TLSGD16_LO;
119 break;
Bill Schmidt24b8dd62012-12-12 19:29:35 +0000120 case MCSymbolRefExpr::VK_PPC_GOT_TLSLD16_LO:
121 Type = ELF::R_PPC64_GOT_TLSLD16_LO;
122 break;
Ulrich Weigand85578502012-11-13 19:24:36 +0000123 }
Rafael Espindola38a400d2011-12-22 01:57:09 +0000124 break;
125 case PPC::fixup_ppc_lo14:
126 Type = ELF::R_PPC_ADDR14;
127 break;
Adhemerval Zanellaf2aceda2012-10-25 12:27:42 +0000128 case PPC::fixup_ppc_toc:
129 Type = ELF::R_PPC64_TOC;
130 break;
131 case PPC::fixup_ppc_toc16:
132 Type = ELF::R_PPC64_TOC16;
133 break;
134 case PPC::fixup_ppc_toc16_ds:
Bill Schmidt34627e32012-11-27 17:35:46 +0000135 switch (Modifier) {
136 default: llvm_unreachable("Unsupported Modifier");
137 case MCSymbolRefExpr::VK_PPC_TOC_ENTRY:
138 Type = ELF::R_PPC64_TOC16_DS;
139 break;
140 case MCSymbolRefExpr::VK_PPC_TOC16_LO:
141 Type = ELF::R_PPC64_TOC16_LO_DS;
142 break;
Bill Schmidt9f0b4ec2012-12-14 17:02:38 +0000143 case MCSymbolRefExpr::VK_PPC_GOT_TPREL16_LO:
144 Type = ELF::R_PPC64_GOT_TPREL16_LO_DS;
Bill Schmidtca4a0c92012-12-04 16:18:08 +0000145 break;
Bill Schmidt34627e32012-11-27 17:35:46 +0000146 }
Adhemerval Zanellaf2aceda2012-10-25 12:27:42 +0000147 break;
Bill Schmidtca4a0c92012-12-04 16:18:08 +0000148 case PPC::fixup_ppc_tlsreg:
149 Type = ELF::R_PPC64_TLS;
150 break;
Bill Schmidt24b8dd62012-12-12 19:29:35 +0000151 case PPC::fixup_ppc_nofixup:
152 switch (Modifier) {
153 default: llvm_unreachable("Unsupported Modifier");
154 case MCSymbolRefExpr::VK_PPC_TLSGD:
155 Type = ELF::R_PPC64_TLSGD;
156 break;
157 case MCSymbolRefExpr::VK_PPC_TLSLD:
158 Type = ELF::R_PPC64_TLSLD;
159 break;
160 }
Bill Schmidtc56f1d32012-12-11 20:30:11 +0000161 break;
Adhemerval Zanellaf2aceda2012-10-25 12:27:42 +0000162 case FK_Data_8:
163 switch (Modifier) {
164 default: llvm_unreachable("Unsupported Modifier");
165 case MCSymbolRefExpr::VK_PPC_TOC:
166 Type = ELF::R_PPC64_TOC;
167 break;
168 case MCSymbolRefExpr::VK_None:
169 Type = ELF::R_PPC64_ADDR64;
170 break;
171 }
172 break;
Rafael Espindola38a400d2011-12-22 01:57:09 +0000173 case FK_Data_4:
174 Type = ELF::R_PPC_ADDR32;
175 break;
176 case FK_Data_2:
177 Type = ELF::R_PPC_ADDR16;
178 break;
179 }
180 }
181 return Type;
182}
183
Adhemerval Zanellaf2aceda2012-10-25 12:27:42 +0000184unsigned PPCELFObjectWriter::GetRelocType(const MCValue &Target,
185 const MCFixup &Fixup,
186 bool IsPCRel,
187 bool IsRelocWithSymbol,
188 int64_t Addend) const {
189 return getRelocTypeInner(Target, Fixup, IsPCRel);
190}
191
192const MCSymbol *PPCELFObjectWriter::undefinedExplicitRelSym(const MCValue &Target,
193 const MCFixup &Fixup,
194 bool IsPCRel) const {
195 assert(Target.getSymA() && "SymA cannot be 0");
196 const MCSymbol &Symbol = Target.getSymA()->getSymbol().AliasedSymbol();
197
198 unsigned RelocType = getRelocTypeInner(Target, Fixup, IsPCRel);
199
200 // The .odp creation emits a relocation against the symbol ".TOC." which
201 // create a R_PPC64_TOC relocation. However the relocation symbol name
202 // in final object creation should be NULL, since the symbol does not
203 // really exist, it is just the reference to TOC base for the current
204 // object file.
205 bool EmitThisSym = RelocType != ELF::R_PPC64_TOC;
206
207 if (EmitThisSym && !Symbol.isTemporary())
208 return &Symbol;
209 return NULL;
210}
211
Rafael Espindola38a400d2011-12-22 01:57:09 +0000212void PPCELFObjectWriter::
213adjustFixupOffset(const MCFixup &Fixup, uint64_t &RelocOffset) {
214 switch ((unsigned)Fixup.getKind()) {
215 case PPC::fixup_ppc_ha16:
216 case PPC::fixup_ppc_lo16:
Adhemerval Zanella1be10dc2012-10-25 14:29:13 +0000217 case PPC::fixup_ppc_toc16:
218 case PPC::fixup_ppc_toc16_ds:
Rafael Espindola38a400d2011-12-22 01:57:09 +0000219 RelocOffset += 2;
220 break;
221 default:
222 break;
223 }
224}
225
226MCObjectWriter *llvm::createPPCELFObjectWriter(raw_ostream &OS,
227 bool Is64Bit,
228 uint8_t OSABI) {
229 MCELFObjectTargetWriter *MOTW = new PPCELFObjectWriter(Is64Bit, OSABI);
Rafael Espindola25009622011-12-22 18:38:06 +0000230 return createELFObjectWriter(MOTW, OS, /*IsLittleEndian=*/false);
Rafael Espindola38a400d2011-12-22 01:57:09 +0000231}