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 "llvm/ADT/STLExtras.h" 13 #include "llvm/MC/MCELFObjectWriter.h" 14 #include "llvm/MC/MCExpr.h" 15 #include "llvm/MC/MCValue.h" 16 #include "llvm/Support/ErrorHandling.h" 17 18 using namespace llvm; 19 20 namespace { 21 class PPCELFObjectWriter : public MCELFObjectTargetWriter { 22 public: 23 PPCELFObjectWriter(bool Is64Bit, uint8_t OSABI); 24 25 virtual ~PPCELFObjectWriter(); 26 protected: 27 virtual unsigned getRelocTypeInner(const MCValue &Target, 28 const MCFixup &Fixup, 29 bool IsPCRel) const; 30 virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, 31 bool IsPCRel, bool IsRelocWithSymbol, 32 int64_t Addend) const; 33 virtual const MCSymbol *undefinedExplicitRelSym(const MCValue &Target, 34 const MCFixup &Fixup, 35 bool IsPCRel) const; 36 }; 37 } 38 39 PPCELFObjectWriter::PPCELFObjectWriter(bool Is64Bit, uint8_t OSABI) 40 : MCELFObjectTargetWriter(Is64Bit, OSABI, 41 Is64Bit ? ELF::EM_PPC64 : ELF::EM_PPC, 42 /*HasRelocationAddend*/ true) {} 43 44 PPCELFObjectWriter::~PPCELFObjectWriter() { 45 } 46 47 unsigned PPCELFObjectWriter::getRelocTypeInner(const MCValue &Target, 48 const MCFixup &Fixup, 49 bool IsPCRel) const 50 { 51 MCSymbolRefExpr::VariantKind Modifier = Target.isAbsolute() ? 52 MCSymbolRefExpr::VK_None : Target.getSymA()->getKind(); 53 54 // determine the type of the relocation 55 unsigned Type; 56 if (IsPCRel) { 57 switch ((unsigned)Fixup.getKind()) { 58 default: 59 llvm_unreachable("Unimplemented"); 60 case PPC::fixup_ppc_br24: 61 Type = ELF::R_PPC_REL24; 62 break; 63 case PPC::fixup_ppc_brcond14: 64 Type = ELF::R_PPC_REL14; 65 break; 66 case PPC::fixup_ppc_half16: 67 switch (Modifier) { 68 default: llvm_unreachable("Unsupported Modifier"); 69 case MCSymbolRefExpr::VK_None: 70 Type = ELF::R_PPC_REL16; 71 break; 72 case MCSymbolRefExpr::VK_PPC_LO: 73 Type = ELF::R_PPC_REL16_LO; 74 break; 75 case MCSymbolRefExpr::VK_PPC_HI: 76 Type = ELF::R_PPC_REL16_HI; 77 break; 78 case MCSymbolRefExpr::VK_PPC_HA: 79 Type = ELF::R_PPC_REL16_HA; 80 break; 81 } 82 break; 83 case FK_Data_4: 84 case FK_PCRel_4: 85 Type = ELF::R_PPC_REL32; 86 break; 87 case FK_Data_8: 88 case FK_PCRel_8: 89 Type = ELF::R_PPC64_REL64; 90 break; 91 } 92 } else { 93 switch ((unsigned)Fixup.getKind()) { 94 default: llvm_unreachable("invalid fixup kind!"); 95 case PPC::fixup_ppc_br24: 96 Type = ELF::R_PPC_ADDR24; 97 break; 98 case PPC::fixup_ppc_brcond14: 99 Type = ELF::R_PPC_ADDR14; // XXX: or BRNTAKEN?_ 100 break; 101 case PPC::fixup_ppc_half16: 102 switch (Modifier) { 103 default: llvm_unreachable("Unsupported Modifier"); 104 case MCSymbolRefExpr::VK_None: 105 Type = ELF::R_PPC_ADDR16; 106 break; 107 case MCSymbolRefExpr::VK_PPC_LO: 108 Type = ELF::R_PPC_ADDR16_LO; 109 break; 110 case MCSymbolRefExpr::VK_PPC_HI: 111 Type = ELF::R_PPC_ADDR16_HI; 112 break; 113 case MCSymbolRefExpr::VK_PPC_HA: 114 Type = ELF::R_PPC_ADDR16_HA; 115 break; 116 case MCSymbolRefExpr::VK_PPC_HIGHER: 117 Type = ELF::R_PPC64_ADDR16_HIGHER; 118 break; 119 case MCSymbolRefExpr::VK_PPC_HIGHERA: 120 Type = ELF::R_PPC64_ADDR16_HIGHERA; 121 break; 122 case MCSymbolRefExpr::VK_PPC_HIGHEST: 123 Type = ELF::R_PPC64_ADDR16_HIGHEST; 124 break; 125 case MCSymbolRefExpr::VK_PPC_HIGHESTA: 126 Type = ELF::R_PPC64_ADDR16_HIGHESTA; 127 break; 128 case MCSymbolRefExpr::VK_PPC_TOC: 129 Type = ELF::R_PPC64_TOC16; 130 break; 131 case MCSymbolRefExpr::VK_PPC_TOC_LO: 132 Type = ELF::R_PPC64_TOC16_LO; 133 break; 134 case MCSymbolRefExpr::VK_PPC_TOC_HI: 135 Type = ELF::R_PPC64_TOC16_HI; 136 break; 137 case MCSymbolRefExpr::VK_PPC_TOC_HA: 138 Type = ELF::R_PPC64_TOC16_HA; 139 break; 140 case MCSymbolRefExpr::VK_PPC_TPREL: 141 Type = ELF::R_PPC_TPREL16; 142 break; 143 case MCSymbolRefExpr::VK_PPC_TPREL_LO: 144 Type = ELF::R_PPC_TPREL16_LO; 145 break; 146 case MCSymbolRefExpr::VK_PPC_TPREL_HI: 147 Type = ELF::R_PPC_TPREL16_HI; 148 break; 149 case MCSymbolRefExpr::VK_PPC_TPREL_HA: 150 Type = ELF::R_PPC_TPREL16_HA; 151 break; 152 case MCSymbolRefExpr::VK_PPC_TPREL_HIGHER: 153 Type = ELF::R_PPC64_TPREL16_HIGHER; 154 break; 155 case MCSymbolRefExpr::VK_PPC_TPREL_HIGHERA: 156 Type = ELF::R_PPC64_TPREL16_HIGHERA; 157 break; 158 case MCSymbolRefExpr::VK_PPC_TPREL_HIGHEST: 159 Type = ELF::R_PPC64_TPREL16_HIGHEST; 160 break; 161 case MCSymbolRefExpr::VK_PPC_TPREL_HIGHESTA: 162 Type = ELF::R_PPC64_TPREL16_HIGHESTA; 163 break; 164 case MCSymbolRefExpr::VK_PPC_DTPREL: 165 Type = ELF::R_PPC64_DTPREL16; 166 break; 167 case MCSymbolRefExpr::VK_PPC_DTPREL_LO: 168 Type = ELF::R_PPC64_DTPREL16_LO; 169 break; 170 case MCSymbolRefExpr::VK_PPC_DTPREL_HI: 171 Type = ELF::R_PPC64_DTPREL16_HI; 172 break; 173 case MCSymbolRefExpr::VK_PPC_DTPREL_HA: 174 Type = ELF::R_PPC64_DTPREL16_HA; 175 break; 176 case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHER: 177 Type = ELF::R_PPC64_DTPREL16_HIGHER; 178 break; 179 case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHERA: 180 Type = ELF::R_PPC64_DTPREL16_HIGHERA; 181 break; 182 case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHEST: 183 Type = ELF::R_PPC64_DTPREL16_HIGHEST; 184 break; 185 case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHESTA: 186 Type = ELF::R_PPC64_DTPREL16_HIGHESTA; 187 break; 188 case MCSymbolRefExpr::VK_PPC_GOT_TLSGD: 189 Type = ELF::R_PPC64_GOT_TLSGD16; 190 break; 191 case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_LO: 192 Type = ELF::R_PPC64_GOT_TLSGD16_LO; 193 break; 194 case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HI: 195 Type = ELF::R_PPC64_GOT_TLSGD16_HI; 196 break; 197 case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HA: 198 Type = ELF::R_PPC64_GOT_TLSGD16_HA; 199 break; 200 case MCSymbolRefExpr::VK_PPC_GOT_TLSLD: 201 Type = ELF::R_PPC64_GOT_TLSLD16; 202 break; 203 case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO: 204 Type = ELF::R_PPC64_GOT_TLSLD16_LO; 205 break; 206 case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HI: 207 Type = ELF::R_PPC64_GOT_TLSLD16_HI; 208 break; 209 case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HA: 210 Type = ELF::R_PPC64_GOT_TLSLD16_HA; 211 break; 212 case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HI: 213 Type = ELF::R_PPC64_GOT_TPREL16_HI; 214 break; 215 case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HA: 216 Type = ELF::R_PPC64_GOT_TPREL16_HA; 217 break; 218 case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HI: 219 Type = ELF::R_PPC64_GOT_DTPREL16_HI; 220 break; 221 case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HA: 222 Type = ELF::R_PPC64_GOT_DTPREL16_HA; 223 break; 224 } 225 break; 226 case PPC::fixup_ppc_half16ds: 227 switch (Modifier) { 228 default: llvm_unreachable("Unsupported Modifier"); 229 case MCSymbolRefExpr::VK_None: 230 Type = ELF::R_PPC64_ADDR16_DS; 231 break; 232 case MCSymbolRefExpr::VK_PPC_LO: 233 Type = ELF::R_PPC64_ADDR16_LO_DS; 234 break; 235 case MCSymbolRefExpr::VK_PPC_TOC: 236 Type = ELF::R_PPC64_TOC16_DS; 237 break; 238 case MCSymbolRefExpr::VK_PPC_TOC_LO: 239 Type = ELF::R_PPC64_TOC16_LO_DS; 240 break; 241 case MCSymbolRefExpr::VK_PPC_TPREL: 242 Type = ELF::R_PPC64_TPREL16_DS; 243 break; 244 case MCSymbolRefExpr::VK_PPC_TPREL_LO: 245 Type = ELF::R_PPC64_TPREL16_LO_DS; 246 break; 247 case MCSymbolRefExpr::VK_PPC_DTPREL: 248 Type = ELF::R_PPC64_DTPREL16_DS; 249 break; 250 case MCSymbolRefExpr::VK_PPC_DTPREL_LO: 251 Type = ELF::R_PPC64_DTPREL16_LO_DS; 252 break; 253 case MCSymbolRefExpr::VK_PPC_GOT_TPREL: 254 Type = ELF::R_PPC64_GOT_TPREL16_DS; 255 break; 256 case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO: 257 Type = ELF::R_PPC64_GOT_TPREL16_LO_DS; 258 break; 259 case MCSymbolRefExpr::VK_PPC_GOT_DTPREL: 260 Type = ELF::R_PPC64_GOT_DTPREL16_DS; 261 break; 262 case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO: 263 Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS; 264 break; 265 } 266 break; 267 case PPC::fixup_ppc_tlsreg: 268 Type = ELF::R_PPC64_TLS; 269 break; 270 case PPC::fixup_ppc_nofixup: 271 switch (Modifier) { 272 default: llvm_unreachable("Unsupported Modifier"); 273 case MCSymbolRefExpr::VK_PPC_TLSGD: 274 Type = ELF::R_PPC64_TLSGD; 275 break; 276 case MCSymbolRefExpr::VK_PPC_TLSLD: 277 Type = ELF::R_PPC64_TLSLD; 278 break; 279 } 280 break; 281 case FK_Data_8: 282 switch (Modifier) { 283 default: llvm_unreachable("Unsupported Modifier"); 284 case MCSymbolRefExpr::VK_PPC_TOCBASE: 285 Type = ELF::R_PPC64_TOC; 286 break; 287 case MCSymbolRefExpr::VK_None: 288 Type = ELF::R_PPC64_ADDR64; 289 break; 290 } 291 break; 292 case FK_Data_4: 293 Type = ELF::R_PPC_ADDR32; 294 break; 295 case FK_Data_2: 296 Type = ELF::R_PPC_ADDR16; 297 break; 298 } 299 } 300 return Type; 301 } 302 303 unsigned PPCELFObjectWriter::GetRelocType(const MCValue &Target, 304 const MCFixup &Fixup, 305 bool IsPCRel, 306 bool IsRelocWithSymbol, 307 int64_t Addend) const { 308 return getRelocTypeInner(Target, Fixup, IsPCRel); 309 } 310 311 const MCSymbol *PPCELFObjectWriter::undefinedExplicitRelSym(const MCValue &Target, 312 const MCFixup &Fixup, 313 bool IsPCRel) const { 314 assert(Target.getSymA() && "SymA cannot be 0"); 315 const MCSymbol &Symbol = Target.getSymA()->getSymbol().AliasedSymbol(); 316 317 unsigned RelocType = getRelocTypeInner(Target, Fixup, IsPCRel); 318 319 // The .odp creation emits a relocation against the symbol ".TOC." which 320 // create a R_PPC64_TOC relocation. However the relocation symbol name 321 // in final object creation should be NULL, since the symbol does not 322 // really exist, it is just the reference to TOC base for the current 323 // object file. 324 bool EmitThisSym = RelocType != ELF::R_PPC64_TOC; 325 326 if (EmitThisSym && !Symbol.isTemporary()) 327 return &Symbol; 328 return NULL; 329 } 330 331 MCObjectWriter *llvm::createPPCELFObjectWriter(raw_ostream &OS, 332 bool Is64Bit, 333 uint8_t OSABI) { 334 MCELFObjectTargetWriter *MOTW = new PPCELFObjectWriter(Is64Bit, OSABI); 335 return createELFObjectWriter(MOTW, OS, /*IsLittleEndian=*/false); 336 } 337