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