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/MC/MCELFObjectWriter.h" 13 #include "llvm/MC/MCExpr.h" 14 #include "llvm/MC/MCValue.h" 15 #include "llvm/Support/ErrorHandling.h" 16 17 using namespace llvm; 18 19 namespace { 20 class PPCELFObjectWriter : public MCELFObjectTargetWriter { 21 public: 22 PPCELFObjectWriter(bool Is64Bit, uint8_t OSABI); 23 24 virtual ~PPCELFObjectWriter(); 25 protected: 26 virtual unsigned getRelocTypeInner(const MCValue &Target, 27 const MCFixup &Fixup, 28 bool IsPCRel) const; 29 virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, 30 bool IsPCRel, bool IsRelocWithSymbol, 31 int64_t Addend) const; 32 virtual const MCSymbol *undefinedExplicitRelSym(const MCValue &Target, 33 const MCFixup &Fixup, 34 bool IsPCRel) const; 35 virtual void adjustFixupOffset(const MCFixup &Fixup, uint64_t &RelocOffset); 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 FK_PCRel_4: 64 Type = ELF::R_PPC_REL32; 65 break; 66 } 67 } else { 68 switch ((unsigned)Fixup.getKind()) { 69 default: llvm_unreachable("invalid fixup kind!"); 70 case PPC::fixup_ppc_br24: 71 Type = ELF::R_PPC_ADDR24; 72 break; 73 case PPC::fixup_ppc_brcond14: 74 Type = ELF::R_PPC_ADDR14; // XXX: or BRNTAKEN?_ 75 break; 76 case PPC::fixup_ppc_ha16: 77 switch (Modifier) { 78 default: llvm_unreachable("Unsupported Modifier"); 79 case MCSymbolRefExpr::VK_PPC_TPREL16_HA: 80 Type = ELF::R_PPC_TPREL16_HA; 81 break; 82 case MCSymbolRefExpr::VK_PPC_DTPREL16_HA: 83 Type = ELF::R_PPC64_DTPREL16_HA; 84 break; 85 case MCSymbolRefExpr::VK_None: 86 Type = ELF::R_PPC_ADDR16_HA; 87 break; 88 case MCSymbolRefExpr::VK_PPC_TOC16_HA: 89 Type = ELF::R_PPC64_TOC16_HA; 90 break; 91 case MCSymbolRefExpr::VK_PPC_GOT_TLSGD16_HA: 92 Type = ELF::R_PPC64_GOT_TLSGD16_HA; 93 break; 94 case MCSymbolRefExpr::VK_PPC_GOT_TLSLD16_HA: 95 Type = ELF::R_PPC64_GOT_TLSLD16_HA; 96 break; 97 } 98 break; 99 case PPC::fixup_ppc_lo16: 100 switch (Modifier) { 101 default: llvm_unreachable("Unsupported Modifier"); 102 case MCSymbolRefExpr::VK_PPC_TPREL16_LO: 103 Type = ELF::R_PPC_TPREL16_LO; 104 break; 105 case MCSymbolRefExpr::VK_PPC_DTPREL16_LO: 106 Type = ELF::R_PPC64_DTPREL16_LO; 107 break; 108 case MCSymbolRefExpr::VK_None: 109 Type = ELF::R_PPC_ADDR16_LO; 110 break; 111 case MCSymbolRefExpr::VK_PPC_TOC16_LO: 112 Type = ELF::R_PPC64_TOC16_LO; 113 break; 114 case MCSymbolRefExpr::VK_PPC_GOT_TLSGD16_LO: 115 Type = ELF::R_PPC64_GOT_TLSGD16_LO; 116 break; 117 case MCSymbolRefExpr::VK_PPC_GOT_TLSLD16_LO: 118 Type = ELF::R_PPC64_GOT_TLSLD16_LO; 119 break; 120 } 121 break; 122 case PPC::fixup_ppc_lo14: 123 Type = ELF::R_PPC_ADDR14; 124 break; 125 case PPC::fixup_ppc_toc: 126 Type = ELF::R_PPC64_TOC; 127 break; 128 case PPC::fixup_ppc_toc16: 129 Type = ELF::R_PPC64_TOC16; 130 break; 131 case PPC::fixup_ppc_toc16_ds: 132 switch (Modifier) { 133 default: llvm_unreachable("Unsupported Modifier"); 134 case MCSymbolRefExpr::VK_PPC_TOC_ENTRY: 135 Type = ELF::R_PPC64_TOC16_DS; 136 break; 137 case MCSymbolRefExpr::VK_PPC_TOC16_LO: 138 Type = ELF::R_PPC64_TOC16_LO_DS; 139 break; 140 case MCSymbolRefExpr::VK_PPC_GOT_TPREL16_DS: 141 Type = ELF::R_PPC64_GOT_TPREL16_DS; 142 break; 143 } 144 break; 145 case PPC::fixup_ppc_tlsreg: 146 Type = ELF::R_PPC64_TLS; 147 break; 148 case PPC::fixup_ppc_nofixup: 149 switch (Modifier) { 150 default: llvm_unreachable("Unsupported Modifier"); 151 case MCSymbolRefExpr::VK_PPC_TLSGD: 152 Type = ELF::R_PPC64_TLSGD; 153 break; 154 case MCSymbolRefExpr::VK_PPC_TLSLD: 155 Type = ELF::R_PPC64_TLSLD; 156 break; 157 } 158 break; 159 case FK_Data_8: 160 switch (Modifier) { 161 default: llvm_unreachable("Unsupported Modifier"); 162 case MCSymbolRefExpr::VK_PPC_TOC: 163 Type = ELF::R_PPC64_TOC; 164 break; 165 case MCSymbolRefExpr::VK_None: 166 Type = ELF::R_PPC64_ADDR64; 167 break; 168 } 169 break; 170 case FK_Data_4: 171 Type = ELF::R_PPC_ADDR32; 172 break; 173 case FK_Data_2: 174 Type = ELF::R_PPC_ADDR16; 175 break; 176 } 177 } 178 return Type; 179 } 180 181 unsigned PPCELFObjectWriter::GetRelocType(const MCValue &Target, 182 const MCFixup &Fixup, 183 bool IsPCRel, 184 bool IsRelocWithSymbol, 185 int64_t Addend) const { 186 return getRelocTypeInner(Target, Fixup, IsPCRel); 187 } 188 189 const MCSymbol *PPCELFObjectWriter::undefinedExplicitRelSym(const MCValue &Target, 190 const MCFixup &Fixup, 191 bool IsPCRel) const { 192 assert(Target.getSymA() && "SymA cannot be 0"); 193 const MCSymbol &Symbol = Target.getSymA()->getSymbol().AliasedSymbol(); 194 195 unsigned RelocType = getRelocTypeInner(Target, Fixup, IsPCRel); 196 197 // The .odp creation emits a relocation against the symbol ".TOC." which 198 // create a R_PPC64_TOC relocation. However the relocation symbol name 199 // in final object creation should be NULL, since the symbol does not 200 // really exist, it is just the reference to TOC base for the current 201 // object file. 202 bool EmitThisSym = RelocType != ELF::R_PPC64_TOC; 203 204 if (EmitThisSym && !Symbol.isTemporary()) 205 return &Symbol; 206 return NULL; 207 } 208 209 void PPCELFObjectWriter:: 210 adjustFixupOffset(const MCFixup &Fixup, uint64_t &RelocOffset) { 211 switch ((unsigned)Fixup.getKind()) { 212 case PPC::fixup_ppc_ha16: 213 case PPC::fixup_ppc_lo16: 214 case PPC::fixup_ppc_toc16: 215 case PPC::fixup_ppc_toc16_ds: 216 RelocOffset += 2; 217 break; 218 default: 219 break; 220 } 221 } 222 223 MCObjectWriter *llvm::createPPCELFObjectWriter(raw_ostream &OS, 224 bool Is64Bit, 225 uint8_t OSABI) { 226 MCELFObjectTargetWriter *MOTW = new PPCELFObjectWriter(Is64Bit, OSABI); 227 return createELFObjectWriter(MOTW, OS, /*IsLittleEndian=*/false); 228 } 229