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