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/MCValue.h" 17 #include "llvm/Support/ErrorHandling.h" 18 19 using namespace llvm; 20 21 namespace { 22 class PPCELFObjectWriter : public MCELFObjectTargetWriter { 23 public: 24 PPCELFObjectWriter(bool Is64Bit, uint8_t OSABI); 25 26 virtual ~PPCELFObjectWriter(); 27 protected: 28 virtual unsigned getRelocTypeInner(const MCValue &Target, 29 const MCFixup &Fixup, 30 bool IsPCRel) const; 31 unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, 32 bool IsPCRel, bool IsRelocWithSymbol) const override; 33 virtual const MCSymbol *ExplicitRelSym(const MCAssembler &Asm, 34 const MCValue &Target, 35 const MCFragment &F, 36 const MCFixup &Fixup, 37 bool IsPCRel) const; 38 virtual const MCSymbol *undefinedExplicitRelSym(const MCValue &Target, 39 const MCFixup &Fixup, 40 bool IsPCRel) const; 41 }; 42 } 43 44 PPCELFObjectWriter::PPCELFObjectWriter(bool Is64Bit, uint8_t OSABI) 45 : MCELFObjectTargetWriter(Is64Bit, OSABI, 46 Is64Bit ? ELF::EM_PPC64 : ELF::EM_PPC, 47 /*HasRelocationAddend*/ true) {} 48 49 PPCELFObjectWriter::~PPCELFObjectWriter() { 50 } 51 52 static MCSymbolRefExpr::VariantKind getAccessVariant(const MCFixup &Fixup) { 53 const MCExpr *Expr = Fixup.getValue(); 54 55 if (Expr->getKind() != MCExpr::Target) 56 return Fixup.getAccessVariant(); 57 58 switch (cast<PPCMCExpr>(Expr)->getKind()) { 59 case PPCMCExpr::VK_PPC_None: 60 return MCSymbolRefExpr::VK_None; 61 case PPCMCExpr::VK_PPC_LO: 62 return MCSymbolRefExpr::VK_PPC_LO; 63 case PPCMCExpr::VK_PPC_HI: 64 return MCSymbolRefExpr::VK_PPC_HI; 65 case PPCMCExpr::VK_PPC_HA: 66 return MCSymbolRefExpr::VK_PPC_HA; 67 case PPCMCExpr::VK_PPC_HIGHERA: 68 return MCSymbolRefExpr::VK_PPC_HIGHERA; 69 case PPCMCExpr::VK_PPC_HIGHER: 70 return MCSymbolRefExpr::VK_PPC_HIGHER; 71 case PPCMCExpr::VK_PPC_HIGHEST: 72 return MCSymbolRefExpr::VK_PPC_HIGHEST; 73 case PPCMCExpr::VK_PPC_HIGHESTA: 74 return MCSymbolRefExpr::VK_PPC_HIGHESTA; 75 } 76 llvm_unreachable("unknown PPCMCExpr kind"); 77 } 78 79 unsigned PPCELFObjectWriter::getRelocTypeInner(const MCValue &Target, 80 const MCFixup &Fixup, 81 bool IsPCRel) const 82 { 83 MCSymbolRefExpr::VariantKind Modifier = getAccessVariant(Fixup); 84 85 // determine the type of the relocation 86 unsigned Type; 87 if (IsPCRel) { 88 switch ((unsigned)Fixup.getKind()) { 89 default: 90 llvm_unreachable("Unimplemented"); 91 case PPC::fixup_ppc_br24: 92 case PPC::fixup_ppc_br24abs: 93 Type = ELF::R_PPC_REL24; 94 break; 95 case PPC::fixup_ppc_brcond14: 96 case PPC::fixup_ppc_brcond14abs: 97 Type = ELF::R_PPC_REL14; 98 break; 99 case PPC::fixup_ppc_half16: 100 switch (Modifier) { 101 default: llvm_unreachable("Unsupported Modifier"); 102 case MCSymbolRefExpr::VK_None: 103 Type = ELF::R_PPC_REL16; 104 break; 105 case MCSymbolRefExpr::VK_PPC_LO: 106 Type = ELF::R_PPC_REL16_LO; 107 break; 108 case MCSymbolRefExpr::VK_PPC_HI: 109 Type = ELF::R_PPC_REL16_HI; 110 break; 111 case MCSymbolRefExpr::VK_PPC_HA: 112 Type = ELF::R_PPC_REL16_HA; 113 break; 114 } 115 break; 116 case FK_Data_4: 117 case FK_PCRel_4: 118 Type = ELF::R_PPC_REL32; 119 break; 120 case FK_Data_8: 121 case FK_PCRel_8: 122 Type = ELF::R_PPC64_REL64; 123 break; 124 } 125 } else { 126 switch ((unsigned)Fixup.getKind()) { 127 default: llvm_unreachable("invalid fixup kind!"); 128 case PPC::fixup_ppc_br24abs: 129 Type = ELF::R_PPC_ADDR24; 130 break; 131 case PPC::fixup_ppc_brcond14abs: 132 Type = ELF::R_PPC_ADDR14; // XXX: or BRNTAKEN?_ 133 break; 134 case PPC::fixup_ppc_half16: 135 switch (Modifier) { 136 default: llvm_unreachable("Unsupported Modifier"); 137 case MCSymbolRefExpr::VK_None: 138 Type = ELF::R_PPC_ADDR16; 139 break; 140 case MCSymbolRefExpr::VK_PPC_LO: 141 Type = ELF::R_PPC_ADDR16_LO; 142 break; 143 case MCSymbolRefExpr::VK_PPC_HI: 144 Type = ELF::R_PPC_ADDR16_HI; 145 break; 146 case MCSymbolRefExpr::VK_PPC_HA: 147 Type = ELF::R_PPC_ADDR16_HA; 148 break; 149 case MCSymbolRefExpr::VK_PPC_HIGHER: 150 Type = ELF::R_PPC64_ADDR16_HIGHER; 151 break; 152 case MCSymbolRefExpr::VK_PPC_HIGHERA: 153 Type = ELF::R_PPC64_ADDR16_HIGHERA; 154 break; 155 case MCSymbolRefExpr::VK_PPC_HIGHEST: 156 Type = ELF::R_PPC64_ADDR16_HIGHEST; 157 break; 158 case MCSymbolRefExpr::VK_PPC_HIGHESTA: 159 Type = ELF::R_PPC64_ADDR16_HIGHESTA; 160 break; 161 case MCSymbolRefExpr::VK_GOT: 162 Type = ELF::R_PPC_GOT16; 163 break; 164 case MCSymbolRefExpr::VK_PPC_GOT_LO: 165 Type = ELF::R_PPC_GOT16_LO; 166 break; 167 case MCSymbolRefExpr::VK_PPC_GOT_HI: 168 Type = ELF::R_PPC_GOT16_HI; 169 break; 170 case MCSymbolRefExpr::VK_PPC_GOT_HA: 171 Type = ELF::R_PPC_GOT16_HA; 172 break; 173 case MCSymbolRefExpr::VK_PPC_TOC: 174 Type = ELF::R_PPC64_TOC16; 175 break; 176 case MCSymbolRefExpr::VK_PPC_TOC_LO: 177 Type = ELF::R_PPC64_TOC16_LO; 178 break; 179 case MCSymbolRefExpr::VK_PPC_TOC_HI: 180 Type = ELF::R_PPC64_TOC16_HI; 181 break; 182 case MCSymbolRefExpr::VK_PPC_TOC_HA: 183 Type = ELF::R_PPC64_TOC16_HA; 184 break; 185 case MCSymbolRefExpr::VK_PPC_TPREL: 186 Type = ELF::R_PPC_TPREL16; 187 break; 188 case MCSymbolRefExpr::VK_PPC_TPREL_LO: 189 Type = ELF::R_PPC_TPREL16_LO; 190 break; 191 case MCSymbolRefExpr::VK_PPC_TPREL_HI: 192 Type = ELF::R_PPC_TPREL16_HI; 193 break; 194 case MCSymbolRefExpr::VK_PPC_TPREL_HA: 195 Type = ELF::R_PPC_TPREL16_HA; 196 break; 197 case MCSymbolRefExpr::VK_PPC_TPREL_HIGHER: 198 Type = ELF::R_PPC64_TPREL16_HIGHER; 199 break; 200 case MCSymbolRefExpr::VK_PPC_TPREL_HIGHERA: 201 Type = ELF::R_PPC64_TPREL16_HIGHERA; 202 break; 203 case MCSymbolRefExpr::VK_PPC_TPREL_HIGHEST: 204 Type = ELF::R_PPC64_TPREL16_HIGHEST; 205 break; 206 case MCSymbolRefExpr::VK_PPC_TPREL_HIGHESTA: 207 Type = ELF::R_PPC64_TPREL16_HIGHESTA; 208 break; 209 case MCSymbolRefExpr::VK_PPC_DTPREL: 210 Type = ELF::R_PPC64_DTPREL16; 211 break; 212 case MCSymbolRefExpr::VK_PPC_DTPREL_LO: 213 Type = ELF::R_PPC64_DTPREL16_LO; 214 break; 215 case MCSymbolRefExpr::VK_PPC_DTPREL_HI: 216 Type = ELF::R_PPC64_DTPREL16_HI; 217 break; 218 case MCSymbolRefExpr::VK_PPC_DTPREL_HA: 219 Type = ELF::R_PPC64_DTPREL16_HA; 220 break; 221 case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHER: 222 Type = ELF::R_PPC64_DTPREL16_HIGHER; 223 break; 224 case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHERA: 225 Type = ELF::R_PPC64_DTPREL16_HIGHERA; 226 break; 227 case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHEST: 228 Type = ELF::R_PPC64_DTPREL16_HIGHEST; 229 break; 230 case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHESTA: 231 Type = ELF::R_PPC64_DTPREL16_HIGHESTA; 232 break; 233 case MCSymbolRefExpr::VK_PPC_GOT_TLSGD: 234 Type = ELF::R_PPC64_GOT_TLSGD16; 235 break; 236 case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_LO: 237 Type = ELF::R_PPC64_GOT_TLSGD16_LO; 238 break; 239 case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HI: 240 Type = ELF::R_PPC64_GOT_TLSGD16_HI; 241 break; 242 case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HA: 243 Type = ELF::R_PPC64_GOT_TLSGD16_HA; 244 break; 245 case MCSymbolRefExpr::VK_PPC_GOT_TLSLD: 246 Type = ELF::R_PPC64_GOT_TLSLD16; 247 break; 248 case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO: 249 Type = ELF::R_PPC64_GOT_TLSLD16_LO; 250 break; 251 case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HI: 252 Type = ELF::R_PPC64_GOT_TLSLD16_HI; 253 break; 254 case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HA: 255 Type = ELF::R_PPC64_GOT_TLSLD16_HA; 256 break; 257 case MCSymbolRefExpr::VK_PPC_GOT_TPREL: 258 /* We don't have R_PPC64_GOT_TPREL16, but since GOT offsets 259 are always 4-aligned, we can use R_PPC64_GOT_TPREL16_DS. */ 260 Type = ELF::R_PPC64_GOT_TPREL16_DS; 261 break; 262 case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO: 263 /* We don't have R_PPC64_GOT_TPREL16_LO, but since GOT offsets 264 are always 4-aligned, we can use R_PPC64_GOT_TPREL16_LO_DS. */ 265 Type = ELF::R_PPC64_GOT_TPREL16_LO_DS; 266 break; 267 case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HI: 268 Type = ELF::R_PPC64_GOT_TPREL16_HI; 269 break; 270 case MCSymbolRefExpr::VK_PPC_GOT_DTPREL: 271 /* We don't have R_PPC64_GOT_DTPREL16, but since GOT offsets 272 are always 4-aligned, we can use R_PPC64_GOT_DTPREL16_DS. */ 273 Type = ELF::R_PPC64_GOT_DTPREL16_DS; 274 break; 275 case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO: 276 /* We don't have R_PPC64_GOT_DTPREL16_LO, but since GOT offsets 277 are always 4-aligned, we can use R_PPC64_GOT_DTPREL16_LO_DS. */ 278 Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS; 279 break; 280 case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HA: 281 Type = ELF::R_PPC64_GOT_TPREL16_HA; 282 break; 283 case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HI: 284 Type = ELF::R_PPC64_GOT_DTPREL16_HI; 285 break; 286 case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HA: 287 Type = ELF::R_PPC64_GOT_DTPREL16_HA; 288 break; 289 } 290 break; 291 case PPC::fixup_ppc_half16ds: 292 switch (Modifier) { 293 default: llvm_unreachable("Unsupported Modifier"); 294 case MCSymbolRefExpr::VK_None: 295 Type = ELF::R_PPC64_ADDR16_DS; 296 break; 297 case MCSymbolRefExpr::VK_PPC_LO: 298 Type = ELF::R_PPC64_ADDR16_LO_DS; 299 break; 300 case MCSymbolRefExpr::VK_GOT: 301 Type = ELF::R_PPC64_GOT16_DS; 302 break; 303 case MCSymbolRefExpr::VK_PPC_GOT_LO: 304 Type = ELF::R_PPC64_GOT16_LO_DS; 305 break; 306 case MCSymbolRefExpr::VK_PPC_TOC: 307 Type = ELF::R_PPC64_TOC16_DS; 308 break; 309 case MCSymbolRefExpr::VK_PPC_TOC_LO: 310 Type = ELF::R_PPC64_TOC16_LO_DS; 311 break; 312 case MCSymbolRefExpr::VK_PPC_TPREL: 313 Type = ELF::R_PPC64_TPREL16_DS; 314 break; 315 case MCSymbolRefExpr::VK_PPC_TPREL_LO: 316 Type = ELF::R_PPC64_TPREL16_LO_DS; 317 break; 318 case MCSymbolRefExpr::VK_PPC_DTPREL: 319 Type = ELF::R_PPC64_DTPREL16_DS; 320 break; 321 case MCSymbolRefExpr::VK_PPC_DTPREL_LO: 322 Type = ELF::R_PPC64_DTPREL16_LO_DS; 323 break; 324 case MCSymbolRefExpr::VK_PPC_GOT_TPREL: 325 Type = ELF::R_PPC64_GOT_TPREL16_DS; 326 break; 327 case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO: 328 Type = ELF::R_PPC64_GOT_TPREL16_LO_DS; 329 break; 330 case MCSymbolRefExpr::VK_PPC_GOT_DTPREL: 331 Type = ELF::R_PPC64_GOT_DTPREL16_DS; 332 break; 333 case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO: 334 Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS; 335 break; 336 } 337 break; 338 case PPC::fixup_ppc_nofixup: 339 switch (Modifier) { 340 default: llvm_unreachable("Unsupported Modifier"); 341 case MCSymbolRefExpr::VK_PPC_TLSGD: 342 Type = ELF::R_PPC64_TLSGD; 343 break; 344 case MCSymbolRefExpr::VK_PPC_TLSLD: 345 Type = ELF::R_PPC64_TLSLD; 346 break; 347 case MCSymbolRefExpr::VK_PPC_TLS: 348 Type = ELF::R_PPC64_TLS; 349 break; 350 } 351 break; 352 case FK_Data_8: 353 switch (Modifier) { 354 default: llvm_unreachable("Unsupported Modifier"); 355 case MCSymbolRefExpr::VK_PPC_TOCBASE: 356 Type = ELF::R_PPC64_TOC; 357 break; 358 case MCSymbolRefExpr::VK_None: 359 Type = ELF::R_PPC64_ADDR64; 360 break; 361 case MCSymbolRefExpr::VK_PPC_DTPMOD: 362 Type = ELF::R_PPC64_DTPMOD64; 363 break; 364 case MCSymbolRefExpr::VK_PPC_TPREL: 365 Type = ELF::R_PPC64_TPREL64; 366 break; 367 case MCSymbolRefExpr::VK_PPC_DTPREL: 368 Type = ELF::R_PPC64_DTPREL64; 369 break; 370 } 371 break; 372 case FK_Data_4: 373 Type = ELF::R_PPC_ADDR32; 374 break; 375 case FK_Data_2: 376 Type = ELF::R_PPC_ADDR16; 377 break; 378 } 379 } 380 return Type; 381 } 382 383 unsigned PPCELFObjectWriter::GetRelocType(const MCValue &Target, 384 const MCFixup &Fixup, 385 bool IsPCRel, 386 bool IsRelocWithSymbol) const { 387 return getRelocTypeInner(Target, Fixup, IsPCRel); 388 } 389 390 const MCSymbol *PPCELFObjectWriter::ExplicitRelSym(const MCAssembler &Asm, 391 const MCValue &Target, 392 const MCFragment &F, 393 const MCFixup &Fixup, 394 bool IsPCRel) const { 395 assert(Target.getSymA() && "SymA cannot be 0"); 396 MCSymbolRefExpr::VariantKind Modifier = Fixup.getAccessVariant(); 397 398 bool EmitThisSym; 399 switch (Modifier) { 400 // GOT references always need a relocation, even if the 401 // target symbol is local. 402 case MCSymbolRefExpr::VK_GOT: 403 case MCSymbolRefExpr::VK_PPC_GOT_LO: 404 case MCSymbolRefExpr::VK_PPC_GOT_HI: 405 case MCSymbolRefExpr::VK_PPC_GOT_HA: 406 EmitThisSym = true; 407 break; 408 default: 409 EmitThisSym = false; 410 break; 411 } 412 413 if (EmitThisSym) 414 return &Target.getSymA()->getSymbol().AliasedSymbol(); 415 return NULL; 416 } 417 418 const MCSymbol *PPCELFObjectWriter::undefinedExplicitRelSym(const MCValue &Target, 419 const MCFixup &Fixup, 420 bool IsPCRel) const { 421 assert(Target.getSymA() && "SymA cannot be 0"); 422 const MCSymbol &Symbol = Target.getSymA()->getSymbol().AliasedSymbol(); 423 424 unsigned RelocType = getRelocTypeInner(Target, Fixup, IsPCRel); 425 426 // The .odp creation emits a relocation against the symbol ".TOC." which 427 // create a R_PPC64_TOC relocation. However the relocation symbol name 428 // in final object creation should be NULL, since the symbol does not 429 // really exist, it is just the reference to TOC base for the current 430 // object file. 431 bool EmitThisSym = RelocType != ELF::R_PPC64_TOC; 432 433 if (EmitThisSym && !Symbol.isTemporary()) 434 return &Symbol; 435 return NULL; 436 } 437 438 MCObjectWriter *llvm::createPPCELFObjectWriter(raw_ostream &OS, 439 bool Is64Bit, 440 bool IsLittleEndian, 441 uint8_t OSABI) { 442 MCELFObjectTargetWriter *MOTW = new PPCELFObjectWriter(Is64Bit, OSABI); 443 return createELFObjectWriter(MOTW, OS, IsLittleEndian); 444 } 445