LLVM API Documentation
00001 //===-- MipsELFObjectWriter.cpp - Mips ELF Writer -------------------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 00010 #include "MCTargetDesc/MipsBaseInfo.h" 00011 #include "MCTargetDesc/MipsFixupKinds.h" 00012 #include "MCTargetDesc/MipsMCTargetDesc.h" 00013 #include "llvm/MC/MCAssembler.h" 00014 #include "llvm/MC/MCELFObjectWriter.h" 00015 #include "llvm/MC/MCExpr.h" 00016 #include "llvm/MC/MCSection.h" 00017 #include "llvm/MC/MCValue.h" 00018 #include "llvm/Support/ErrorHandling.h" 00019 #include <list> 00020 00021 using namespace llvm; 00022 00023 namespace { 00024 class MipsELFObjectWriter : public MCELFObjectTargetWriter { 00025 public: 00026 MipsELFObjectWriter(bool _is64Bit, uint8_t OSABI, 00027 bool _isN64, bool IsLittleEndian); 00028 00029 virtual ~MipsELFObjectWriter(); 00030 00031 unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, 00032 bool IsPCRel) const override; 00033 bool needsRelocateWithSymbol(const MCSymbolData &SD, 00034 unsigned Type) const override; 00035 }; 00036 } 00037 00038 MipsELFObjectWriter::MipsELFObjectWriter(bool _is64Bit, uint8_t OSABI, 00039 bool _isN64, bool IsLittleEndian) 00040 : MCELFObjectTargetWriter(_is64Bit, OSABI, ELF::EM_MIPS, 00041 /*HasRelocationAddend*/ (_isN64) ? true : false, 00042 /*IsN64*/ _isN64) {} 00043 00044 MipsELFObjectWriter::~MipsELFObjectWriter() {} 00045 00046 unsigned MipsELFObjectWriter::GetRelocType(const MCValue &Target, 00047 const MCFixup &Fixup, 00048 bool IsPCRel) const { 00049 // determine the type of the relocation 00050 unsigned Type = (unsigned)ELF::R_MIPS_NONE; 00051 unsigned Kind = (unsigned)Fixup.getKind(); 00052 00053 switch (Kind) { 00054 default: 00055 llvm_unreachable("invalid fixup kind!"); 00056 case FK_Data_4: 00057 Type = ELF::R_MIPS_32; 00058 break; 00059 case FK_Data_8: 00060 Type = ELF::R_MIPS_64; 00061 break; 00062 case FK_GPRel_4: 00063 if (isN64()) { 00064 Type = setRType((unsigned)ELF::R_MIPS_GPREL32, Type); 00065 Type = setRType2((unsigned)ELF::R_MIPS_64, Type); 00066 Type = setRType3((unsigned)ELF::R_MIPS_NONE, Type); 00067 } 00068 else 00069 Type = ELF::R_MIPS_GPREL32; 00070 break; 00071 case Mips::fixup_Mips_GPREL16: 00072 Type = ELF::R_MIPS_GPREL16; 00073 break; 00074 case Mips::fixup_Mips_26: 00075 Type = ELF::R_MIPS_26; 00076 break; 00077 case Mips::fixup_Mips_CALL16: 00078 Type = ELF::R_MIPS_CALL16; 00079 break; 00080 case Mips::fixup_Mips_GOT_Global: 00081 case Mips::fixup_Mips_GOT_Local: 00082 Type = ELF::R_MIPS_GOT16; 00083 break; 00084 case Mips::fixup_Mips_HI16: 00085 Type = ELF::R_MIPS_HI16; 00086 break; 00087 case Mips::fixup_Mips_LO16: 00088 Type = ELF::R_MIPS_LO16; 00089 break; 00090 case Mips::fixup_Mips_TLSGD: 00091 Type = ELF::R_MIPS_TLS_GD; 00092 break; 00093 case Mips::fixup_Mips_GOTTPREL: 00094 Type = ELF::R_MIPS_TLS_GOTTPREL; 00095 break; 00096 case Mips::fixup_Mips_TPREL_HI: 00097 Type = ELF::R_MIPS_TLS_TPREL_HI16; 00098 break; 00099 case Mips::fixup_Mips_TPREL_LO: 00100 Type = ELF::R_MIPS_TLS_TPREL_LO16; 00101 break; 00102 case Mips::fixup_Mips_TLSLDM: 00103 Type = ELF::R_MIPS_TLS_LDM; 00104 break; 00105 case Mips::fixup_Mips_DTPREL_HI: 00106 Type = ELF::R_MIPS_TLS_DTPREL_HI16; 00107 break; 00108 case Mips::fixup_Mips_DTPREL_LO: 00109 Type = ELF::R_MIPS_TLS_DTPREL_LO16; 00110 break; 00111 case Mips::fixup_Mips_Branch_PCRel: 00112 case Mips::fixup_Mips_PC16: 00113 Type = ELF::R_MIPS_PC16; 00114 break; 00115 case Mips::fixup_Mips_GOT_PAGE: 00116 Type = ELF::R_MIPS_GOT_PAGE; 00117 break; 00118 case Mips::fixup_Mips_GOT_OFST: 00119 Type = ELF::R_MIPS_GOT_OFST; 00120 break; 00121 case Mips::fixup_Mips_GOT_DISP: 00122 Type = ELF::R_MIPS_GOT_DISP; 00123 break; 00124 case Mips::fixup_Mips_GPOFF_HI: 00125 Type = setRType((unsigned)ELF::R_MIPS_GPREL16, Type); 00126 Type = setRType2((unsigned)ELF::R_MIPS_SUB, Type); 00127 Type = setRType3((unsigned)ELF::R_MIPS_HI16, Type); 00128 break; 00129 case Mips::fixup_Mips_GPOFF_LO: 00130 Type = setRType((unsigned)ELF::R_MIPS_GPREL16, Type); 00131 Type = setRType2((unsigned)ELF::R_MIPS_SUB, Type); 00132 Type = setRType3((unsigned)ELF::R_MIPS_LO16, Type); 00133 break; 00134 case Mips::fixup_Mips_HIGHER: 00135 Type = ELF::R_MIPS_HIGHER; 00136 break; 00137 case Mips::fixup_Mips_HIGHEST: 00138 Type = ELF::R_MIPS_HIGHEST; 00139 break; 00140 case Mips::fixup_Mips_GOT_HI16: 00141 Type = ELF::R_MIPS_GOT_HI16; 00142 break; 00143 case Mips::fixup_Mips_GOT_LO16: 00144 Type = ELF::R_MIPS_GOT_LO16; 00145 break; 00146 case Mips::fixup_Mips_CALL_HI16: 00147 Type = ELF::R_MIPS_CALL_HI16; 00148 break; 00149 case Mips::fixup_Mips_CALL_LO16: 00150 Type = ELF::R_MIPS_CALL_LO16; 00151 break; 00152 case Mips::fixup_MICROMIPS_26_S1: 00153 Type = ELF::R_MICROMIPS_26_S1; 00154 break; 00155 case Mips::fixup_MICROMIPS_HI16: 00156 Type = ELF::R_MICROMIPS_HI16; 00157 break; 00158 case Mips::fixup_MICROMIPS_LO16: 00159 Type = ELF::R_MICROMIPS_LO16; 00160 break; 00161 case Mips::fixup_MICROMIPS_GOT16: 00162 Type = ELF::R_MICROMIPS_GOT16; 00163 break; 00164 case Mips::fixup_MICROMIPS_PC16_S1: 00165 Type = ELF::R_MICROMIPS_PC16_S1; 00166 break; 00167 case Mips::fixup_MICROMIPS_CALL16: 00168 Type = ELF::R_MICROMIPS_CALL16; 00169 break; 00170 case Mips::fixup_MICROMIPS_GOT_DISP: 00171 Type = ELF::R_MICROMIPS_GOT_DISP; 00172 break; 00173 case Mips::fixup_MICROMIPS_GOT_PAGE: 00174 Type = ELF::R_MICROMIPS_GOT_PAGE; 00175 break; 00176 case Mips::fixup_MICROMIPS_GOT_OFST: 00177 Type = ELF::R_MICROMIPS_GOT_OFST; 00178 break; 00179 case Mips::fixup_MICROMIPS_TLS_GD: 00180 Type = ELF::R_MICROMIPS_TLS_GD; 00181 break; 00182 case Mips::fixup_MICROMIPS_TLS_LDM: 00183 Type = ELF::R_MICROMIPS_TLS_LDM; 00184 break; 00185 case Mips::fixup_MICROMIPS_TLS_DTPREL_HI16: 00186 Type = ELF::R_MICROMIPS_TLS_DTPREL_HI16; 00187 break; 00188 case Mips::fixup_MICROMIPS_TLS_DTPREL_LO16: 00189 Type = ELF::R_MICROMIPS_TLS_DTPREL_LO16; 00190 break; 00191 case Mips::fixup_MICROMIPS_TLS_TPREL_HI16: 00192 Type = ELF::R_MICROMIPS_TLS_TPREL_HI16; 00193 break; 00194 case Mips::fixup_MICROMIPS_TLS_TPREL_LO16: 00195 Type = ELF::R_MICROMIPS_TLS_TPREL_LO16; 00196 break; 00197 case Mips::fixup_MIPS_PC19_S2: 00198 Type = ELF::R_MIPS_PC19_S2; 00199 break; 00200 case Mips::fixup_MIPS_PC18_S3: 00201 Type = ELF::R_MIPS_PC18_S3; 00202 break; 00203 case Mips::fixup_MIPS_PC21_S2: 00204 Type = ELF::R_MIPS_PC21_S2; 00205 break; 00206 case Mips::fixup_MIPS_PC26_S2: 00207 Type = ELF::R_MIPS_PC26_S2; 00208 break; 00209 case Mips::fixup_MIPS_PCHI16: 00210 Type = ELF::R_MIPS_PCHI16; 00211 break; 00212 case Mips::fixup_MIPS_PCLO16: 00213 Type = ELF::R_MIPS_PCLO16; 00214 break; 00215 } 00216 return Type; 00217 } 00218 00219 bool 00220 MipsELFObjectWriter::needsRelocateWithSymbol(const MCSymbolData &SD, 00221 unsigned Type) const { 00222 // FIXME: This is extremelly conservative. This really needs to use a 00223 // whitelist with a clear explanation for why each realocation needs to 00224 // point to the symbol, not to the section. 00225 switch (Type) { 00226 default: 00227 return true; 00228 00229 case ELF::R_MIPS_GOT16: 00230 case ELF::R_MIPS16_GOT16: 00231 case ELF::R_MICROMIPS_GOT16: 00232 llvm_unreachable("Should have been handled already"); 00233 00234 // These relocations might be paired with another relocation. The pairing is 00235 // done by the static linker by matching the symbol. Since we only see one 00236 // relocation at a time, we have to force them to relocate with a symbol to 00237 // avoid ending up with a pair where one points to a section and another 00238 // points to a symbol. 00239 case ELF::R_MIPS_HI16: 00240 case ELF::R_MIPS16_HI16: 00241 case ELF::R_MICROMIPS_HI16: 00242 case ELF::R_MIPS_LO16: 00243 case ELF::R_MIPS16_LO16: 00244 case ELF::R_MICROMIPS_LO16: 00245 return true; 00246 00247 case ELF::R_MIPS_26: 00248 case ELF::R_MIPS_32: 00249 case ELF::R_MIPS_64: 00250 case ELF::R_MIPS_GPREL16: 00251 return false; 00252 } 00253 } 00254 00255 MCObjectWriter *llvm::createMipsELFObjectWriter(raw_ostream &OS, 00256 uint8_t OSABI, 00257 bool IsLittleEndian, 00258 bool Is64Bit) { 00259 MCELFObjectTargetWriter *MOTW = new MipsELFObjectWriter(Is64Bit, OSABI, 00260 (Is64Bit) ? true : false, 00261 IsLittleEndian); 00262 return createELFObjectWriter(MOTW, OS, IsLittleEndian); 00263 }