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