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