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" 132c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar#include "llvm/ADT/STLExtras.h" 1437ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka#include "llvm/MC/MCAssembler.h" 15ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines#include "llvm/MC/MCELF.h" 16090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola#include "llvm/MC/MCELFObjectWriter.h" 17090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola#include "llvm/MC/MCExpr.h" 18090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola#include "llvm/MC/MCSection.h" 19090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola#include "llvm/MC/MCValue.h" 20090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola#include "llvm/Support/ErrorHandling.h" 2137ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka#include <list> 22090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola 23090445967f0b5988446faffefd1d0722f982bc7aRafael Espindolausing namespace llvm; 24090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola 25090445967f0b5988446faffefd1d0722f982bc7aRafael Espindolanamespace { 262c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// A helper structure based on ELFRelocationEntry, used for sorting entries in 272c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// the relocation table. 282c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainarstruct MipsRelocationEntry { 292c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar MipsRelocationEntry(const ELFRelocationEntry &R) 302c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar : R(R), SortOffset(R.Offset), HasMatchingHi(false) {} 312c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar const ELFRelocationEntry R; 322c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar // SortOffset equals R.Offset except for the *HI16 relocations, for which it 332c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar // will be set based on the R.Offset of the matching *LO16 relocation. 342c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar int64_t SortOffset; 352c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar // True when this is a *LO16 relocation chosen as a match for a *HI16 362c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar // relocation. 372c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar bool HasMatchingHi; 382c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar}; 392c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar 40090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola class MipsELFObjectWriter : public MCELFObjectTargetWriter { 41090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola public: 42b889e0cd2fea4afee623d5be603b912b955a2ecaAkira Hatanaka MipsELFObjectWriter(bool _is64Bit, uint8_t OSABI, 43b889e0cd2fea4afee623d5be603b912b955a2ecaAkira Hatanaka bool _isN64, bool IsLittleEndian); 44090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola 452c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar ~MipsELFObjectWriter() override; 46090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola 4736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, 4836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines bool IsPCRel) const override; 4937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines bool needsRelocateWithSymbol(const MCSymbolData &SD, 5037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines unsigned Type) const override; 512c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar virtual void sortRelocs(const MCAssembler &Asm, 522c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar std::vector<ELFRelocationEntry> &Relocs) override; 53090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola }; 54090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola} 55090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola 5693ee286e8d949147f8df7f093c9bd8529a99102dJack CarterMipsELFObjectWriter::MipsELFObjectWriter(bool _is64Bit, uint8_t OSABI, 57b889e0cd2fea4afee623d5be603b912b955a2ecaAkira Hatanaka bool _isN64, bool IsLittleEndian) 584c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar : MCELFObjectTargetWriter(_is64Bit, OSABI, ELF::EM_MIPS, 594c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar /*HasRelocationAddend*/ _isN64, 604c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar /*IsN64*/ _isN64) {} 61090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola 62090445967f0b5988446faffefd1d0722f982bc7aRafael EspindolaMipsELFObjectWriter::~MipsELFObjectWriter() {} 63090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola 64090445967f0b5988446faffefd1d0722f982bc7aRafael Espindolaunsigned MipsELFObjectWriter::GetRelocType(const MCValue &Target, 65090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola const MCFixup &Fixup, 6636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines bool IsPCRel) const { 67090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola // determine the type of the relocation 68090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola unsigned Type = (unsigned)ELF::R_MIPS_NONE; 69090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola unsigned Kind = (unsigned)Fixup.getKind(); 70090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola 71090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola switch (Kind) { 72090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola default: 73090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola llvm_unreachable("invalid fixup kind!"); 744c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar case Mips::fixup_Mips_32: 75090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola case FK_Data_4: 76090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola Type = ELF::R_MIPS_32; 77090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola break; 784c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar case Mips::fixup_Mips_64: 79e2245bab3ca29dc2142d8f254005f4ae7c40cde2Jack Carter case FK_Data_8: 80e2245bab3ca29dc2142d8f254005f4ae7c40cde2Jack Carter Type = ELF::R_MIPS_64; 81e2245bab3ca29dc2142d8f254005f4ae7c40cde2Jack Carter break; 82090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola case FK_GPRel_4: 83096d617796228293810cb0443c6617b33c5afdc5Jack Carter if (isN64()) { 84096d617796228293810cb0443c6617b33c5afdc5Jack Carter Type = setRType((unsigned)ELF::R_MIPS_GPREL32, Type); 85096d617796228293810cb0443c6617b33c5afdc5Jack Carter Type = setRType2((unsigned)ELF::R_MIPS_64, Type); 86096d617796228293810cb0443c6617b33c5afdc5Jack Carter Type = setRType3((unsigned)ELF::R_MIPS_NONE, Type); 87096d617796228293810cb0443c6617b33c5afdc5Jack Carter } 88096d617796228293810cb0443c6617b33c5afdc5Jack Carter else 89096d617796228293810cb0443c6617b33c5afdc5Jack Carter Type = ELF::R_MIPS_GPREL32; 90090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola break; 91090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola case Mips::fixup_Mips_GPREL16: 92090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola Type = ELF::R_MIPS_GPREL16; 93090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola break; 94090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola case Mips::fixup_Mips_26: 95090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola Type = ELF::R_MIPS_26; 96090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola break; 97090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola case Mips::fixup_Mips_CALL16: 98090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola Type = ELF::R_MIPS_CALL16; 99090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola break; 100090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola case Mips::fixup_Mips_GOT_Global: 101090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola case Mips::fixup_Mips_GOT_Local: 102090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola Type = ELF::R_MIPS_GOT16; 103090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola break; 104090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola case Mips::fixup_Mips_HI16: 105090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola Type = ELF::R_MIPS_HI16; 106090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola break; 107090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola case Mips::fixup_Mips_LO16: 108090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola Type = ELF::R_MIPS_LO16; 109090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola break; 110090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola case Mips::fixup_Mips_TLSGD: 111090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola Type = ELF::R_MIPS_TLS_GD; 112090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola break; 113090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola case Mips::fixup_Mips_GOTTPREL: 114090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola Type = ELF::R_MIPS_TLS_GOTTPREL; 115090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola break; 116090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola case Mips::fixup_Mips_TPREL_HI: 117090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola Type = ELF::R_MIPS_TLS_TPREL_HI16; 118090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola break; 119090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola case Mips::fixup_Mips_TPREL_LO: 120090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola Type = ELF::R_MIPS_TLS_TPREL_LO16; 121090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola break; 122090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola case Mips::fixup_Mips_TLSLDM: 123090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola Type = ELF::R_MIPS_TLS_LDM; 124090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola break; 125090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola case Mips::fixup_Mips_DTPREL_HI: 126090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola Type = ELF::R_MIPS_TLS_DTPREL_HI16; 127090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola break; 128090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola case Mips::fixup_Mips_DTPREL_LO: 129090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola Type = ELF::R_MIPS_TLS_DTPREL_LO16; 130090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola break; 131090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola case Mips::fixup_Mips_Branch_PCRel: 132090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola case Mips::fixup_Mips_PC16: 133090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola Type = ELF::R_MIPS_PC16; 134090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola break; 1350140e55393c4403ab240c386501cdc5e438dcc0eJack Carter case Mips::fixup_Mips_GOT_PAGE: 1360140e55393c4403ab240c386501cdc5e438dcc0eJack Carter Type = ELF::R_MIPS_GOT_PAGE; 1370140e55393c4403ab240c386501cdc5e438dcc0eJack Carter break; 1380140e55393c4403ab240c386501cdc5e438dcc0eJack Carter case Mips::fixup_Mips_GOT_OFST: 1390140e55393c4403ab240c386501cdc5e438dcc0eJack Carter Type = ELF::R_MIPS_GOT_OFST; 1400140e55393c4403ab240c386501cdc5e438dcc0eJack Carter break; 141fd506efec628819f7e6fad8016a9dbb5d8612b8bJack Carter case Mips::fixup_Mips_GOT_DISP: 142fd506efec628819f7e6fad8016a9dbb5d8612b8bJack Carter Type = ELF::R_MIPS_GOT_DISP; 143fd506efec628819f7e6fad8016a9dbb5d8612b8bJack Carter break; 1440140e55393c4403ab240c386501cdc5e438dcc0eJack Carter case Mips::fixup_Mips_GPOFF_HI: 1450140e55393c4403ab240c386501cdc5e438dcc0eJack Carter Type = setRType((unsigned)ELF::R_MIPS_GPREL16, Type); 1460140e55393c4403ab240c386501cdc5e438dcc0eJack Carter Type = setRType2((unsigned)ELF::R_MIPS_SUB, Type); 1470140e55393c4403ab240c386501cdc5e438dcc0eJack Carter Type = setRType3((unsigned)ELF::R_MIPS_HI16, Type); 1480140e55393c4403ab240c386501cdc5e438dcc0eJack Carter break; 1490140e55393c4403ab240c386501cdc5e438dcc0eJack Carter case Mips::fixup_Mips_GPOFF_LO: 1500140e55393c4403ab240c386501cdc5e438dcc0eJack Carter Type = setRType((unsigned)ELF::R_MIPS_GPREL16, Type); 1510140e55393c4403ab240c386501cdc5e438dcc0eJack Carter Type = setRType2((unsigned)ELF::R_MIPS_SUB, Type); 1520140e55393c4403ab240c386501cdc5e438dcc0eJack Carter Type = setRType3((unsigned)ELF::R_MIPS_LO16, Type); 1530140e55393c4403ab240c386501cdc5e438dcc0eJack Carter break; 154fc54d9e47a1276650f14f38e7d037c9b58c8dc2dJack Carter case Mips::fixup_Mips_HIGHER: 155fc54d9e47a1276650f14f38e7d037c9b58c8dc2dJack Carter Type = ELF::R_MIPS_HIGHER; 156fc54d9e47a1276650f14f38e7d037c9b58c8dc2dJack Carter break; 157fc54d9e47a1276650f14f38e7d037c9b58c8dc2dJack Carter case Mips::fixup_Mips_HIGHEST: 158fc54d9e47a1276650f14f38e7d037c9b58c8dc2dJack Carter Type = ELF::R_MIPS_HIGHEST; 159fc54d9e47a1276650f14f38e7d037c9b58c8dc2dJack Carter break; 160198ad916d736047f8a439f19dee25cee917df8a9Jack Carter case Mips::fixup_Mips_GOT_HI16: 161198ad916d736047f8a439f19dee25cee917df8a9Jack Carter Type = ELF::R_MIPS_GOT_HI16; 162198ad916d736047f8a439f19dee25cee917df8a9Jack Carter break; 163198ad916d736047f8a439f19dee25cee917df8a9Jack Carter case Mips::fixup_Mips_GOT_LO16: 164198ad916d736047f8a439f19dee25cee917df8a9Jack Carter Type = ELF::R_MIPS_GOT_LO16; 165198ad916d736047f8a439f19dee25cee917df8a9Jack Carter break; 166198ad916d736047f8a439f19dee25cee917df8a9Jack Carter case Mips::fixup_Mips_CALL_HI16: 167198ad916d736047f8a439f19dee25cee917df8a9Jack Carter Type = ELF::R_MIPS_CALL_HI16; 168198ad916d736047f8a439f19dee25cee917df8a9Jack Carter break; 169198ad916d736047f8a439f19dee25cee917df8a9Jack Carter case Mips::fixup_Mips_CALL_LO16: 170198ad916d736047f8a439f19dee25cee917df8a9Jack Carter Type = ELF::R_MIPS_CALL_LO16; 171198ad916d736047f8a439f19dee25cee917df8a9Jack Carter break; 1721aaf43c2a2ec0fd4c8dbfe56558237219c5f8af7Zoran Jovanovic case Mips::fixup_MICROMIPS_26_S1: 1731aaf43c2a2ec0fd4c8dbfe56558237219c5f8af7Zoran Jovanovic Type = ELF::R_MICROMIPS_26_S1; 1741aaf43c2a2ec0fd4c8dbfe56558237219c5f8af7Zoran Jovanovic break; 1750082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic case Mips::fixup_MICROMIPS_HI16: 1760082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic Type = ELF::R_MICROMIPS_HI16; 1770082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic break; 1780082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic case Mips::fixup_MICROMIPS_LO16: 1790082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic Type = ELF::R_MICROMIPS_LO16; 1800082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic break; 1810082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic case Mips::fixup_MICROMIPS_GOT16: 1820082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic Type = ELF::R_MICROMIPS_GOT16; 1830082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic break; 184ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines case Mips::fixup_MICROMIPS_PC7_S1: 185ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines Type = ELF::R_MICROMIPS_PC7_S1; 186ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines break; 187ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines case Mips::fixup_MICROMIPS_PC10_S1: 188ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines Type = ELF::R_MICROMIPS_PC10_S1; 189ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines break; 1905c042162beb3c2dd556e00aab84c4278a69cd5b1Zoran Jovanovic case Mips::fixup_MICROMIPS_PC16_S1: 1915c042162beb3c2dd556e00aab84c4278a69cd5b1Zoran Jovanovic Type = ELF::R_MICROMIPS_PC16_S1; 1925c042162beb3c2dd556e00aab84c4278a69cd5b1Zoran Jovanovic break; 1930082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic case Mips::fixup_MICROMIPS_CALL16: 1940082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic Type = ELF::R_MICROMIPS_CALL16; 1950082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic break; 1960082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic case Mips::fixup_MICROMIPS_GOT_DISP: 1970082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic Type = ELF::R_MICROMIPS_GOT_DISP; 1980082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic break; 1990082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic case Mips::fixup_MICROMIPS_GOT_PAGE: 2000082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic Type = ELF::R_MICROMIPS_GOT_PAGE; 2010082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic break; 2020082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic case Mips::fixup_MICROMIPS_GOT_OFST: 2030082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic Type = ELF::R_MICROMIPS_GOT_OFST; 2040082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic break; 20536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case Mips::fixup_MICROMIPS_TLS_GD: 20636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Type = ELF::R_MICROMIPS_TLS_GD; 20736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines break; 20836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case Mips::fixup_MICROMIPS_TLS_LDM: 20936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Type = ELF::R_MICROMIPS_TLS_LDM; 21036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines break; 2110082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic case Mips::fixup_MICROMIPS_TLS_DTPREL_HI16: 2120082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic Type = ELF::R_MICROMIPS_TLS_DTPREL_HI16; 2130082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic break; 2140082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic case Mips::fixup_MICROMIPS_TLS_DTPREL_LO16: 2150082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic Type = ELF::R_MICROMIPS_TLS_DTPREL_LO16; 2160082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic break; 2170082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic case Mips::fixup_MICROMIPS_TLS_TPREL_HI16: 2180082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic Type = ELF::R_MICROMIPS_TLS_TPREL_HI16; 2190082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic break; 2200082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic case Mips::fixup_MICROMIPS_TLS_TPREL_LO16: 2210082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic Type = ELF::R_MICROMIPS_TLS_TPREL_LO16; 2220082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic break; 223c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines case Mips::fixup_MIPS_PC19_S2: 224c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines Type = ELF::R_MIPS_PC19_S2; 225c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines break; 226c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines case Mips::fixup_MIPS_PC18_S3: 227c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines Type = ELF::R_MIPS_PC18_S3; 228c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines break; 229dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines case Mips::fixup_MIPS_PC21_S2: 230dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Type = ELF::R_MIPS_PC21_S2; 231dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines break; 232dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines case Mips::fixup_MIPS_PC26_S2: 233dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Type = ELF::R_MIPS_PC26_S2; 234dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines break; 235dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines case Mips::fixup_MIPS_PCHI16: 236dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Type = ELF::R_MIPS_PCHI16; 237dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines break; 238dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines case Mips::fixup_MIPS_PCLO16: 239dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Type = ELF::R_MIPS_PCLO16; 240dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines break; 241090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola } 242090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola return Type; 243090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola} 244090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola 2452c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// Sort entries by SortOffset in descending order. 2462c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// When there are more *HI16 relocs paired with one *LO16 reloc, the 2nd rule 2472c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// sorts them in ascending order of R.Offset. 2482c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainarstatic int cmpRelMips(const MipsRelocationEntry *AP, 2492c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar const MipsRelocationEntry *BP) { 2502c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar const MipsRelocationEntry &A = *AP; 2512c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar const MipsRelocationEntry &B = *BP; 2522c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar if (A.SortOffset != B.SortOffset) 2532c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar return B.SortOffset - A.SortOffset; 2542c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar if (A.R.Offset != B.R.Offset) 2552c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar return A.R.Offset - B.R.Offset; 2562c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar if (B.R.Type != A.R.Type) 2572c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar return B.R.Type - A.R.Type; 2582c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar //llvm_unreachable("ELFRelocs might be unstable!"); 2592c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar return 0; 2602c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar} 2612c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar 2622c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// For the given Reloc.Type, return the matching relocation type, as in the 2632c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// table below. 2642c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainarstatic unsigned getMatchingLoType(const MCAssembler &Asm, 2652c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar const ELFRelocationEntry &Reloc) { 2662c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar unsigned Type = Reloc.Type; 2672c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar if (Type == ELF::R_MIPS_HI16) 2682c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar return ELF::R_MIPS_LO16; 2692c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar if (Type == ELF::R_MICROMIPS_HI16) 2702c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar return ELF::R_MICROMIPS_LO16; 2712c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar if (Type == ELF::R_MIPS16_HI16) 2722c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar return ELF::R_MIPS16_LO16; 2732c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar 2742c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar const MCSymbolData &SD = Asm.getSymbolData(*Reloc.Symbol); 2752c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar 2762c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar if (MCELF::GetBinding(SD) != ELF::STB_LOCAL) 2772c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar return ELF::R_MIPS_NONE; 2782c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar 2792c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar if (Type == ELF::R_MIPS_GOT16) 2802c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar return ELF::R_MIPS_LO16; 2812c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar if (Type == ELF::R_MICROMIPS_GOT16) 2822c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar return ELF::R_MICROMIPS_LO16; 2832c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar if (Type == ELF::R_MIPS16_GOT16) 2842c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar return ELF::R_MIPS16_LO16; 2852c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar 2862c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar return ELF::R_MIPS_NONE; 2872c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar} 2882c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar 2892c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// Return true if First needs a matching *LO16, its matching *LO16 type equals 2902c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// Second's type and both relocations are against the same symbol. 2912c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainarstatic bool areMatchingHiAndLo(const MCAssembler &Asm, 2922c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar const ELFRelocationEntry &First, 2932c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar const ELFRelocationEntry &Second) { 2942c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar return getMatchingLoType(Asm, First) != ELF::R_MIPS_NONE && 2952c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar getMatchingLoType(Asm, First) == Second.Type && 2962c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar First.Symbol && First.Symbol == Second.Symbol; 2972c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar} 2982c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar 2992c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// Return true if MipsRelocs[Index] is a *LO16 preceded by a matching *HI16. 3002c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainarstatic bool 3012c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga NainarisPrecededByMatchingHi(const MCAssembler &Asm, uint32_t Index, 3022c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar std::vector<MipsRelocationEntry> &MipsRelocs) { 3032c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar return Index < MipsRelocs.size() - 1 && 3042c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar areMatchingHiAndLo(Asm, MipsRelocs[Index + 1].R, MipsRelocs[Index].R); 3052c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar} 3062c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar 3072c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// Return true if MipsRelocs[Index] is a *LO16 not preceded by a matching *HI16 3082c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// and not chosen by a *HI16 as a match. 3092c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainarstatic bool isFreeLo(const MCAssembler &Asm, uint32_t Index, 3102c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar std::vector<MipsRelocationEntry> &MipsRelocs) { 3112c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar return Index < MipsRelocs.size() && !MipsRelocs[Index].HasMatchingHi && 3122c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar !isPrecededByMatchingHi(Asm, Index, MipsRelocs); 3132c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar} 3142c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar 3152c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// Lo is chosen as a match for Hi, set their fields accordingly. 3162c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// Mips instructions have fixed length of at least two bytes (two for 3172c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// micromips/mips16, four for mips32/64), so we can set HI's SortOffset to 3182c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// matching LO's Offset minus one to simplify the sorting function. 3192c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainarstatic void setMatch(MipsRelocationEntry &Hi, MipsRelocationEntry &Lo) { 3202c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar Lo.HasMatchingHi = true; 3212c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar Hi.SortOffset = Lo.R.Offset - 1; 3222c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar} 3232c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar 3242c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// We sort relocation table entries by offset, except for one additional rule 3252c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// required by MIPS ABI: every *HI16 relocation must be immediately followed by 3262c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// the corresponding *LO16 relocation. We also support a GNU extension that 3272c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// allows more *HI16s paired with one *LO16. 3282c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// 3292c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// *HI16 relocations and their matching *LO16 are: 3302c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// 3312c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// +---------------------------------------------+-------------------+ 3322c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// | *HI16 | matching *LO16 | 3332c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// |---------------------------------------------+-------------------| 3342c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// | R_MIPS_HI16, local R_MIPS_GOT16 | R_MIPS_LO16 | 3352c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// | R_MICROMIPS_HI16, local R_MICROMIPS_GOT16 | R_MICROMIPS_LO16 | 3362c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// | R_MIPS16_HI16, local R_MIPS16_GOT16 | R_MIPS16_LO16 | 3372c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// +---------------------------------------------+-------------------+ 3382c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// 3392c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// (local R_*_GOT16 meaning R_*_GOT16 against the local symbol.) 3402c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// 3412c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// To handle *HI16 and *LO16 relocations, the linker needs a combined addend 3422c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// ("AHL") calculated from both *HI16 ("AHI") and *LO16 ("ALO") relocations: 3432c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// AHL = (AHI << 16) + (short)ALO; 3442c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// 3452c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// We are reusing gnu as sorting algorithm so we are emitting the relocation 3462c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// table sorted the same way as gnu as would sort it, for easier comparison of 3472c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// the generated .o files. 3482c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// 3492c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// The logic is: 3502c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// search the table (starting from the highest offset and going back to zero) 3512c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// for all *HI16 relocations that don't have a matching *LO16. 3522c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// For every such HI, find a matching LO with highest offset that isn't already 3532c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// matched with another HI. If there are no free LOs, match it with the first 3542c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// found (starting from lowest offset). 3552c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// When there are more HIs matched with one LO, sort them in descending order by 3562c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// offset. 3572c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// 3582c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// In other words, when searching for a matching LO: 3592c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// - don't look for a 'better' match for the HIs that are already followed by a 3602c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// matching LO; 3612c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// - prefer LOs without a pair; 3622c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// - prefer LOs with higher offset; 3632c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainarvoid MipsELFObjectWriter::sortRelocs(const MCAssembler &Asm, 3642c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar std::vector<ELFRelocationEntry> &Relocs) { 3652c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar if (Relocs.size() < 2) 3662c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar return; 3672c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar 3682c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar // The default function sorts entries by Offset in descending order. 3692c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar MCELFObjectTargetWriter::sortRelocs(Asm, Relocs); 3702c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar 3712c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar // Init MipsRelocs from Relocs. 3722c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar std::vector<MipsRelocationEntry> MipsRelocs; 3732c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar for (unsigned I = 0, E = Relocs.size(); I != E; ++I) 3742c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar MipsRelocs.push_back(MipsRelocationEntry(Relocs[I])); 3752c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar 3762c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar // Find a matching LO for all HIs that need it. 3772c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar for (int32_t I = 0, E = MipsRelocs.size(); I != E; ++I) { 3782c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar if (getMatchingLoType(Asm, MipsRelocs[I].R) == ELF::R_MIPS_NONE || 3792c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar (I > 0 && isPrecededByMatchingHi(Asm, I - 1, MipsRelocs))) 3802c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar continue; 3812c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar 3822c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar int32_t MatchedLoIndex = -1; 3832c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar 3842c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar // Search the list in the ascending order of Offset. 3852c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar for (int32_t J = MipsRelocs.size() - 1, N = -1; J != N; --J) { 3862c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar // check for a match 3872c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar if (areMatchingHiAndLo(Asm, MipsRelocs[I].R, MipsRelocs[J].R) && 3882c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar (MatchedLoIndex == -1 || // first match 3892c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar // or we already have a match, 3902c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar // but this one is with higher offset and it's free 3912c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar (MatchedLoIndex > J && isFreeLo(Asm, J, MipsRelocs)))) 3922c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar MatchedLoIndex = J; 3932c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar } 3942c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar 3952c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar if (MatchedLoIndex != -1) 3962c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar // We have a match. 3972c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar setMatch(MipsRelocs[I], MipsRelocs[MatchedLoIndex]); 3982c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar } 3992c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar 4002c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar // SortOffsets are calculated, call the sorting function. 4012c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar array_pod_sort(MipsRelocs.begin(), MipsRelocs.end(), cmpRelMips); 4022c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar 4032c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar // Copy sorted MipsRelocs back to Relocs. 4042c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar for (unsigned I = 0, E = MipsRelocs.size(); I != E; ++I) 4052c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar Relocs[I] = MipsRelocs[I].R; 4062c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar} 4072c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar 40836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesbool 40937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen HinesMipsELFObjectWriter::needsRelocateWithSymbol(const MCSymbolData &SD, 41037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines unsigned Type) const { 411ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // FIXME: This is extremely conservative. This really needs to use a 41236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // whitelist with a clear explanation for why each realocation needs to 41336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // point to the symbol, not to the section. 41436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines switch (Type) { 41536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines default: 41636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return true; 41736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 41836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case ELF::R_MIPS_GOT16: 41936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case ELF::R_MIPS16_GOT16: 42036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case ELF::R_MICROMIPS_GOT16: 42136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines llvm_unreachable("Should have been handled already"); 42236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 42336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // These relocations might be paired with another relocation. The pairing is 42436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // done by the static linker by matching the symbol. Since we only see one 42536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // relocation at a time, we have to force them to relocate with a symbol to 42636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // avoid ending up with a pair where one points to a section and another 42736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // points to a symbol. 42836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case ELF::R_MIPS_HI16: 42936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case ELF::R_MIPS16_HI16: 43036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case ELF::R_MICROMIPS_HI16: 43136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case ELF::R_MIPS_LO16: 43236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case ELF::R_MIPS16_LO16: 43336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case ELF::R_MICROMIPS_LO16: 43436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return true; 43536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 43636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case ELF::R_MIPS_32: 437ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines if (MCELF::getOther(SD) & (ELF::STO_MIPS_MICROMIPS >> 2)) 438ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines return true; 439ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // falltrough 440ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines case ELF::R_MIPS_26: 44136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case ELF::R_MIPS_64: 44236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case ELF::R_MIPS_GPREL16: 44337ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka return false; 44437ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka } 44537ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka} 44637ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka 4472c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga NainarMCObjectWriter *llvm::createMipsELFObjectWriter(raw_pwrite_stream &OS, 4482c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar uint8_t OSABI, 449a551a48402385cf3f4b754dc72264b2f0974b1a6Akira Hatanaka bool IsLittleEndian, 450a551a48402385cf3f4b754dc72264b2f0974b1a6Akira Hatanaka bool Is64Bit) { 4514c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar MCELFObjectTargetWriter *MOTW = 4524c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar new MipsELFObjectWriter(Is64Bit, OSABI, Is64Bit, IsLittleEndian); 453090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola return createELFObjectWriter(MOTW, OS, IsLittleEndian); 454090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola} 455