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