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