MipsELFObjectWriter.cpp revision 36b56886974eae4f9c5ebc96befd3e7bfe5de338
1//===-- MipsELFObjectWriter.cpp - Mips 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/MipsBaseInfo.h" 11#include "MCTargetDesc/MipsFixupKinds.h" 12#include "MCTargetDesc/MipsMCTargetDesc.h" 13#include "llvm/MC/MCAssembler.h" 14#include "llvm/MC/MCELFObjectWriter.h" 15#include "llvm/MC/MCExpr.h" 16#include "llvm/MC/MCSection.h" 17#include "llvm/MC/MCValue.h" 18#include "llvm/Support/ErrorHandling.h" 19#include <list> 20 21using namespace llvm; 22 23namespace { 24 class MipsELFObjectWriter : public MCELFObjectTargetWriter { 25 public: 26 MipsELFObjectWriter(bool _is64Bit, uint8_t OSABI, 27 bool _isN64, bool IsLittleEndian); 28 29 virtual ~MipsELFObjectWriter(); 30 31 unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, 32 bool IsPCRel) const override; 33 bool needsRelocateWithSymbol(unsigned Type) const override; 34 }; 35} 36 37MipsELFObjectWriter::MipsELFObjectWriter(bool _is64Bit, uint8_t OSABI, 38 bool _isN64, bool IsLittleEndian) 39 : MCELFObjectTargetWriter(_is64Bit, OSABI, ELF::EM_MIPS, 40 /*HasRelocationAddend*/ (_isN64) ? true : false, 41 /*IsN64*/ _isN64) {} 42 43MipsELFObjectWriter::~MipsELFObjectWriter() {} 44 45unsigned MipsELFObjectWriter::GetRelocType(const MCValue &Target, 46 const MCFixup &Fixup, 47 bool IsPCRel) const { 48 // determine the type of the relocation 49 unsigned Type = (unsigned)ELF::R_MIPS_NONE; 50 unsigned Kind = (unsigned)Fixup.getKind(); 51 52 switch (Kind) { 53 default: 54 llvm_unreachable("invalid fixup kind!"); 55 case FK_Data_4: 56 Type = ELF::R_MIPS_32; 57 break; 58 case FK_Data_8: 59 Type = ELF::R_MIPS_64; 60 break; 61 case FK_GPRel_4: 62 if (isN64()) { 63 Type = setRType((unsigned)ELF::R_MIPS_GPREL32, Type); 64 Type = setRType2((unsigned)ELF::R_MIPS_64, Type); 65 Type = setRType3((unsigned)ELF::R_MIPS_NONE, Type); 66 } 67 else 68 Type = ELF::R_MIPS_GPREL32; 69 break; 70 case Mips::fixup_Mips_GPREL16: 71 Type = ELF::R_MIPS_GPREL16; 72 break; 73 case Mips::fixup_Mips_26: 74 Type = ELF::R_MIPS_26; 75 break; 76 case Mips::fixup_Mips_CALL16: 77 Type = ELF::R_MIPS_CALL16; 78 break; 79 case Mips::fixup_Mips_GOT_Global: 80 case Mips::fixup_Mips_GOT_Local: 81 Type = ELF::R_MIPS_GOT16; 82 break; 83 case Mips::fixup_Mips_HI16: 84 Type = ELF::R_MIPS_HI16; 85 break; 86 case Mips::fixup_Mips_LO16: 87 Type = ELF::R_MIPS_LO16; 88 break; 89 case Mips::fixup_Mips_TLSGD: 90 Type = ELF::R_MIPS_TLS_GD; 91 break; 92 case Mips::fixup_Mips_GOTTPREL: 93 Type = ELF::R_MIPS_TLS_GOTTPREL; 94 break; 95 case Mips::fixup_Mips_TPREL_HI: 96 Type = ELF::R_MIPS_TLS_TPREL_HI16; 97 break; 98 case Mips::fixup_Mips_TPREL_LO: 99 Type = ELF::R_MIPS_TLS_TPREL_LO16; 100 break; 101 case Mips::fixup_Mips_TLSLDM: 102 Type = ELF::R_MIPS_TLS_LDM; 103 break; 104 case Mips::fixup_Mips_DTPREL_HI: 105 Type = ELF::R_MIPS_TLS_DTPREL_HI16; 106 break; 107 case Mips::fixup_Mips_DTPREL_LO: 108 Type = ELF::R_MIPS_TLS_DTPREL_LO16; 109 break; 110 case Mips::fixup_Mips_Branch_PCRel: 111 case Mips::fixup_Mips_PC16: 112 Type = ELF::R_MIPS_PC16; 113 break; 114 case Mips::fixup_Mips_GOT_PAGE: 115 Type = ELF::R_MIPS_GOT_PAGE; 116 break; 117 case Mips::fixup_Mips_GOT_OFST: 118 Type = ELF::R_MIPS_GOT_OFST; 119 break; 120 case Mips::fixup_Mips_GOT_DISP: 121 Type = ELF::R_MIPS_GOT_DISP; 122 break; 123 case Mips::fixup_Mips_GPOFF_HI: 124 Type = setRType((unsigned)ELF::R_MIPS_GPREL16, Type); 125 Type = setRType2((unsigned)ELF::R_MIPS_SUB, Type); 126 Type = setRType3((unsigned)ELF::R_MIPS_HI16, Type); 127 break; 128 case Mips::fixup_Mips_GPOFF_LO: 129 Type = setRType((unsigned)ELF::R_MIPS_GPREL16, Type); 130 Type = setRType2((unsigned)ELF::R_MIPS_SUB, Type); 131 Type = setRType3((unsigned)ELF::R_MIPS_LO16, Type); 132 break; 133 case Mips::fixup_Mips_HIGHER: 134 Type = ELF::R_MIPS_HIGHER; 135 break; 136 case Mips::fixup_Mips_HIGHEST: 137 Type = ELF::R_MIPS_HIGHEST; 138 break; 139 case Mips::fixup_Mips_GOT_HI16: 140 Type = ELF::R_MIPS_GOT_HI16; 141 break; 142 case Mips::fixup_Mips_GOT_LO16: 143 Type = ELF::R_MIPS_GOT_LO16; 144 break; 145 case Mips::fixup_Mips_CALL_HI16: 146 Type = ELF::R_MIPS_CALL_HI16; 147 break; 148 case Mips::fixup_Mips_CALL_LO16: 149 Type = ELF::R_MIPS_CALL_LO16; 150 break; 151 case Mips::fixup_MICROMIPS_26_S1: 152 Type = ELF::R_MICROMIPS_26_S1; 153 break; 154 case Mips::fixup_MICROMIPS_HI16: 155 Type = ELF::R_MICROMIPS_HI16; 156 break; 157 case Mips::fixup_MICROMIPS_LO16: 158 Type = ELF::R_MICROMIPS_LO16; 159 break; 160 case Mips::fixup_MICROMIPS_GOT16: 161 Type = ELF::R_MICROMIPS_GOT16; 162 break; 163 case Mips::fixup_MICROMIPS_PC16_S1: 164 Type = ELF::R_MICROMIPS_PC16_S1; 165 break; 166 case Mips::fixup_MICROMIPS_CALL16: 167 Type = ELF::R_MICROMIPS_CALL16; 168 break; 169 case Mips::fixup_MICROMIPS_GOT_DISP: 170 Type = ELF::R_MICROMIPS_GOT_DISP; 171 break; 172 case Mips::fixup_MICROMIPS_GOT_PAGE: 173 Type = ELF::R_MICROMIPS_GOT_PAGE; 174 break; 175 case Mips::fixup_MICROMIPS_GOT_OFST: 176 Type = ELF::R_MICROMIPS_GOT_OFST; 177 break; 178 case Mips::fixup_MICROMIPS_TLS_GD: 179 Type = ELF::R_MICROMIPS_TLS_GD; 180 break; 181 case Mips::fixup_MICROMIPS_TLS_LDM: 182 Type = ELF::R_MICROMIPS_TLS_LDM; 183 break; 184 case Mips::fixup_MICROMIPS_TLS_DTPREL_HI16: 185 Type = ELF::R_MICROMIPS_TLS_DTPREL_HI16; 186 break; 187 case Mips::fixup_MICROMIPS_TLS_DTPREL_LO16: 188 Type = ELF::R_MICROMIPS_TLS_DTPREL_LO16; 189 break; 190 case Mips::fixup_MICROMIPS_TLS_TPREL_HI16: 191 Type = ELF::R_MICROMIPS_TLS_TPREL_HI16; 192 break; 193 case Mips::fixup_MICROMIPS_TLS_TPREL_LO16: 194 Type = ELF::R_MICROMIPS_TLS_TPREL_LO16; 195 break; 196 } 197 return Type; 198} 199 200bool 201MipsELFObjectWriter::needsRelocateWithSymbol(unsigned Type) const { 202 // FIXME: This is extremelly conservative. This really needs to use a 203 // whitelist with a clear explanation for why each realocation needs to 204 // point to the symbol, not to the section. 205 switch (Type) { 206 default: 207 return true; 208 209 case ELF::R_MIPS_GOT16: 210 case ELF::R_MIPS16_GOT16: 211 case ELF::R_MICROMIPS_GOT16: 212 llvm_unreachable("Should have been handled already"); 213 214 // These relocations might be paired with another relocation. The pairing is 215 // done by the static linker by matching the symbol. Since we only see one 216 // relocation at a time, we have to force them to relocate with a symbol to 217 // avoid ending up with a pair where one points to a section and another 218 // points to a symbol. 219 case ELF::R_MIPS_HI16: 220 case ELF::R_MIPS16_HI16: 221 case ELF::R_MICROMIPS_HI16: 222 case ELF::R_MIPS_LO16: 223 case ELF::R_MIPS16_LO16: 224 case ELF::R_MICROMIPS_LO16: 225 return true; 226 227 case ELF::R_MIPS_26: 228 case ELF::R_MIPS_32: 229 case ELF::R_MIPS_64: 230 case ELF::R_MIPS_GPREL16: 231 return false; 232 } 233} 234 235MCObjectWriter *llvm::createMipsELFObjectWriter(raw_ostream &OS, 236 uint8_t OSABI, 237 bool IsLittleEndian, 238 bool Is64Bit) { 239 MCELFObjectTargetWriter *MOTW = new MipsELFObjectWriter(Is64Bit, OSABI, 240 (Is64Bit) ? true : false, 241 IsLittleEndian); 242 return createELFObjectWriter(MOTW, OS, IsLittleEndian); 243} 244