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