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