1c5707112e7635d1dd2f2cc9c4f42e79a51302ccaJia Liu//===-- MipsELFObjectWriter.cpp - Mips ELF Writer -------------------------===// 2090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola// 3090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola// The LLVM Compiler Infrastructure 4090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola// 5090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola// This file is distributed under the University of Illinois Open Source 6090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola// License. See LICENSE.TXT for details. 7090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola// 8090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola//===----------------------------------------------------------------------===// 9090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola 1037ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka#include "MCTargetDesc/MipsBaseInfo.h" 11090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola#include "MCTargetDesc/MipsFixupKinds.h" 12090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola#include "MCTargetDesc/MipsMCTargetDesc.h" 1337ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka#include "llvm/MC/MCAssembler.h" 14090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola#include "llvm/MC/MCELFObjectWriter.h" 15090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola#include "llvm/MC/MCExpr.h" 16090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola#include "llvm/MC/MCSection.h" 17090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola#include "llvm/MC/MCValue.h" 18090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola#include "llvm/Support/ErrorHandling.h" 1937ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka#include <list> 20090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola 21090445967f0b5988446faffefd1d0722f982bc7aRafael Espindolausing namespace llvm; 22090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola 23090445967f0b5988446faffefd1d0722f982bc7aRafael Espindolanamespace { 2437ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka struct RelEntry { 2537ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka RelEntry(const ELFRelocationEntry &R, const MCSymbol *S, int64_t O) : 2637ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka Reloc(R), Sym(S), Offset(O) {} 2737ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka ELFRelocationEntry Reloc; 2837ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka const MCSymbol *Sym; 2937ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka int64_t Offset; 3037ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka }; 3137ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka 3237ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka typedef std::list<RelEntry> RelLs; 3337ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka typedef RelLs::iterator RelLsIter; 3437ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka 35090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola class MipsELFObjectWriter : public MCELFObjectTargetWriter { 36090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola public: 37b889e0cd2fea4afee623d5be603b912b955a2ecaAkira Hatanaka MipsELFObjectWriter(bool _is64Bit, uint8_t OSABI, 38b889e0cd2fea4afee623d5be603b912b955a2ecaAkira Hatanaka bool _isN64, bool IsLittleEndian); 39090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola 40090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola virtual ~MipsELFObjectWriter(); 41090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola 42090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, 43090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola bool IsPCRel, bool IsRelocWithSymbol, 44090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola int64_t Addend) const; 45090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola virtual const MCSymbol *ExplicitRelSym(const MCAssembler &Asm, 46090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola const MCValue &Target, 47090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola const MCFragment &F, 48090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola const MCFixup &Fixup, 49090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola bool IsPCRel) const; 5037ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka virtual void sortRelocs(const MCAssembler &Asm, 5137ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka std::vector<ELFRelocationEntry> &Relocs); 52090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola }; 53090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola} 54090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola 5593ee286e8d949147f8df7f093c9bd8529a99102dJack CarterMipsELFObjectWriter::MipsELFObjectWriter(bool _is64Bit, uint8_t OSABI, 56b889e0cd2fea4afee623d5be603b912b955a2ecaAkira Hatanaka bool _isN64, bool IsLittleEndian) 57a551a48402385cf3f4b754dc72264b2f0974b1a6Akira Hatanaka : MCELFObjectTargetWriter(_is64Bit, OSABI, ELF::EM_MIPS, 58101771ba4d9c2421f836069fcedf9ddc8a0c9dc7Jack Carter /*HasRelocationAddend*/ (_isN64) ? true : false, 5993ee286e8d949147f8df7f093c9bd8529a99102dJack Carter /*IsN64*/ _isN64) {} 60090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola 61090445967f0b5988446faffefd1d0722f982bc7aRafael EspindolaMipsELFObjectWriter::~MipsELFObjectWriter() {} 62090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola 63090445967f0b5988446faffefd1d0722f982bc7aRafael Espindolaconst MCSymbol *MipsELFObjectWriter::ExplicitRelSym(const MCAssembler &Asm, 64090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola const MCValue &Target, 65090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola const MCFragment &F, 66090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola const MCFixup &Fixup, 67090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola bool IsPCRel) const { 68090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola assert(Target.getSymA() && "SymA cannot be 0."); 692d8955a77c6920d1a50de5ec9094faaa1b2f4e88James Molloy const MCSymbol &Sym = Target.getSymA()->getSymbol().AliasedSymbol(); 70090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola 71090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola if (Sym.getSection().getKind().isMergeableCString() || 72090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola Sym.getSection().getKind().isMergeableConst()) 73090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola return &Sym; 74090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola 75090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola return NULL; 76090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola} 77090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola 78090445967f0b5988446faffefd1d0722f982bc7aRafael Espindolaunsigned MipsELFObjectWriter::GetRelocType(const MCValue &Target, 79090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola const MCFixup &Fixup, 80090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola bool IsPCRel, 81090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola bool IsRelocWithSymbol, 82090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola int64_t Addend) const { 83090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola // determine the type of the relocation 84090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola unsigned Type = (unsigned)ELF::R_MIPS_NONE; 85090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola unsigned Kind = (unsigned)Fixup.getKind(); 86090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola 87090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola switch (Kind) { 88090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola default: 89090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola llvm_unreachable("invalid fixup kind!"); 90090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola case FK_Data_4: 91090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola Type = ELF::R_MIPS_32; 92090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola break; 93e2245bab3ca29dc2142d8f254005f4ae7c40cde2Jack Carter case FK_Data_8: 94e2245bab3ca29dc2142d8f254005f4ae7c40cde2Jack Carter Type = ELF::R_MIPS_64; 95e2245bab3ca29dc2142d8f254005f4ae7c40cde2Jack Carter break; 96090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola case FK_GPRel_4: 97096d617796228293810cb0443c6617b33c5afdc5Jack Carter if (isN64()) { 98096d617796228293810cb0443c6617b33c5afdc5Jack Carter Type = setRType((unsigned)ELF::R_MIPS_GPREL32, Type); 99096d617796228293810cb0443c6617b33c5afdc5Jack Carter Type = setRType2((unsigned)ELF::R_MIPS_64, Type); 100096d617796228293810cb0443c6617b33c5afdc5Jack Carter Type = setRType3((unsigned)ELF::R_MIPS_NONE, Type); 101096d617796228293810cb0443c6617b33c5afdc5Jack Carter } 102096d617796228293810cb0443c6617b33c5afdc5Jack Carter else 103096d617796228293810cb0443c6617b33c5afdc5Jack Carter Type = ELF::R_MIPS_GPREL32; 104090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola break; 105090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola case Mips::fixup_Mips_GPREL16: 106090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola Type = ELF::R_MIPS_GPREL16; 107090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola break; 108090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola case Mips::fixup_Mips_26: 109090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola Type = ELF::R_MIPS_26; 110090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola break; 111090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola case Mips::fixup_Mips_CALL16: 112090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola Type = ELF::R_MIPS_CALL16; 113090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola break; 114090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola case Mips::fixup_Mips_GOT_Global: 115090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola case Mips::fixup_Mips_GOT_Local: 116090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola Type = ELF::R_MIPS_GOT16; 117090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola break; 118090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola case Mips::fixup_Mips_HI16: 119090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola Type = ELF::R_MIPS_HI16; 120090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola break; 121090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola case Mips::fixup_Mips_LO16: 122090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola Type = ELF::R_MIPS_LO16; 123090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola break; 124090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola case Mips::fixup_Mips_TLSGD: 125090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola Type = ELF::R_MIPS_TLS_GD; 126090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola break; 127090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola case Mips::fixup_Mips_GOTTPREL: 128090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola Type = ELF::R_MIPS_TLS_GOTTPREL; 129090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola break; 130090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola case Mips::fixup_Mips_TPREL_HI: 131090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola Type = ELF::R_MIPS_TLS_TPREL_HI16; 132090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola break; 133090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola case Mips::fixup_Mips_TPREL_LO: 134090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola Type = ELF::R_MIPS_TLS_TPREL_LO16; 135090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola break; 136090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola case Mips::fixup_Mips_TLSLDM: 137090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola Type = ELF::R_MIPS_TLS_LDM; 138090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola break; 139090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola case Mips::fixup_Mips_DTPREL_HI: 140090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola Type = ELF::R_MIPS_TLS_DTPREL_HI16; 141090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola break; 142090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola case Mips::fixup_Mips_DTPREL_LO: 143090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola Type = ELF::R_MIPS_TLS_DTPREL_LO16; 144090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola break; 145090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola case Mips::fixup_Mips_Branch_PCRel: 146090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola case Mips::fixup_Mips_PC16: 147090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola Type = ELF::R_MIPS_PC16; 148090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola break; 1490140e55393c4403ab240c386501cdc5e438dcc0eJack Carter case Mips::fixup_Mips_GOT_PAGE: 1500140e55393c4403ab240c386501cdc5e438dcc0eJack Carter Type = ELF::R_MIPS_GOT_PAGE; 1510140e55393c4403ab240c386501cdc5e438dcc0eJack Carter break; 1520140e55393c4403ab240c386501cdc5e438dcc0eJack Carter case Mips::fixup_Mips_GOT_OFST: 1530140e55393c4403ab240c386501cdc5e438dcc0eJack Carter Type = ELF::R_MIPS_GOT_OFST; 1540140e55393c4403ab240c386501cdc5e438dcc0eJack Carter break; 155fd506efec628819f7e6fad8016a9dbb5d8612b8bJack Carter case Mips::fixup_Mips_GOT_DISP: 156fd506efec628819f7e6fad8016a9dbb5d8612b8bJack Carter Type = ELF::R_MIPS_GOT_DISP; 157fd506efec628819f7e6fad8016a9dbb5d8612b8bJack Carter break; 1580140e55393c4403ab240c386501cdc5e438dcc0eJack Carter case Mips::fixup_Mips_GPOFF_HI: 1590140e55393c4403ab240c386501cdc5e438dcc0eJack Carter Type = setRType((unsigned)ELF::R_MIPS_GPREL16, Type); 1600140e55393c4403ab240c386501cdc5e438dcc0eJack Carter Type = setRType2((unsigned)ELF::R_MIPS_SUB, Type); 1610140e55393c4403ab240c386501cdc5e438dcc0eJack Carter Type = setRType3((unsigned)ELF::R_MIPS_HI16, Type); 1620140e55393c4403ab240c386501cdc5e438dcc0eJack Carter break; 1630140e55393c4403ab240c386501cdc5e438dcc0eJack Carter case Mips::fixup_Mips_GPOFF_LO: 1640140e55393c4403ab240c386501cdc5e438dcc0eJack Carter Type = setRType((unsigned)ELF::R_MIPS_GPREL16, Type); 1650140e55393c4403ab240c386501cdc5e438dcc0eJack Carter Type = setRType2((unsigned)ELF::R_MIPS_SUB, Type); 1660140e55393c4403ab240c386501cdc5e438dcc0eJack Carter Type = setRType3((unsigned)ELF::R_MIPS_LO16, Type); 1670140e55393c4403ab240c386501cdc5e438dcc0eJack Carter break; 168fc54d9e47a1276650f14f38e7d037c9b58c8dc2dJack Carter case Mips::fixup_Mips_HIGHER: 169fc54d9e47a1276650f14f38e7d037c9b58c8dc2dJack Carter Type = ELF::R_MIPS_HIGHER; 170fc54d9e47a1276650f14f38e7d037c9b58c8dc2dJack Carter break; 171fc54d9e47a1276650f14f38e7d037c9b58c8dc2dJack Carter case Mips::fixup_Mips_HIGHEST: 172fc54d9e47a1276650f14f38e7d037c9b58c8dc2dJack Carter Type = ELF::R_MIPS_HIGHEST; 173fc54d9e47a1276650f14f38e7d037c9b58c8dc2dJack Carter break; 174198ad916d736047f8a439f19dee25cee917df8a9Jack Carter case Mips::fixup_Mips_GOT_HI16: 175198ad916d736047f8a439f19dee25cee917df8a9Jack Carter Type = ELF::R_MIPS_GOT_HI16; 176198ad916d736047f8a439f19dee25cee917df8a9Jack Carter break; 177198ad916d736047f8a439f19dee25cee917df8a9Jack Carter case Mips::fixup_Mips_GOT_LO16: 178198ad916d736047f8a439f19dee25cee917df8a9Jack Carter Type = ELF::R_MIPS_GOT_LO16; 179198ad916d736047f8a439f19dee25cee917df8a9Jack Carter break; 180198ad916d736047f8a439f19dee25cee917df8a9Jack Carter case Mips::fixup_Mips_CALL_HI16: 181198ad916d736047f8a439f19dee25cee917df8a9Jack Carter Type = ELF::R_MIPS_CALL_HI16; 182198ad916d736047f8a439f19dee25cee917df8a9Jack Carter break; 183198ad916d736047f8a439f19dee25cee917df8a9Jack Carter case Mips::fixup_Mips_CALL_LO16: 184198ad916d736047f8a439f19dee25cee917df8a9Jack Carter Type = ELF::R_MIPS_CALL_LO16; 185198ad916d736047f8a439f19dee25cee917df8a9Jack Carter break; 186090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola } 187090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola return Type; 188090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola} 189090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola 19037ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka// Return true if R is either a GOT16 against a local symbol or HI16. 19137ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanakastatic bool NeedsMatchingLo(const MCAssembler &Asm, const RelEntry &R) { 19237ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka if (!R.Sym) 19337ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka return false; 19437ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka 19537ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka MCSymbolData &SD = Asm.getSymbolData(R.Sym->AliasedSymbol()); 19637ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka 19737ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka return ((R.Reloc.Type == ELF::R_MIPS_GOT16) && !SD.isExternal()) || 19837ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka (R.Reloc.Type == ELF::R_MIPS_HI16); 19937ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka} 20037ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka 20137ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanakastatic bool HasMatchingLo(const MCAssembler &Asm, RelLsIter I, RelLsIter Last) { 20237ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka if (I == Last) 20337ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka return false; 20437ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka 20537ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka RelLsIter Hi = I++; 20637ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka 20737ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka return (I->Reloc.Type == ELF::R_MIPS_LO16) && (Hi->Sym == I->Sym) && 20837ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka (Hi->Offset == I->Offset); 20937ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka} 21037ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka 21137ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanakastatic bool HasSameSymbol(const RelEntry &R0, const RelEntry &R1) { 21237ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka return R0.Sym == R1.Sym; 21337ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka} 21437ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka 21537ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanakastatic int CompareOffset(const RelEntry &R0, const RelEntry &R1) { 21637ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka return (R0.Offset > R1.Offset) ? 1 : ((R0.Offset == R1.Offset) ? 0 : -1); 21737ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka} 21837ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka 21937ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanakavoid MipsELFObjectWriter::sortRelocs(const MCAssembler &Asm, 22037ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka std::vector<ELFRelocationEntry> &Relocs) { 22193ee286e8d949147f8df7f093c9bd8529a99102dJack Carter // Call the default function first. Relocations are sorted in descending 22237ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka // order of r_offset. 22337ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka MCELFObjectTargetWriter::sortRelocs(Asm, Relocs); 224864f66085cd9543070ef01b9f7371c110ecd7898Akira Hatanaka 22537ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka RelLs RelocLs; 22637ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka std::vector<RelLsIter> Unmatched; 22737ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka 22837ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka // Fill RelocLs. Traverse Relocs backwards so that relocations in RelocLs 22937ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka // are in ascending order of r_offset. 23037ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka for (std::vector<ELFRelocationEntry>::reverse_iterator R = Relocs.rbegin(); 23137ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka R != Relocs.rend(); ++R) { 23237ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka std::pair<const MCSymbolRefExpr*, int64_t> P = 23337ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka MipsGetSymAndOffset(*R->Fixup); 23437ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka RelocLs.push_back(RelEntry(*R, P.first ? &P.first->getSymbol() : 0, 23537ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka P.second)); 23637ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka } 23737ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka 23837ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka // Get list of unmatched HI16 and GOT16. 23937ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka for (RelLsIter R = RelocLs.begin(); R != RelocLs.end(); ++R) 24037ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka if (NeedsMatchingLo(Asm, *R) && !HasMatchingLo(Asm, R, --RelocLs.end())) 24137ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka Unmatched.push_back(R); 24237ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka 24337ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka // Insert unmatched HI16 and GOT16 immediately before their matching LO16. 24437ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka for (std::vector<RelLsIter>::iterator U = Unmatched.begin(); 24537ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka U != Unmatched.end(); ++U) { 24637ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka RelLsIter LoPos = RelocLs.end(), HiPos = *U; 24737ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka bool MatchedLo = false; 24837ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka 24937ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka for (RelLsIter R = RelocLs.begin(); R != RelocLs.end(); ++R) { 25037ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka if ((R->Reloc.Type == ELF::R_MIPS_LO16) && HasSameSymbol(*HiPos, *R) && 25137ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka (CompareOffset(*R, *HiPos) >= 0) && 25237ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka ((LoPos == RelocLs.end()) || ((CompareOffset(*R, *LoPos) < 0)) || 25337ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka (!MatchedLo && !CompareOffset(*R, *LoPos)))) 25437ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka LoPos = R; 25537ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka 25637ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka MatchedLo = NeedsMatchingLo(Asm, *R) && 25737ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka HasMatchingLo(Asm, R, --RelocLs.end()); 25837ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka } 25937ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka 26037ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka // If a matching LoPos was found, move HiPos and insert it before LoPos. 26137ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka // Make the offsets of HiPos and LoPos match. 26237ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka if (LoPos != RelocLs.end()) { 26337ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka HiPos->Offset = LoPos->Offset; 26437ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka RelocLs.insert(LoPos, *HiPos); 26537ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka RelocLs.erase(HiPos); 26637ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka } 26737ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka } 26837ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka 26937ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka // Put the sorted list back in reverse order. 27037ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka assert(Relocs.size() == RelocLs.size()); 27137ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka unsigned I = RelocLs.size(); 27237ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka 27337ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka for (RelLsIter R = RelocLs.begin(); R != RelocLs.end(); ++R) 27437ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka Relocs[--I] = R->Reloc; 27537ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka} 27637ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka 277a551a48402385cf3f4b754dc72264b2f0974b1a6Akira HatanakaMCObjectWriter *llvm::createMipsELFObjectWriter(raw_ostream &OS, 278a551a48402385cf3f4b754dc72264b2f0974b1a6Akira Hatanaka uint8_t OSABI, 279a551a48402385cf3f4b754dc72264b2f0974b1a6Akira Hatanaka bool IsLittleEndian, 280a551a48402385cf3f4b754dc72264b2f0974b1a6Akira Hatanaka bool Is64Bit) { 28193ee286e8d949147f8df7f093c9bd8529a99102dJack Carter MCELFObjectTargetWriter *MOTW = new MipsELFObjectWriter(Is64Bit, OSABI, 282b889e0cd2fea4afee623d5be603b912b955a2ecaAkira Hatanaka (Is64Bit) ? true : false, 283b889e0cd2fea4afee623d5be603b912b955a2ecaAkira Hatanaka IsLittleEndian); 284090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola return createELFObjectWriter(MOTW, OS, IsLittleEndian); 285090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola} 286