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/MCELFObjectWriter.h" 15#include "llvm/MC/MCExpr.h" 16#include "llvm/MC/MCValue.h" 17#include "llvm/Support/ErrorHandling.h" 18 19using namespace llvm; 20 21namespace { 22 class PPCELFObjectWriter : public MCELFObjectTargetWriter { 23 public: 24 PPCELFObjectWriter(bool Is64Bit, uint8_t OSABI); 25 26 virtual ~PPCELFObjectWriter(); 27 protected: 28 virtual unsigned getRelocTypeInner(const MCValue &Target, 29 const MCFixup &Fixup, 30 bool IsPCRel) const; 31 unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, 32 bool IsPCRel) const override; 33 }; 34} 35 36PPCELFObjectWriter::PPCELFObjectWriter(bool Is64Bit, uint8_t OSABI) 37 : MCELFObjectTargetWriter(Is64Bit, OSABI, 38 Is64Bit ? ELF::EM_PPC64 : ELF::EM_PPC, 39 /*HasRelocationAddend*/ true) {} 40 41PPCELFObjectWriter::~PPCELFObjectWriter() { 42} 43 44static MCSymbolRefExpr::VariantKind getAccessVariant(const MCValue &Target, 45 const MCFixup &Fixup) { 46 const MCExpr *Expr = Fixup.getValue(); 47 48 if (Expr->getKind() != MCExpr::Target) 49 return Target.getAccessVariant(); 50 51 switch (cast<PPCMCExpr>(Expr)->getKind()) { 52 case PPCMCExpr::VK_PPC_None: 53 return MCSymbolRefExpr::VK_None; 54 case PPCMCExpr::VK_PPC_LO: 55 return MCSymbolRefExpr::VK_PPC_LO; 56 case PPCMCExpr::VK_PPC_HI: 57 return MCSymbolRefExpr::VK_PPC_HI; 58 case PPCMCExpr::VK_PPC_HA: 59 return MCSymbolRefExpr::VK_PPC_HA; 60 case PPCMCExpr::VK_PPC_HIGHERA: 61 return MCSymbolRefExpr::VK_PPC_HIGHERA; 62 case PPCMCExpr::VK_PPC_HIGHER: 63 return MCSymbolRefExpr::VK_PPC_HIGHER; 64 case PPCMCExpr::VK_PPC_HIGHEST: 65 return MCSymbolRefExpr::VK_PPC_HIGHEST; 66 case PPCMCExpr::VK_PPC_HIGHESTA: 67 return MCSymbolRefExpr::VK_PPC_HIGHESTA; 68 } 69 llvm_unreachable("unknown PPCMCExpr kind"); 70} 71 72unsigned PPCELFObjectWriter::getRelocTypeInner(const MCValue &Target, 73 const MCFixup &Fixup, 74 bool IsPCRel) const 75{ 76 MCSymbolRefExpr::VariantKind Modifier = getAccessVariant(Target, Fixup); 77 78 // determine the type of the relocation 79 unsigned Type; 80 if (IsPCRel) { 81 switch ((unsigned)Fixup.getKind()) { 82 default: 83 llvm_unreachable("Unimplemented"); 84 case PPC::fixup_ppc_br24: 85 case PPC::fixup_ppc_br24abs: 86 Type = ELF::R_PPC_REL24; 87 break; 88 case PPC::fixup_ppc_brcond14: 89 case PPC::fixup_ppc_brcond14abs: 90 Type = ELF::R_PPC_REL14; 91 break; 92 case PPC::fixup_ppc_half16: 93 switch (Modifier) { 94 default: llvm_unreachable("Unsupported Modifier"); 95 case MCSymbolRefExpr::VK_None: 96 Type = ELF::R_PPC_REL16; 97 break; 98 case MCSymbolRefExpr::VK_PPC_LO: 99 Type = ELF::R_PPC_REL16_LO; 100 break; 101 case MCSymbolRefExpr::VK_PPC_HI: 102 Type = ELF::R_PPC_REL16_HI; 103 break; 104 case MCSymbolRefExpr::VK_PPC_HA: 105 Type = ELF::R_PPC_REL16_HA; 106 break; 107 } 108 break; 109 case FK_Data_4: 110 case FK_PCRel_4: 111 Type = ELF::R_PPC_REL32; 112 break; 113 case FK_Data_8: 114 case FK_PCRel_8: 115 Type = ELF::R_PPC64_REL64; 116 break; 117 } 118 } else { 119 switch ((unsigned)Fixup.getKind()) { 120 default: llvm_unreachable("invalid fixup kind!"); 121 case PPC::fixup_ppc_br24abs: 122 Type = ELF::R_PPC_ADDR24; 123 break; 124 case PPC::fixup_ppc_brcond14abs: 125 Type = ELF::R_PPC_ADDR14; // XXX: or BRNTAKEN?_ 126 break; 127 case PPC::fixup_ppc_half16: 128 switch (Modifier) { 129 default: llvm_unreachable("Unsupported Modifier"); 130 case MCSymbolRefExpr::VK_None: 131 Type = ELF::R_PPC_ADDR16; 132 break; 133 case MCSymbolRefExpr::VK_PPC_LO: 134 Type = ELF::R_PPC_ADDR16_LO; 135 break; 136 case MCSymbolRefExpr::VK_PPC_HI: 137 Type = ELF::R_PPC_ADDR16_HI; 138 break; 139 case MCSymbolRefExpr::VK_PPC_HA: 140 Type = ELF::R_PPC_ADDR16_HA; 141 break; 142 case MCSymbolRefExpr::VK_PPC_HIGHER: 143 Type = ELF::R_PPC64_ADDR16_HIGHER; 144 break; 145 case MCSymbolRefExpr::VK_PPC_HIGHERA: 146 Type = ELF::R_PPC64_ADDR16_HIGHERA; 147 break; 148 case MCSymbolRefExpr::VK_PPC_HIGHEST: 149 Type = ELF::R_PPC64_ADDR16_HIGHEST; 150 break; 151 case MCSymbolRefExpr::VK_PPC_HIGHESTA: 152 Type = ELF::R_PPC64_ADDR16_HIGHESTA; 153 break; 154 case MCSymbolRefExpr::VK_GOT: 155 Type = ELF::R_PPC_GOT16; 156 break; 157 case MCSymbolRefExpr::VK_PPC_GOT_LO: 158 Type = ELF::R_PPC_GOT16_LO; 159 break; 160 case MCSymbolRefExpr::VK_PPC_GOT_HI: 161 Type = ELF::R_PPC_GOT16_HI; 162 break; 163 case MCSymbolRefExpr::VK_PPC_GOT_HA: 164 Type = ELF::R_PPC_GOT16_HA; 165 break; 166 case MCSymbolRefExpr::VK_PPC_TOC: 167 Type = ELF::R_PPC64_TOC16; 168 break; 169 case MCSymbolRefExpr::VK_PPC_TOC_LO: 170 Type = ELF::R_PPC64_TOC16_LO; 171 break; 172 case MCSymbolRefExpr::VK_PPC_TOC_HI: 173 Type = ELF::R_PPC64_TOC16_HI; 174 break; 175 case MCSymbolRefExpr::VK_PPC_TOC_HA: 176 Type = ELF::R_PPC64_TOC16_HA; 177 break; 178 case MCSymbolRefExpr::VK_PPC_TPREL: 179 Type = ELF::R_PPC_TPREL16; 180 break; 181 case MCSymbolRefExpr::VK_PPC_TPREL_LO: 182 Type = ELF::R_PPC_TPREL16_LO; 183 break; 184 case MCSymbolRefExpr::VK_PPC_TPREL_HI: 185 Type = ELF::R_PPC_TPREL16_HI; 186 break; 187 case MCSymbolRefExpr::VK_PPC_TPREL_HA: 188 Type = ELF::R_PPC_TPREL16_HA; 189 break; 190 case MCSymbolRefExpr::VK_PPC_TPREL_HIGHER: 191 Type = ELF::R_PPC64_TPREL16_HIGHER; 192 break; 193 case MCSymbolRefExpr::VK_PPC_TPREL_HIGHERA: 194 Type = ELF::R_PPC64_TPREL16_HIGHERA; 195 break; 196 case MCSymbolRefExpr::VK_PPC_TPREL_HIGHEST: 197 Type = ELF::R_PPC64_TPREL16_HIGHEST; 198 break; 199 case MCSymbolRefExpr::VK_PPC_TPREL_HIGHESTA: 200 Type = ELF::R_PPC64_TPREL16_HIGHESTA; 201 break; 202 case MCSymbolRefExpr::VK_PPC_DTPREL: 203 Type = ELF::R_PPC64_DTPREL16; 204 break; 205 case MCSymbolRefExpr::VK_PPC_DTPREL_LO: 206 Type = ELF::R_PPC64_DTPREL16_LO; 207 break; 208 case MCSymbolRefExpr::VK_PPC_DTPREL_HI: 209 Type = ELF::R_PPC64_DTPREL16_HI; 210 break; 211 case MCSymbolRefExpr::VK_PPC_DTPREL_HA: 212 Type = ELF::R_PPC64_DTPREL16_HA; 213 break; 214 case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHER: 215 Type = ELF::R_PPC64_DTPREL16_HIGHER; 216 break; 217 case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHERA: 218 Type = ELF::R_PPC64_DTPREL16_HIGHERA; 219 break; 220 case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHEST: 221 Type = ELF::R_PPC64_DTPREL16_HIGHEST; 222 break; 223 case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHESTA: 224 Type = ELF::R_PPC64_DTPREL16_HIGHESTA; 225 break; 226 case MCSymbolRefExpr::VK_PPC_GOT_TLSGD: 227 Type = ELF::R_PPC64_GOT_TLSGD16; 228 break; 229 case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_LO: 230 Type = ELF::R_PPC64_GOT_TLSGD16_LO; 231 break; 232 case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HI: 233 Type = ELF::R_PPC64_GOT_TLSGD16_HI; 234 break; 235 case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HA: 236 Type = ELF::R_PPC64_GOT_TLSGD16_HA; 237 break; 238 case MCSymbolRefExpr::VK_PPC_GOT_TLSLD: 239 Type = ELF::R_PPC64_GOT_TLSLD16; 240 break; 241 case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO: 242 Type = ELF::R_PPC64_GOT_TLSLD16_LO; 243 break; 244 case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HI: 245 Type = ELF::R_PPC64_GOT_TLSLD16_HI; 246 break; 247 case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HA: 248 Type = ELF::R_PPC64_GOT_TLSLD16_HA; 249 break; 250 case MCSymbolRefExpr::VK_PPC_GOT_TPREL: 251 /* We don't have R_PPC64_GOT_TPREL16, but since GOT offsets 252 are always 4-aligned, we can use R_PPC64_GOT_TPREL16_DS. */ 253 Type = ELF::R_PPC64_GOT_TPREL16_DS; 254 break; 255 case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO: 256 /* We don't have R_PPC64_GOT_TPREL16_LO, but since GOT offsets 257 are always 4-aligned, we can use R_PPC64_GOT_TPREL16_LO_DS. */ 258 Type = ELF::R_PPC64_GOT_TPREL16_LO_DS; 259 break; 260 case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HI: 261 Type = ELF::R_PPC64_GOT_TPREL16_HI; 262 break; 263 case MCSymbolRefExpr::VK_PPC_GOT_DTPREL: 264 /* We don't have R_PPC64_GOT_DTPREL16, but since GOT offsets 265 are always 4-aligned, we can use R_PPC64_GOT_DTPREL16_DS. */ 266 Type = ELF::R_PPC64_GOT_DTPREL16_DS; 267 break; 268 case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO: 269 /* We don't have R_PPC64_GOT_DTPREL16_LO, but since GOT offsets 270 are always 4-aligned, we can use R_PPC64_GOT_DTPREL16_LO_DS. */ 271 Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS; 272 break; 273 case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HA: 274 Type = ELF::R_PPC64_GOT_TPREL16_HA; 275 break; 276 case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HI: 277 Type = ELF::R_PPC64_GOT_DTPREL16_HI; 278 break; 279 case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HA: 280 Type = ELF::R_PPC64_GOT_DTPREL16_HA; 281 break; 282 } 283 break; 284 case PPC::fixup_ppc_half16ds: 285 switch (Modifier) { 286 default: llvm_unreachable("Unsupported Modifier"); 287 case MCSymbolRefExpr::VK_None: 288 Type = ELF::R_PPC64_ADDR16_DS; 289 break; 290 case MCSymbolRefExpr::VK_PPC_LO: 291 Type = ELF::R_PPC64_ADDR16_LO_DS; 292 break; 293 case MCSymbolRefExpr::VK_GOT: 294 Type = ELF::R_PPC64_GOT16_DS; 295 break; 296 case MCSymbolRefExpr::VK_PPC_GOT_LO: 297 Type = ELF::R_PPC64_GOT16_LO_DS; 298 break; 299 case MCSymbolRefExpr::VK_PPC_TOC: 300 Type = ELF::R_PPC64_TOC16_DS; 301 break; 302 case MCSymbolRefExpr::VK_PPC_TOC_LO: 303 Type = ELF::R_PPC64_TOC16_LO_DS; 304 break; 305 case MCSymbolRefExpr::VK_PPC_TPREL: 306 Type = ELF::R_PPC64_TPREL16_DS; 307 break; 308 case MCSymbolRefExpr::VK_PPC_TPREL_LO: 309 Type = ELF::R_PPC64_TPREL16_LO_DS; 310 break; 311 case MCSymbolRefExpr::VK_PPC_DTPREL: 312 Type = ELF::R_PPC64_DTPREL16_DS; 313 break; 314 case MCSymbolRefExpr::VK_PPC_DTPREL_LO: 315 Type = ELF::R_PPC64_DTPREL16_LO_DS; 316 break; 317 case MCSymbolRefExpr::VK_PPC_GOT_TPREL: 318 Type = ELF::R_PPC64_GOT_TPREL16_DS; 319 break; 320 case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO: 321 Type = ELF::R_PPC64_GOT_TPREL16_LO_DS; 322 break; 323 case MCSymbolRefExpr::VK_PPC_GOT_DTPREL: 324 Type = ELF::R_PPC64_GOT_DTPREL16_DS; 325 break; 326 case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO: 327 Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS; 328 break; 329 } 330 break; 331 case PPC::fixup_ppc_nofixup: 332 switch (Modifier) { 333 default: llvm_unreachable("Unsupported Modifier"); 334 case MCSymbolRefExpr::VK_PPC_TLSGD: 335 Type = ELF::R_PPC64_TLSGD; 336 break; 337 case MCSymbolRefExpr::VK_PPC_TLSLD: 338 Type = ELF::R_PPC64_TLSLD; 339 break; 340 case MCSymbolRefExpr::VK_PPC_TLS: 341 Type = ELF::R_PPC64_TLS; 342 break; 343 } 344 break; 345 case FK_Data_8: 346 switch (Modifier) { 347 default: llvm_unreachable("Unsupported Modifier"); 348 case MCSymbolRefExpr::VK_PPC_TOCBASE: 349 Type = ELF::R_PPC64_TOC; 350 break; 351 case MCSymbolRefExpr::VK_None: 352 Type = ELF::R_PPC64_ADDR64; 353 break; 354 case MCSymbolRefExpr::VK_PPC_DTPMOD: 355 Type = ELF::R_PPC64_DTPMOD64; 356 break; 357 case MCSymbolRefExpr::VK_PPC_TPREL: 358 Type = ELF::R_PPC64_TPREL64; 359 break; 360 case MCSymbolRefExpr::VK_PPC_DTPREL: 361 Type = ELF::R_PPC64_DTPREL64; 362 break; 363 } 364 break; 365 case FK_Data_4: 366 Type = ELF::R_PPC_ADDR32; 367 break; 368 case FK_Data_2: 369 Type = ELF::R_PPC_ADDR16; 370 break; 371 } 372 } 373 return Type; 374} 375 376unsigned PPCELFObjectWriter::GetRelocType(const MCValue &Target, 377 const MCFixup &Fixup, 378 bool IsPCRel) const { 379 return getRelocTypeInner(Target, Fixup, IsPCRel); 380} 381 382MCObjectWriter *llvm::createPPCELFObjectWriter(raw_ostream &OS, 383 bool Is64Bit, 384 bool IsLittleEndian, 385 uint8_t OSABI) { 386 MCELFObjectTargetWriter *MOTW = new PPCELFObjectWriter(Is64Bit, OSABI); 387 return createELFObjectWriter(MOTW, OS, IsLittleEndian); 388} 389