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