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 "llvm/ADT/STLExtras.h" 13 #include "llvm/MC/MCELFObjectWriter.h" 14 #include "llvm/MC/MCExpr.h" 15 #include "llvm/MC/MCValue.h" 16 #include "llvm/Support/ErrorHandling.h" 17 18 using namespace llvm; 19 20 namespace { 21 class PPCELFObjectWriter : public MCELFObjectTargetWriter { 22 public: 23 PPCELFObjectWriter(bool Is64Bit, uint8_t OSABI); 24 25 virtual ~PPCELFObjectWriter(); 26 protected: 27 virtual unsigned getRelocTypeInner(const MCValue &Target, 28 const MCFixup &Fixup, 29 bool IsPCRel) const; 30 virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, 31 bool IsPCRel, bool IsRelocWithSymbol, 32 int64_t Addend) const; 33 virtual const MCSymbol *undefinedExplicitRelSym(const MCValue &Target, 34 const MCFixup &Fixup, 35 bool IsPCRel) const; 36 }; 37 } 38 39 PPCELFObjectWriter::PPCELFObjectWriter(bool Is64Bit, uint8_t OSABI) 40 : MCELFObjectTargetWriter(Is64Bit, OSABI, 41 Is64Bit ? ELF::EM_PPC64 : ELF::EM_PPC, 42 /*HasRelocationAddend*/ true) {} 43 44 PPCELFObjectWriter::~PPCELFObjectWriter() { 45 } 46 47 unsigned 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 54 // 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 case PPC::fixup_ppc_br24abs: 62 Type = ELF::R_PPC_REL24; 63 break; 64 case PPC::fixup_ppc_brcond14: 65 case PPC::fixup_ppc_brcond14abs: 66 Type = ELF::R_PPC_REL14; 67 break; 68 case PPC::fixup_ppc_half16: 69 switch (Modifier) { 70 default: llvm_unreachable("Unsupported Modifier"); 71 case MCSymbolRefExpr::VK_None: 72 Type = ELF::R_PPC_REL16; 73 break; 74 case MCSymbolRefExpr::VK_PPC_LO: 75 Type = ELF::R_PPC_REL16_LO; 76 break; 77 case MCSymbolRefExpr::VK_PPC_HI: 78 Type = ELF::R_PPC_REL16_HI; 79 break; 80 case MCSymbolRefExpr::VK_PPC_HA: 81 Type = ELF::R_PPC_REL16_HA; 82 break; 83 } 84 break; 85 case FK_Data_4: 86 case FK_PCRel_4: 87 Type = ELF::R_PPC_REL32; 88 break; 89 case FK_Data_8: 90 case FK_PCRel_8: 91 Type = ELF::R_PPC64_REL64; 92 break; 93 } 94 } else { 95 switch ((unsigned)Fixup.getKind()) { 96 default: llvm_unreachable("invalid fixup kind!"); 97 case PPC::fixup_ppc_br24abs: 98 Type = ELF::R_PPC_ADDR24; 99 break; 100 case PPC::fixup_ppc_brcond14abs: 101 Type = ELF::R_PPC_ADDR14; // XXX: or BRNTAKEN?_ 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_ADDR16; 108 break; 109 case MCSymbolRefExpr::VK_PPC_LO: 110 Type = ELF::R_PPC_ADDR16_LO; 111 break; 112 case MCSymbolRefExpr::VK_PPC_HI: 113 Type = ELF::R_PPC_ADDR16_HI; 114 break; 115 case MCSymbolRefExpr::VK_PPC_HA: 116 Type = ELF::R_PPC_ADDR16_HA; 117 break; 118 case MCSymbolRefExpr::VK_PPC_HIGHER: 119 Type = ELF::R_PPC64_ADDR16_HIGHER; 120 break; 121 case MCSymbolRefExpr::VK_PPC_HIGHERA: 122 Type = ELF::R_PPC64_ADDR16_HIGHERA; 123 break; 124 case MCSymbolRefExpr::VK_PPC_HIGHEST: 125 Type = ELF::R_PPC64_ADDR16_HIGHEST; 126 break; 127 case MCSymbolRefExpr::VK_PPC_HIGHESTA: 128 Type = ELF::R_PPC64_ADDR16_HIGHESTA; 129 break; 130 case MCSymbolRefExpr::VK_GOT: 131 Type = ELF::R_PPC_GOT16; 132 break; 133 case MCSymbolRefExpr::VK_PPC_GOT_LO: 134 Type = ELF::R_PPC_GOT16_LO; 135 break; 136 case MCSymbolRefExpr::VK_PPC_GOT_HI: 137 Type = ELF::R_PPC_GOT16_HI; 138 break; 139 case MCSymbolRefExpr::VK_PPC_GOT_HA: 140 Type = ELF::R_PPC_GOT16_HA; 141 break; 142 case MCSymbolRefExpr::VK_PPC_TOC: 143 Type = ELF::R_PPC64_TOC16; 144 break; 145 case MCSymbolRefExpr::VK_PPC_TOC_LO: 146 Type = ELF::R_PPC64_TOC16_LO; 147 break; 148 case MCSymbolRefExpr::VK_PPC_TOC_HI: 149 Type = ELF::R_PPC64_TOC16_HI; 150 break; 151 case MCSymbolRefExpr::VK_PPC_TOC_HA: 152 Type = ELF::R_PPC64_TOC16_HA; 153 break; 154 case MCSymbolRefExpr::VK_PPC_TPREL: 155 Type = ELF::R_PPC_TPREL16; 156 break; 157 case MCSymbolRefExpr::VK_PPC_TPREL_LO: 158 Type = ELF::R_PPC_TPREL16_LO; 159 break; 160 case MCSymbolRefExpr::VK_PPC_TPREL_HI: 161 Type = ELF::R_PPC_TPREL16_HI; 162 break; 163 case MCSymbolRefExpr::VK_PPC_TPREL_HA: 164 Type = ELF::R_PPC_TPREL16_HA; 165 break; 166 case MCSymbolRefExpr::VK_PPC_TPREL_HIGHER: 167 Type = ELF::R_PPC64_TPREL16_HIGHER; 168 break; 169 case MCSymbolRefExpr::VK_PPC_TPREL_HIGHERA: 170 Type = ELF::R_PPC64_TPREL16_HIGHERA; 171 break; 172 case MCSymbolRefExpr::VK_PPC_TPREL_HIGHEST: 173 Type = ELF::R_PPC64_TPREL16_HIGHEST; 174 break; 175 case MCSymbolRefExpr::VK_PPC_TPREL_HIGHESTA: 176 Type = ELF::R_PPC64_TPREL16_HIGHESTA; 177 break; 178 case MCSymbolRefExpr::VK_PPC_DTPREL: 179 Type = ELF::R_PPC64_DTPREL16; 180 break; 181 case MCSymbolRefExpr::VK_PPC_DTPREL_LO: 182 Type = ELF::R_PPC64_DTPREL16_LO; 183 break; 184 case MCSymbolRefExpr::VK_PPC_DTPREL_HI: 185 Type = ELF::R_PPC64_DTPREL16_HI; 186 break; 187 case MCSymbolRefExpr::VK_PPC_DTPREL_HA: 188 Type = ELF::R_PPC64_DTPREL16_HA; 189 break; 190 case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHER: 191 Type = ELF::R_PPC64_DTPREL16_HIGHER; 192 break; 193 case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHERA: 194 Type = ELF::R_PPC64_DTPREL16_HIGHERA; 195 break; 196 case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHEST: 197 Type = ELF::R_PPC64_DTPREL16_HIGHEST; 198 break; 199 case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHESTA: 200 Type = ELF::R_PPC64_DTPREL16_HIGHESTA; 201 break; 202 case MCSymbolRefExpr::VK_PPC_GOT_TLSGD: 203 Type = ELF::R_PPC64_GOT_TLSGD16; 204 break; 205 case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_LO: 206 Type = ELF::R_PPC64_GOT_TLSGD16_LO; 207 break; 208 case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HI: 209 Type = ELF::R_PPC64_GOT_TLSGD16_HI; 210 break; 211 case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HA: 212 Type = ELF::R_PPC64_GOT_TLSGD16_HA; 213 break; 214 case MCSymbolRefExpr::VK_PPC_GOT_TLSLD: 215 Type = ELF::R_PPC64_GOT_TLSLD16; 216 break; 217 case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO: 218 Type = ELF::R_PPC64_GOT_TLSLD16_LO; 219 break; 220 case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HI: 221 Type = ELF::R_PPC64_GOT_TLSLD16_HI; 222 break; 223 case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HA: 224 Type = ELF::R_PPC64_GOT_TLSLD16_HA; 225 break; 226 case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HI: 227 Type = ELF::R_PPC64_GOT_TPREL16_HI; 228 break; 229 case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HA: 230 Type = ELF::R_PPC64_GOT_TPREL16_HA; 231 break; 232 case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HI: 233 Type = ELF::R_PPC64_GOT_DTPREL16_HI; 234 break; 235 case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HA: 236 Type = ELF::R_PPC64_GOT_DTPREL16_HA; 237 break; 238 } 239 break; 240 case PPC::fixup_ppc_half16ds: 241 switch (Modifier) { 242 default: llvm_unreachable("Unsupported Modifier"); 243 case MCSymbolRefExpr::VK_None: 244 Type = ELF::R_PPC64_ADDR16_DS; 245 break; 246 case MCSymbolRefExpr::VK_PPC_LO: 247 Type = ELF::R_PPC64_ADDR16_LO_DS; 248 break; 249 case MCSymbolRefExpr::VK_GOT: 250 Type = ELF::R_PPC64_GOT16_DS; 251 break; 252 case MCSymbolRefExpr::VK_PPC_GOT_LO: 253 Type = ELF::R_PPC64_GOT16_LO_DS; 254 break; 255 case MCSymbolRefExpr::VK_PPC_TOC: 256 Type = ELF::R_PPC64_TOC16_DS; 257 break; 258 case MCSymbolRefExpr::VK_PPC_TOC_LO: 259 Type = ELF::R_PPC64_TOC16_LO_DS; 260 break; 261 case MCSymbolRefExpr::VK_PPC_TPREL: 262 Type = ELF::R_PPC64_TPREL16_DS; 263 break; 264 case MCSymbolRefExpr::VK_PPC_TPREL_LO: 265 Type = ELF::R_PPC64_TPREL16_LO_DS; 266 break; 267 case MCSymbolRefExpr::VK_PPC_DTPREL: 268 Type = ELF::R_PPC64_DTPREL16_DS; 269 break; 270 case MCSymbolRefExpr::VK_PPC_DTPREL_LO: 271 Type = ELF::R_PPC64_DTPREL16_LO_DS; 272 break; 273 case MCSymbolRefExpr::VK_PPC_GOT_TPREL: 274 Type = ELF::R_PPC64_GOT_TPREL16_DS; 275 break; 276 case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO: 277 Type = ELF::R_PPC64_GOT_TPREL16_LO_DS; 278 break; 279 case MCSymbolRefExpr::VK_PPC_GOT_DTPREL: 280 Type = ELF::R_PPC64_GOT_DTPREL16_DS; 281 break; 282 case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO: 283 Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS; 284 break; 285 } 286 break; 287 case PPC::fixup_ppc_tlsreg: 288 Type = ELF::R_PPC64_TLS; 289 break; 290 case PPC::fixup_ppc_nofixup: 291 switch (Modifier) { 292 default: llvm_unreachable("Unsupported Modifier"); 293 case MCSymbolRefExpr::VK_PPC_TLSGD: 294 Type = ELF::R_PPC64_TLSGD; 295 break; 296 case MCSymbolRefExpr::VK_PPC_TLSLD: 297 Type = ELF::R_PPC64_TLSLD; 298 break; 299 } 300 break; 301 case FK_Data_8: 302 switch (Modifier) { 303 default: llvm_unreachable("Unsupported Modifier"); 304 case MCSymbolRefExpr::VK_PPC_TOCBASE: 305 Type = ELF::R_PPC64_TOC; 306 break; 307 case MCSymbolRefExpr::VK_None: 308 Type = ELF::R_PPC64_ADDR64; 309 break; 310 } 311 break; 312 case FK_Data_4: 313 Type = ELF::R_PPC_ADDR32; 314 break; 315 case FK_Data_2: 316 Type = ELF::R_PPC_ADDR16; 317 break; 318 } 319 } 320 return Type; 321 } 322 323 unsigned PPCELFObjectWriter::GetRelocType(const MCValue &Target, 324 const MCFixup &Fixup, 325 bool IsPCRel, 326 bool IsRelocWithSymbol, 327 int64_t Addend) const { 328 return getRelocTypeInner(Target, Fixup, IsPCRel); 329 } 330 331 const MCSymbol *PPCELFObjectWriter::undefinedExplicitRelSym(const MCValue &Target, 332 const MCFixup &Fixup, 333 bool IsPCRel) const { 334 assert(Target.getSymA() && "SymA cannot be 0"); 335 const MCSymbol &Symbol = Target.getSymA()->getSymbol().AliasedSymbol(); 336 337 unsigned RelocType = getRelocTypeInner(Target, Fixup, IsPCRel); 338 339 // The .odp creation emits a relocation against the symbol ".TOC." which 340 // create a R_PPC64_TOC relocation. However the relocation symbol name 341 // in final object creation should be NULL, since the symbol does not 342 // really exist, it is just the reference to TOC base for the current 343 // object file. 344 bool EmitThisSym = RelocType != ELF::R_PPC64_TOC; 345 346 if (EmitThisSym && !Symbol.isTemporary()) 347 return &Symbol; 348 return NULL; 349 } 350 351 MCObjectWriter *llvm::createPPCELFObjectWriter(raw_ostream &OS, 352 bool Is64Bit, 353 uint8_t OSABI) { 354 MCELFObjectTargetWriter *MOTW = new PPCELFObjectWriter(Is64Bit, OSABI); 355 return createELFObjectWriter(MOTW, OS, /*IsLittleEndian=*/false); 356 } 357