109467b48Spatrick //===-- MipsELFObjectWriter.cpp - Mips ELF Writer -------------------------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick
909467b48Spatrick #include "MCTargetDesc/MipsFixupKinds.h"
1009467b48Spatrick #include "MCTargetDesc/MipsMCTargetDesc.h"
1109467b48Spatrick #include "llvm/ADT/STLExtras.h"
1209467b48Spatrick #include "llvm/BinaryFormat/ELF.h"
1309467b48Spatrick #include "llvm/MC/MCContext.h"
1409467b48Spatrick #include "llvm/MC/MCELFObjectWriter.h"
1509467b48Spatrick #include "llvm/MC/MCFixup.h"
1609467b48Spatrick #include "llvm/MC/MCObjectWriter.h"
1709467b48Spatrick #include "llvm/MC/MCSymbolELF.h"
1809467b48Spatrick #include "llvm/Support/Casting.h"
1909467b48Spatrick #include "llvm/Support/Compiler.h"
2009467b48Spatrick #include "llvm/Support/Debug.h"
2109467b48Spatrick #include "llvm/Support/ErrorHandling.h"
2209467b48Spatrick #include "llvm/Support/MathExtras.h"
2309467b48Spatrick #include "llvm/Support/raw_ostream.h"
2409467b48Spatrick #include <algorithm>
2509467b48Spatrick #include <cassert>
2609467b48Spatrick #include <cstdint>
2709467b48Spatrick #include <iterator>
2809467b48Spatrick #include <list>
2909467b48Spatrick #include <utility>
3009467b48Spatrick
3109467b48Spatrick #define DEBUG_TYPE "mips-elf-object-writer"
3209467b48Spatrick
3309467b48Spatrick using namespace llvm;
3409467b48Spatrick
3509467b48Spatrick namespace {
3609467b48Spatrick
3709467b48Spatrick /// Holds additional information needed by the relocation ordering algorithm.
3809467b48Spatrick struct MipsRelocationEntry {
3909467b48Spatrick const ELFRelocationEntry R; ///< The relocation.
4009467b48Spatrick bool Matched = false; ///< Is this relocation part of a match.
4109467b48Spatrick
MipsRelocationEntry__anoncfa1e46e0111::MipsRelocationEntry4209467b48Spatrick MipsRelocationEntry(const ELFRelocationEntry &R) : R(R) {}
4309467b48Spatrick
print__anoncfa1e46e0111::MipsRelocationEntry4409467b48Spatrick void print(raw_ostream &Out) const {
4509467b48Spatrick R.print(Out);
4609467b48Spatrick Out << ", Matched=" << Matched;
4709467b48Spatrick }
4809467b48Spatrick };
4909467b48Spatrick
5009467b48Spatrick #ifndef NDEBUG
operator <<(raw_ostream & OS,const MipsRelocationEntry & RHS)5109467b48Spatrick raw_ostream &operator<<(raw_ostream &OS, const MipsRelocationEntry &RHS) {
5209467b48Spatrick RHS.print(OS);
5309467b48Spatrick return OS;
5409467b48Spatrick }
5509467b48Spatrick #endif
5609467b48Spatrick
5709467b48Spatrick class MipsELFObjectWriter : public MCELFObjectTargetWriter {
5809467b48Spatrick public:
5909467b48Spatrick MipsELFObjectWriter(uint8_t OSABI, bool HasRelocationAddend, bool Is64);
6009467b48Spatrick
6109467b48Spatrick ~MipsELFObjectWriter() override = default;
6209467b48Spatrick
6309467b48Spatrick unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
6409467b48Spatrick const MCFixup &Fixup, bool IsPCRel) const override;
6509467b48Spatrick bool needsRelocateWithSymbol(const MCSymbol &Sym,
6609467b48Spatrick unsigned Type) const override;
6709467b48Spatrick void sortRelocs(const MCAssembler &Asm,
6809467b48Spatrick std::vector<ELFRelocationEntry> &Relocs) override;
6909467b48Spatrick };
7009467b48Spatrick
7109467b48Spatrick /// The possible results of the Predicate function used by find_best.
7209467b48Spatrick enum FindBestPredicateResult {
7309467b48Spatrick FindBest_NoMatch = 0, ///< The current element is not a match.
7409467b48Spatrick FindBest_Match, ///< The current element is a match but better ones are
7509467b48Spatrick /// possible.
7609467b48Spatrick FindBest_PerfectMatch, ///< The current element is an unbeatable match.
7709467b48Spatrick };
7809467b48Spatrick
7909467b48Spatrick } // end anonymous namespace
8009467b48Spatrick
8109467b48Spatrick /// Copy elements in the range [First, Last) to d1 when the predicate is true or
8209467b48Spatrick /// d2 when the predicate is false. This is essentially both std::copy_if and
8309467b48Spatrick /// std::remove_copy_if combined into a single pass.
8409467b48Spatrick template <class InputIt, class OutputIt1, class OutputIt2, class UnaryPredicate>
copy_if_else(InputIt First,InputIt Last,OutputIt1 d1,OutputIt2 d2,UnaryPredicate Predicate)8509467b48Spatrick static std::pair<OutputIt1, OutputIt2> copy_if_else(InputIt First, InputIt Last,
8609467b48Spatrick OutputIt1 d1, OutputIt2 d2,
8709467b48Spatrick UnaryPredicate Predicate) {
8809467b48Spatrick for (InputIt I = First; I != Last; ++I) {
8909467b48Spatrick if (Predicate(*I)) {
9009467b48Spatrick *d1 = *I;
9109467b48Spatrick d1++;
9209467b48Spatrick } else {
9309467b48Spatrick *d2 = *I;
9409467b48Spatrick d2++;
9509467b48Spatrick }
9609467b48Spatrick }
9709467b48Spatrick
9809467b48Spatrick return std::make_pair(d1, d2);
9909467b48Spatrick }
10009467b48Spatrick
10109467b48Spatrick /// Find the best match in the range [First, Last).
10209467b48Spatrick ///
10309467b48Spatrick /// An element matches when Predicate(X) returns FindBest_Match or
10409467b48Spatrick /// FindBest_PerfectMatch. A value of FindBest_PerfectMatch also terminates
10509467b48Spatrick /// the search. BetterThan(A, B) is a comparator that returns true when A is a
10609467b48Spatrick /// better match than B. The return value is the position of the best match.
10709467b48Spatrick ///
10809467b48Spatrick /// This is similar to std::find_if but finds the best of multiple possible
10909467b48Spatrick /// matches.
11009467b48Spatrick template <class InputIt, class UnaryPredicate, class Comparator>
find_best(InputIt First,InputIt Last,UnaryPredicate Predicate,Comparator BetterThan)11109467b48Spatrick static InputIt find_best(InputIt First, InputIt Last, UnaryPredicate Predicate,
11209467b48Spatrick Comparator BetterThan) {
11309467b48Spatrick InputIt Best = Last;
11409467b48Spatrick
11509467b48Spatrick for (InputIt I = First; I != Last; ++I) {
11609467b48Spatrick unsigned Matched = Predicate(*I);
11709467b48Spatrick if (Matched != FindBest_NoMatch) {
11809467b48Spatrick LLVM_DEBUG(dbgs() << std::distance(First, I) << " is a match (";
11909467b48Spatrick I->print(dbgs()); dbgs() << ")\n");
12009467b48Spatrick if (Best == Last || BetterThan(*I, *Best)) {
12109467b48Spatrick LLVM_DEBUG(dbgs() << ".. and it beats the last one\n");
12209467b48Spatrick Best = I;
12309467b48Spatrick }
12409467b48Spatrick }
12509467b48Spatrick if (Matched == FindBest_PerfectMatch) {
12609467b48Spatrick LLVM_DEBUG(dbgs() << ".. and it is unbeatable\n");
12709467b48Spatrick break;
12809467b48Spatrick }
12909467b48Spatrick }
13009467b48Spatrick
13109467b48Spatrick return Best;
13209467b48Spatrick }
13309467b48Spatrick
13409467b48Spatrick /// Determine the low relocation that matches the given relocation.
13509467b48Spatrick /// If the relocation does not need a low relocation then the return value
13609467b48Spatrick /// is ELF::R_MIPS_NONE.
13709467b48Spatrick ///
13809467b48Spatrick /// The relocations that need a matching low part are
13909467b48Spatrick /// R_(MIPS|MICROMIPS|MIPS16)_HI16 for all symbols and
14009467b48Spatrick /// R_(MIPS|MICROMIPS|MIPS16)_GOT16 for local symbols only.
getMatchingLoType(const ELFRelocationEntry & Reloc)14109467b48Spatrick static unsigned getMatchingLoType(const ELFRelocationEntry &Reloc) {
14209467b48Spatrick unsigned Type = Reloc.Type;
14309467b48Spatrick if (Type == ELF::R_MIPS_HI16)
14409467b48Spatrick return ELF::R_MIPS_LO16;
14509467b48Spatrick if (Type == ELF::R_MICROMIPS_HI16)
14609467b48Spatrick return ELF::R_MICROMIPS_LO16;
14709467b48Spatrick if (Type == ELF::R_MIPS16_HI16)
14809467b48Spatrick return ELF::R_MIPS16_LO16;
14909467b48Spatrick
15009467b48Spatrick if (Reloc.OriginalSymbol &&
15109467b48Spatrick Reloc.OriginalSymbol->getBinding() != ELF::STB_LOCAL)
15209467b48Spatrick return ELF::R_MIPS_NONE;
15309467b48Spatrick
15409467b48Spatrick if (Type == ELF::R_MIPS_GOT16)
15509467b48Spatrick return ELF::R_MIPS_LO16;
15609467b48Spatrick if (Type == ELF::R_MICROMIPS_GOT16)
15709467b48Spatrick return ELF::R_MICROMIPS_LO16;
15809467b48Spatrick if (Type == ELF::R_MIPS16_GOT16)
15909467b48Spatrick return ELF::R_MIPS16_LO16;
16009467b48Spatrick
16109467b48Spatrick return ELF::R_MIPS_NONE;
16209467b48Spatrick }
16309467b48Spatrick
16409467b48Spatrick /// Determine whether a relocation (X) matches the one given in R.
16509467b48Spatrick ///
16609467b48Spatrick /// A relocation matches if:
16709467b48Spatrick /// - It's type matches that of a corresponding low part. This is provided in
16809467b48Spatrick /// MatchingType for efficiency.
16909467b48Spatrick /// - It's based on the same symbol.
17009467b48Spatrick /// - It's offset of greater or equal to that of the one given in R.
17109467b48Spatrick /// It should be noted that this rule assumes the programmer does not use
17209467b48Spatrick /// offsets that exceed the alignment of the symbol. The carry-bit will be
17309467b48Spatrick /// incorrect if this is not true.
17409467b48Spatrick ///
17509467b48Spatrick /// A matching relocation is unbeatable if:
17609467b48Spatrick /// - It is not already involved in a match.
17709467b48Spatrick /// - It's offset is exactly that of the one given in R.
isMatchingReloc(const MipsRelocationEntry & X,const ELFRelocationEntry & R,unsigned MatchingType)17809467b48Spatrick static FindBestPredicateResult isMatchingReloc(const MipsRelocationEntry &X,
17909467b48Spatrick const ELFRelocationEntry &R,
18009467b48Spatrick unsigned MatchingType) {
18109467b48Spatrick if (X.R.Type == MatchingType && X.R.OriginalSymbol == R.OriginalSymbol) {
18209467b48Spatrick if (!X.Matched &&
18309467b48Spatrick X.R.OriginalAddend == R.OriginalAddend)
18409467b48Spatrick return FindBest_PerfectMatch;
18509467b48Spatrick else if (X.R.OriginalAddend >= R.OriginalAddend)
18609467b48Spatrick return FindBest_Match;
18709467b48Spatrick }
18809467b48Spatrick return FindBest_NoMatch;
18909467b48Spatrick }
19009467b48Spatrick
19109467b48Spatrick /// Determine whether Candidate or PreviousBest is the better match.
19209467b48Spatrick /// The return value is true if Candidate is the better match.
19309467b48Spatrick ///
19409467b48Spatrick /// A matching relocation is a better match if:
19509467b48Spatrick /// - It has a smaller addend.
19609467b48Spatrick /// - It is not already involved in a match.
compareMatchingRelocs(const MipsRelocationEntry & Candidate,const MipsRelocationEntry & PreviousBest)19709467b48Spatrick static bool compareMatchingRelocs(const MipsRelocationEntry &Candidate,
19809467b48Spatrick const MipsRelocationEntry &PreviousBest) {
19909467b48Spatrick if (Candidate.R.OriginalAddend != PreviousBest.R.OriginalAddend)
20009467b48Spatrick return Candidate.R.OriginalAddend < PreviousBest.R.OriginalAddend;
20109467b48Spatrick return PreviousBest.Matched && !Candidate.Matched;
20209467b48Spatrick }
20309467b48Spatrick
20409467b48Spatrick #ifndef NDEBUG
20509467b48Spatrick /// Print all the relocations.
20609467b48Spatrick template <class Container>
dumpRelocs(const char * Prefix,const Container & Relocs)20709467b48Spatrick static void dumpRelocs(const char *Prefix, const Container &Relocs) {
20809467b48Spatrick for (const auto &R : Relocs)
20909467b48Spatrick dbgs() << Prefix << R << "\n";
21009467b48Spatrick }
21109467b48Spatrick #endif
21209467b48Spatrick
MipsELFObjectWriter(uint8_t OSABI,bool HasRelocationAddend,bool Is64)21309467b48Spatrick MipsELFObjectWriter::MipsELFObjectWriter(uint8_t OSABI,
21409467b48Spatrick bool HasRelocationAddend, bool Is64)
21509467b48Spatrick : MCELFObjectTargetWriter(Is64, OSABI, ELF::EM_MIPS, HasRelocationAddend) {}
21609467b48Spatrick
getRelocType(MCContext & Ctx,const MCValue & Target,const MCFixup & Fixup,bool IsPCRel) const21709467b48Spatrick unsigned MipsELFObjectWriter::getRelocType(MCContext &Ctx,
21809467b48Spatrick const MCValue &Target,
21909467b48Spatrick const MCFixup &Fixup,
22009467b48Spatrick bool IsPCRel) const {
22109467b48Spatrick // Determine the type of the relocation.
22209467b48Spatrick unsigned Kind = Fixup.getTargetKind();
223*d415bd75Srobert if (Kind >= FirstLiteralRelocationKind)
224*d415bd75Srobert return Kind - FirstLiteralRelocationKind;
22509467b48Spatrick
22609467b48Spatrick switch (Kind) {
22709467b48Spatrick case FK_NONE:
22809467b48Spatrick return ELF::R_MIPS_NONE;
22909467b48Spatrick case FK_Data_1:
23009467b48Spatrick Ctx.reportError(Fixup.getLoc(),
23109467b48Spatrick "MIPS does not support one byte relocations");
23209467b48Spatrick return ELF::R_MIPS_NONE;
23309467b48Spatrick case Mips::fixup_Mips_16:
23409467b48Spatrick case FK_Data_2:
23509467b48Spatrick return IsPCRel ? ELF::R_MIPS_PC16 : ELF::R_MIPS_16;
23609467b48Spatrick case Mips::fixup_Mips_32:
23709467b48Spatrick case FK_Data_4:
23809467b48Spatrick return IsPCRel ? ELF::R_MIPS_PC32 : ELF::R_MIPS_32;
239097a140dSpatrick case Mips::fixup_Mips_64:
240097a140dSpatrick case FK_Data_8:
241097a140dSpatrick return IsPCRel
242097a140dSpatrick ? setRTypes(ELF::R_MIPS_PC32, ELF::R_MIPS_64, ELF::R_MIPS_NONE)
243097a140dSpatrick : (unsigned)ELF::R_MIPS_64;
24409467b48Spatrick }
24509467b48Spatrick
24609467b48Spatrick if (IsPCRel) {
24709467b48Spatrick switch (Kind) {
24809467b48Spatrick case Mips::fixup_Mips_Branch_PCRel:
24909467b48Spatrick case Mips::fixup_Mips_PC16:
25009467b48Spatrick return ELF::R_MIPS_PC16;
25109467b48Spatrick case Mips::fixup_MICROMIPS_PC7_S1:
25209467b48Spatrick return ELF::R_MICROMIPS_PC7_S1;
25309467b48Spatrick case Mips::fixup_MICROMIPS_PC10_S1:
25409467b48Spatrick return ELF::R_MICROMIPS_PC10_S1;
25509467b48Spatrick case Mips::fixup_MICROMIPS_PC16_S1:
25609467b48Spatrick return ELF::R_MICROMIPS_PC16_S1;
25709467b48Spatrick case Mips::fixup_MICROMIPS_PC26_S1:
25809467b48Spatrick return ELF::R_MICROMIPS_PC26_S1;
25909467b48Spatrick case Mips::fixup_MICROMIPS_PC19_S2:
26009467b48Spatrick return ELF::R_MICROMIPS_PC19_S2;
26109467b48Spatrick case Mips::fixup_MICROMIPS_PC18_S3:
26209467b48Spatrick return ELF::R_MICROMIPS_PC18_S3;
26309467b48Spatrick case Mips::fixup_MICROMIPS_PC21_S1:
26409467b48Spatrick return ELF::R_MICROMIPS_PC21_S1;
26509467b48Spatrick case Mips::fixup_MIPS_PC19_S2:
26609467b48Spatrick return ELF::R_MIPS_PC19_S2;
26709467b48Spatrick case Mips::fixup_MIPS_PC18_S3:
26809467b48Spatrick return ELF::R_MIPS_PC18_S3;
26909467b48Spatrick case Mips::fixup_MIPS_PC21_S2:
27009467b48Spatrick return ELF::R_MIPS_PC21_S2;
27109467b48Spatrick case Mips::fixup_MIPS_PC26_S2:
27209467b48Spatrick return ELF::R_MIPS_PC26_S2;
27309467b48Spatrick case Mips::fixup_MIPS_PCHI16:
27409467b48Spatrick return ELF::R_MIPS_PCHI16;
27509467b48Spatrick case Mips::fixup_MIPS_PCLO16:
27609467b48Spatrick return ELF::R_MIPS_PCLO16;
27709467b48Spatrick }
27809467b48Spatrick
27909467b48Spatrick llvm_unreachable("invalid PC-relative fixup kind!");
28009467b48Spatrick }
28109467b48Spatrick
28209467b48Spatrick switch (Kind) {
28309467b48Spatrick case FK_DTPRel_4:
28409467b48Spatrick return ELF::R_MIPS_TLS_DTPREL32;
28509467b48Spatrick case FK_DTPRel_8:
28609467b48Spatrick return ELF::R_MIPS_TLS_DTPREL64;
28709467b48Spatrick case FK_TPRel_4:
28809467b48Spatrick return ELF::R_MIPS_TLS_TPREL32;
28909467b48Spatrick case FK_TPRel_8:
29009467b48Spatrick return ELF::R_MIPS_TLS_TPREL64;
29109467b48Spatrick case FK_GPRel_4:
292097a140dSpatrick return setRTypes(ELF::R_MIPS_GPREL32,
293097a140dSpatrick is64Bit() ? ELF::R_MIPS_64 : ELF::R_MIPS_NONE,
294097a140dSpatrick ELF::R_MIPS_NONE);
29509467b48Spatrick case Mips::fixup_Mips_GPREL16:
29609467b48Spatrick return ELF::R_MIPS_GPREL16;
29709467b48Spatrick case Mips::fixup_Mips_26:
29809467b48Spatrick return ELF::R_MIPS_26;
29909467b48Spatrick case Mips::fixup_Mips_CALL16:
30009467b48Spatrick return ELF::R_MIPS_CALL16;
30109467b48Spatrick case Mips::fixup_Mips_GOT:
30209467b48Spatrick return ELF::R_MIPS_GOT16;
30309467b48Spatrick case Mips::fixup_Mips_HI16:
30409467b48Spatrick return ELF::R_MIPS_HI16;
30509467b48Spatrick case Mips::fixup_Mips_LO16:
30609467b48Spatrick return ELF::R_MIPS_LO16;
30709467b48Spatrick case Mips::fixup_Mips_TLSGD:
30809467b48Spatrick return ELF::R_MIPS_TLS_GD;
30909467b48Spatrick case Mips::fixup_Mips_GOTTPREL:
31009467b48Spatrick return ELF::R_MIPS_TLS_GOTTPREL;
31109467b48Spatrick case Mips::fixup_Mips_TPREL_HI:
31209467b48Spatrick return ELF::R_MIPS_TLS_TPREL_HI16;
31309467b48Spatrick case Mips::fixup_Mips_TPREL_LO:
31409467b48Spatrick return ELF::R_MIPS_TLS_TPREL_LO16;
31509467b48Spatrick case Mips::fixup_Mips_TLSLDM:
31609467b48Spatrick return ELF::R_MIPS_TLS_LDM;
31709467b48Spatrick case Mips::fixup_Mips_DTPREL_HI:
31809467b48Spatrick return ELF::R_MIPS_TLS_DTPREL_HI16;
31909467b48Spatrick case Mips::fixup_Mips_DTPREL_LO:
32009467b48Spatrick return ELF::R_MIPS_TLS_DTPREL_LO16;
32109467b48Spatrick case Mips::fixup_Mips_GOT_PAGE:
32209467b48Spatrick return ELF::R_MIPS_GOT_PAGE;
32309467b48Spatrick case Mips::fixup_Mips_GOT_OFST:
32409467b48Spatrick return ELF::R_MIPS_GOT_OFST;
32509467b48Spatrick case Mips::fixup_Mips_GOT_DISP:
32609467b48Spatrick return ELF::R_MIPS_GOT_DISP;
327097a140dSpatrick case Mips::fixup_Mips_GPOFF_HI:
328097a140dSpatrick return setRTypes(ELF::R_MIPS_GPREL16, ELF::R_MIPS_SUB, ELF::R_MIPS_HI16);
329097a140dSpatrick case Mips::fixup_MICROMIPS_GPOFF_HI:
330097a140dSpatrick return setRTypes(ELF::R_MICROMIPS_GPREL16, ELF::R_MICROMIPS_SUB,
331097a140dSpatrick ELF::R_MICROMIPS_HI16);
332097a140dSpatrick case Mips::fixup_Mips_GPOFF_LO:
333097a140dSpatrick return setRTypes(ELF::R_MIPS_GPREL16, ELF::R_MIPS_SUB, ELF::R_MIPS_LO16);
334097a140dSpatrick case Mips::fixup_MICROMIPS_GPOFF_LO:
335097a140dSpatrick return setRTypes(ELF::R_MICROMIPS_GPREL16, ELF::R_MICROMIPS_SUB,
336097a140dSpatrick ELF::R_MICROMIPS_LO16);
33709467b48Spatrick case Mips::fixup_Mips_HIGHER:
33809467b48Spatrick return ELF::R_MIPS_HIGHER;
33909467b48Spatrick case Mips::fixup_Mips_HIGHEST:
34009467b48Spatrick return ELF::R_MIPS_HIGHEST;
34109467b48Spatrick case Mips::fixup_Mips_SUB:
34209467b48Spatrick return ELF::R_MIPS_SUB;
34309467b48Spatrick case Mips::fixup_Mips_GOT_HI16:
34409467b48Spatrick return ELF::R_MIPS_GOT_HI16;
34509467b48Spatrick case Mips::fixup_Mips_GOT_LO16:
34609467b48Spatrick return ELF::R_MIPS_GOT_LO16;
34709467b48Spatrick case Mips::fixup_Mips_CALL_HI16:
34809467b48Spatrick return ELF::R_MIPS_CALL_HI16;
34909467b48Spatrick case Mips::fixup_Mips_CALL_LO16:
35009467b48Spatrick return ELF::R_MIPS_CALL_LO16;
35109467b48Spatrick case Mips::fixup_MICROMIPS_26_S1:
35209467b48Spatrick return ELF::R_MICROMIPS_26_S1;
35309467b48Spatrick case Mips::fixup_MICROMIPS_HI16:
35409467b48Spatrick return ELF::R_MICROMIPS_HI16;
35509467b48Spatrick case Mips::fixup_MICROMIPS_LO16:
35609467b48Spatrick return ELF::R_MICROMIPS_LO16;
35709467b48Spatrick case Mips::fixup_MICROMIPS_GOT16:
35809467b48Spatrick return ELF::R_MICROMIPS_GOT16;
35909467b48Spatrick case Mips::fixup_MICROMIPS_CALL16:
36009467b48Spatrick return ELF::R_MICROMIPS_CALL16;
36109467b48Spatrick case Mips::fixup_MICROMIPS_GOT_DISP:
36209467b48Spatrick return ELF::R_MICROMIPS_GOT_DISP;
36309467b48Spatrick case Mips::fixup_MICROMIPS_GOT_PAGE:
36409467b48Spatrick return ELF::R_MICROMIPS_GOT_PAGE;
36509467b48Spatrick case Mips::fixup_MICROMIPS_GOT_OFST:
36609467b48Spatrick return ELF::R_MICROMIPS_GOT_OFST;
36709467b48Spatrick case Mips::fixup_MICROMIPS_TLS_GD:
36809467b48Spatrick return ELF::R_MICROMIPS_TLS_GD;
36909467b48Spatrick case Mips::fixup_MICROMIPS_TLS_LDM:
37009467b48Spatrick return ELF::R_MICROMIPS_TLS_LDM;
37109467b48Spatrick case Mips::fixup_MICROMIPS_TLS_DTPREL_HI16:
37209467b48Spatrick return ELF::R_MICROMIPS_TLS_DTPREL_HI16;
37309467b48Spatrick case Mips::fixup_MICROMIPS_TLS_DTPREL_LO16:
37409467b48Spatrick return ELF::R_MICROMIPS_TLS_DTPREL_LO16;
37509467b48Spatrick case Mips::fixup_MICROMIPS_GOTTPREL:
37609467b48Spatrick return ELF::R_MICROMIPS_TLS_GOTTPREL;
37709467b48Spatrick case Mips::fixup_MICROMIPS_TLS_TPREL_HI16:
37809467b48Spatrick return ELF::R_MICROMIPS_TLS_TPREL_HI16;
37909467b48Spatrick case Mips::fixup_MICROMIPS_TLS_TPREL_LO16:
38009467b48Spatrick return ELF::R_MICROMIPS_TLS_TPREL_LO16;
38109467b48Spatrick case Mips::fixup_MICROMIPS_SUB:
38209467b48Spatrick return ELF::R_MICROMIPS_SUB;
38309467b48Spatrick case Mips::fixup_MICROMIPS_HIGHER:
38409467b48Spatrick return ELF::R_MICROMIPS_HIGHER;
38509467b48Spatrick case Mips::fixup_MICROMIPS_HIGHEST:
38609467b48Spatrick return ELF::R_MICROMIPS_HIGHEST;
38709467b48Spatrick case Mips::fixup_Mips_JALR:
38809467b48Spatrick return ELF::R_MIPS_JALR;
38909467b48Spatrick case Mips::fixup_MICROMIPS_JALR:
39009467b48Spatrick return ELF::R_MICROMIPS_JALR;
39109467b48Spatrick }
39209467b48Spatrick
39309467b48Spatrick llvm_unreachable("invalid fixup kind!");
39409467b48Spatrick }
39509467b48Spatrick
39609467b48Spatrick /// Sort relocation table entries by offset except where another order is
39709467b48Spatrick /// required by the MIPS ABI.
39809467b48Spatrick ///
39909467b48Spatrick /// MIPS has a few relocations that have an AHL component in the expression used
40009467b48Spatrick /// to evaluate them. This AHL component is an addend with the same number of
40109467b48Spatrick /// bits as a symbol value but not all of our ABI's are able to supply a
40209467b48Spatrick /// sufficiently sized addend in a single relocation.
40309467b48Spatrick ///
40409467b48Spatrick /// The O32 ABI for example, uses REL relocations which store the addend in the
40509467b48Spatrick /// section data. All the relocations with AHL components affect 16-bit fields
40609467b48Spatrick /// so the addend for a single relocation is limited to 16-bit. This ABI
40709467b48Spatrick /// resolves the limitation by linking relocations (e.g. R_MIPS_HI16 and
40809467b48Spatrick /// R_MIPS_LO16) and distributing the addend between the linked relocations. The
40909467b48Spatrick /// ABI mandates that such relocations must be next to each other in a
41009467b48Spatrick /// particular order (e.g. R_MIPS_HI16 must be immediately followed by a
41109467b48Spatrick /// matching R_MIPS_LO16) but the rule is less strict in practice.
41209467b48Spatrick ///
41309467b48Spatrick /// The de facto standard is lenient in the following ways:
41409467b48Spatrick /// - 'Immediately following' does not refer to the next relocation entry but
41509467b48Spatrick /// the next matching relocation.
41609467b48Spatrick /// - There may be multiple high parts relocations for one low part relocation.
41709467b48Spatrick /// - There may be multiple low part relocations for one high part relocation.
41809467b48Spatrick /// - The AHL addend in each part does not have to be exactly equal as long as
41909467b48Spatrick /// the difference does not affect the carry bit from bit 15 into 16. This is
42009467b48Spatrick /// to allow, for example, the use of %lo(foo) and %lo(foo+4) when loading
42109467b48Spatrick /// both halves of a long long.
42209467b48Spatrick ///
42309467b48Spatrick /// See getMatchingLoType() for a description of which high part relocations
42409467b48Spatrick /// match which low part relocations. One particular thing to note is that
42509467b48Spatrick /// R_MIPS_GOT16 and similar only have AHL addends if they refer to local
42609467b48Spatrick /// symbols.
42709467b48Spatrick ///
42809467b48Spatrick /// It should also be noted that this function is not affected by whether
42909467b48Spatrick /// the symbol was kept or rewritten into a section-relative equivalent. We
43009467b48Spatrick /// always match using the expressions from the source.
sortRelocs(const MCAssembler & Asm,std::vector<ELFRelocationEntry> & Relocs)43109467b48Spatrick void MipsELFObjectWriter::sortRelocs(const MCAssembler &Asm,
43209467b48Spatrick std::vector<ELFRelocationEntry> &Relocs) {
43309467b48Spatrick // We do not need to sort the relocation table for RELA relocations which
43409467b48Spatrick // N32/N64 uses as the relocation addend contains the value we require,
43509467b48Spatrick // rather than it being split across a pair of relocations.
43609467b48Spatrick if (hasRelocationAddend())
43709467b48Spatrick return;
43809467b48Spatrick
43909467b48Spatrick if (Relocs.size() < 2)
44009467b48Spatrick return;
44109467b48Spatrick
44209467b48Spatrick // Sort relocations by the address they are applied to.
44309467b48Spatrick llvm::sort(Relocs,
44409467b48Spatrick [](const ELFRelocationEntry &A, const ELFRelocationEntry &B) {
44509467b48Spatrick return A.Offset < B.Offset;
44609467b48Spatrick });
44709467b48Spatrick
44809467b48Spatrick std::list<MipsRelocationEntry> Sorted;
44909467b48Spatrick std::list<ELFRelocationEntry> Remainder;
45009467b48Spatrick
45109467b48Spatrick LLVM_DEBUG(dumpRelocs("R: ", Relocs));
45209467b48Spatrick
45309467b48Spatrick // Separate the movable relocations (AHL relocations using the high bits) from
45409467b48Spatrick // the immobile relocations (everything else). This does not preserve high/low
45509467b48Spatrick // matches that already existed in the input.
45609467b48Spatrick copy_if_else(Relocs.begin(), Relocs.end(), std::back_inserter(Remainder),
45709467b48Spatrick std::back_inserter(Sorted), [](const ELFRelocationEntry &Reloc) {
45809467b48Spatrick return getMatchingLoType(Reloc) != ELF::R_MIPS_NONE;
45909467b48Spatrick });
46009467b48Spatrick
46109467b48Spatrick for (auto &R : Remainder) {
46209467b48Spatrick LLVM_DEBUG(dbgs() << "Matching: " << R << "\n");
46309467b48Spatrick
46409467b48Spatrick unsigned MatchingType = getMatchingLoType(R);
46509467b48Spatrick assert(MatchingType != ELF::R_MIPS_NONE &&
46609467b48Spatrick "Wrong list for reloc that doesn't need a match");
46709467b48Spatrick
46809467b48Spatrick // Find the best matching relocation for the current high part.
46909467b48Spatrick // See isMatchingReloc for a description of a matching relocation and
47009467b48Spatrick // compareMatchingRelocs for a description of what 'best' means.
47109467b48Spatrick auto InsertionPoint =
47209467b48Spatrick find_best(Sorted.begin(), Sorted.end(),
47309467b48Spatrick [&R, &MatchingType](const MipsRelocationEntry &X) {
47409467b48Spatrick return isMatchingReloc(X, R, MatchingType);
47509467b48Spatrick },
47609467b48Spatrick compareMatchingRelocs);
47709467b48Spatrick
47809467b48Spatrick // If we matched then insert the high part in front of the match and mark
47909467b48Spatrick // both relocations as being involved in a match. We only mark the high
48009467b48Spatrick // part for cosmetic reasons in the debug output.
48109467b48Spatrick //
48209467b48Spatrick // If we failed to find a match then the high part is orphaned. This is not
48309467b48Spatrick // permitted since the relocation cannot be evaluated without knowing the
48409467b48Spatrick // carry-in. We can sometimes handle this using a matching low part that is
48509467b48Spatrick // already used in a match but we already cover that case in
48609467b48Spatrick // isMatchingReloc and compareMatchingRelocs. For the remaining cases we
48709467b48Spatrick // should insert the high part at the end of the list. This will cause the
48809467b48Spatrick // linker to fail but the alternative is to cause the linker to bind the
48909467b48Spatrick // high part to a semi-matching low part and silently calculate the wrong
49009467b48Spatrick // value. Unfortunately we have no means to warn the user that we did this
49109467b48Spatrick // so leave it up to the linker to complain about it.
49209467b48Spatrick if (InsertionPoint != Sorted.end())
49309467b48Spatrick InsertionPoint->Matched = true;
49409467b48Spatrick Sorted.insert(InsertionPoint, R)->Matched = true;
49509467b48Spatrick }
49609467b48Spatrick
49709467b48Spatrick LLVM_DEBUG(dumpRelocs("S: ", Sorted));
49809467b48Spatrick
49909467b48Spatrick assert(Relocs.size() == Sorted.size() && "Some relocs were not consumed");
50009467b48Spatrick
50109467b48Spatrick // Overwrite the original vector with the sorted elements. The caller expects
50209467b48Spatrick // them in reverse order.
50309467b48Spatrick unsigned CopyTo = 0;
50409467b48Spatrick for (const auto &R : reverse(Sorted))
50509467b48Spatrick Relocs[CopyTo++] = R.R;
50609467b48Spatrick }
50709467b48Spatrick
needsRelocateWithSymbol(const MCSymbol & Sym,unsigned Type) const50809467b48Spatrick bool MipsELFObjectWriter::needsRelocateWithSymbol(const MCSymbol &Sym,
50909467b48Spatrick unsigned Type) const {
51009467b48Spatrick // If it's a compound relocation for N64 then we need the relocation if any
51109467b48Spatrick // sub-relocation needs it.
51209467b48Spatrick if (!isUInt<8>(Type))
51309467b48Spatrick return needsRelocateWithSymbol(Sym, Type & 0xff) ||
51409467b48Spatrick needsRelocateWithSymbol(Sym, (Type >> 8) & 0xff) ||
51509467b48Spatrick needsRelocateWithSymbol(Sym, (Type >> 16) & 0xff);
51609467b48Spatrick
51709467b48Spatrick switch (Type) {
51809467b48Spatrick default:
51909467b48Spatrick errs() << Type << "\n";
52009467b48Spatrick llvm_unreachable("Unexpected relocation");
52109467b48Spatrick return true;
52209467b48Spatrick
52309467b48Spatrick // This relocation doesn't affect the section data.
52409467b48Spatrick case ELF::R_MIPS_NONE:
52509467b48Spatrick return false;
52609467b48Spatrick
52709467b48Spatrick // On REL ABI's (e.g. O32), these relocations form pairs. The pairing is done
52809467b48Spatrick // by the static linker by matching the symbol and offset.
52909467b48Spatrick // We only see one relocation at a time but it's still safe to relocate with
53009467b48Spatrick // the section so long as both relocations make the same decision.
53109467b48Spatrick //
53209467b48Spatrick // Some older linkers may require the symbol for particular cases. Such cases
53309467b48Spatrick // are not supported yet but can be added as required.
53409467b48Spatrick case ELF::R_MIPS_GOT16:
53509467b48Spatrick case ELF::R_MIPS16_GOT16:
53609467b48Spatrick case ELF::R_MICROMIPS_GOT16:
53709467b48Spatrick case ELF::R_MIPS_HIGHER:
53809467b48Spatrick case ELF::R_MIPS_HIGHEST:
53909467b48Spatrick case ELF::R_MIPS_HI16:
54009467b48Spatrick case ELF::R_MIPS16_HI16:
54109467b48Spatrick case ELF::R_MICROMIPS_HI16:
54209467b48Spatrick case ELF::R_MIPS_LO16:
54309467b48Spatrick case ELF::R_MIPS16_LO16:
54409467b48Spatrick case ELF::R_MICROMIPS_LO16:
54509467b48Spatrick // FIXME: It should be safe to return false for the STO_MIPS_MICROMIPS but
54609467b48Spatrick // we neglect to handle the adjustment to the LSB of the addend that
54709467b48Spatrick // it causes in applyFixup() and similar.
54809467b48Spatrick if (cast<MCSymbolELF>(Sym).getOther() & ELF::STO_MIPS_MICROMIPS)
54909467b48Spatrick return true;
55009467b48Spatrick return false;
55109467b48Spatrick
55209467b48Spatrick case ELF::R_MIPS_GOT_PAGE:
55309467b48Spatrick case ELF::R_MICROMIPS_GOT_PAGE:
55409467b48Spatrick case ELF::R_MIPS_GOT_OFST:
55509467b48Spatrick case ELF::R_MICROMIPS_GOT_OFST:
55609467b48Spatrick case ELF::R_MIPS_16:
55709467b48Spatrick case ELF::R_MIPS_32:
55809467b48Spatrick case ELF::R_MIPS_GPREL32:
55909467b48Spatrick if (cast<MCSymbolELF>(Sym).getOther() & ELF::STO_MIPS_MICROMIPS)
56009467b48Spatrick return true;
561*d415bd75Srobert [[fallthrough]];
56209467b48Spatrick case ELF::R_MIPS_26:
56309467b48Spatrick case ELF::R_MIPS_64:
56409467b48Spatrick case ELF::R_MIPS_GPREL16:
56509467b48Spatrick case ELF::R_MIPS_PC16:
56609467b48Spatrick case ELF::R_MIPS_SUB:
56709467b48Spatrick return false;
56809467b48Spatrick
56909467b48Spatrick // FIXME: Many of these relocations should probably return false but this
57009467b48Spatrick // hasn't been confirmed to be safe yet.
57109467b48Spatrick case ELF::R_MIPS_REL32:
57209467b48Spatrick case ELF::R_MIPS_LITERAL:
57309467b48Spatrick case ELF::R_MIPS_CALL16:
57409467b48Spatrick case ELF::R_MIPS_SHIFT5:
57509467b48Spatrick case ELF::R_MIPS_SHIFT6:
57609467b48Spatrick case ELF::R_MIPS_GOT_DISP:
57709467b48Spatrick case ELF::R_MIPS_GOT_HI16:
57809467b48Spatrick case ELF::R_MIPS_GOT_LO16:
57909467b48Spatrick case ELF::R_MIPS_INSERT_A:
58009467b48Spatrick case ELF::R_MIPS_INSERT_B:
58109467b48Spatrick case ELF::R_MIPS_DELETE:
58209467b48Spatrick case ELF::R_MIPS_CALL_HI16:
58309467b48Spatrick case ELF::R_MIPS_CALL_LO16:
58409467b48Spatrick case ELF::R_MIPS_SCN_DISP:
58509467b48Spatrick case ELF::R_MIPS_REL16:
58609467b48Spatrick case ELF::R_MIPS_ADD_IMMEDIATE:
58709467b48Spatrick case ELF::R_MIPS_PJUMP:
58809467b48Spatrick case ELF::R_MIPS_RELGOT:
58909467b48Spatrick case ELF::R_MIPS_JALR:
59009467b48Spatrick case ELF::R_MIPS_TLS_DTPMOD32:
59109467b48Spatrick case ELF::R_MIPS_TLS_DTPREL32:
59209467b48Spatrick case ELF::R_MIPS_TLS_DTPMOD64:
59309467b48Spatrick case ELF::R_MIPS_TLS_DTPREL64:
59409467b48Spatrick case ELF::R_MIPS_TLS_GD:
59509467b48Spatrick case ELF::R_MIPS_TLS_LDM:
59609467b48Spatrick case ELF::R_MIPS_TLS_DTPREL_HI16:
59709467b48Spatrick case ELF::R_MIPS_TLS_DTPREL_LO16:
59809467b48Spatrick case ELF::R_MIPS_TLS_GOTTPREL:
59909467b48Spatrick case ELF::R_MIPS_TLS_TPREL32:
60009467b48Spatrick case ELF::R_MIPS_TLS_TPREL64:
60109467b48Spatrick case ELF::R_MIPS_TLS_TPREL_HI16:
60209467b48Spatrick case ELF::R_MIPS_TLS_TPREL_LO16:
60309467b48Spatrick case ELF::R_MIPS_GLOB_DAT:
60409467b48Spatrick case ELF::R_MIPS_PC21_S2:
60509467b48Spatrick case ELF::R_MIPS_PC26_S2:
60609467b48Spatrick case ELF::R_MIPS_PC18_S3:
60709467b48Spatrick case ELF::R_MIPS_PC19_S2:
60809467b48Spatrick case ELF::R_MIPS_PCHI16:
60909467b48Spatrick case ELF::R_MIPS_PCLO16:
61009467b48Spatrick case ELF::R_MIPS_COPY:
61109467b48Spatrick case ELF::R_MIPS_JUMP_SLOT:
61209467b48Spatrick case ELF::R_MIPS_NUM:
61309467b48Spatrick case ELF::R_MIPS_PC32:
61409467b48Spatrick case ELF::R_MIPS_EH:
61509467b48Spatrick case ELF::R_MICROMIPS_26_S1:
61609467b48Spatrick case ELF::R_MICROMIPS_GPREL16:
61709467b48Spatrick case ELF::R_MICROMIPS_LITERAL:
61809467b48Spatrick case ELF::R_MICROMIPS_PC7_S1:
61909467b48Spatrick case ELF::R_MICROMIPS_PC10_S1:
62009467b48Spatrick case ELF::R_MICROMIPS_PC16_S1:
62109467b48Spatrick case ELF::R_MICROMIPS_CALL16:
62209467b48Spatrick case ELF::R_MICROMIPS_GOT_DISP:
62309467b48Spatrick case ELF::R_MICROMIPS_GOT_HI16:
62409467b48Spatrick case ELF::R_MICROMIPS_GOT_LO16:
62509467b48Spatrick case ELF::R_MICROMIPS_SUB:
62609467b48Spatrick case ELF::R_MICROMIPS_HIGHER:
62709467b48Spatrick case ELF::R_MICROMIPS_HIGHEST:
62809467b48Spatrick case ELF::R_MICROMIPS_CALL_HI16:
62909467b48Spatrick case ELF::R_MICROMIPS_CALL_LO16:
63009467b48Spatrick case ELF::R_MICROMIPS_SCN_DISP:
63109467b48Spatrick case ELF::R_MICROMIPS_JALR:
63209467b48Spatrick case ELF::R_MICROMIPS_HI0_LO16:
63309467b48Spatrick case ELF::R_MICROMIPS_TLS_GD:
63409467b48Spatrick case ELF::R_MICROMIPS_TLS_LDM:
63509467b48Spatrick case ELF::R_MICROMIPS_TLS_DTPREL_HI16:
63609467b48Spatrick case ELF::R_MICROMIPS_TLS_DTPREL_LO16:
63709467b48Spatrick case ELF::R_MICROMIPS_TLS_GOTTPREL:
63809467b48Spatrick case ELF::R_MICROMIPS_TLS_TPREL_HI16:
63909467b48Spatrick case ELF::R_MICROMIPS_TLS_TPREL_LO16:
64009467b48Spatrick case ELF::R_MICROMIPS_GPREL7_S2:
64109467b48Spatrick case ELF::R_MICROMIPS_PC23_S2:
64209467b48Spatrick case ELF::R_MICROMIPS_PC21_S1:
64309467b48Spatrick case ELF::R_MICROMIPS_PC26_S1:
64409467b48Spatrick case ELF::R_MICROMIPS_PC18_S3:
64509467b48Spatrick case ELF::R_MICROMIPS_PC19_S2:
64609467b48Spatrick return true;
64709467b48Spatrick
64809467b48Spatrick // FIXME: Many of these should probably return false but MIPS16 isn't
64909467b48Spatrick // supported by the integrated assembler.
65009467b48Spatrick case ELF::R_MIPS16_26:
65109467b48Spatrick case ELF::R_MIPS16_GPREL:
65209467b48Spatrick case ELF::R_MIPS16_CALL16:
65309467b48Spatrick case ELF::R_MIPS16_TLS_GD:
65409467b48Spatrick case ELF::R_MIPS16_TLS_LDM:
65509467b48Spatrick case ELF::R_MIPS16_TLS_DTPREL_HI16:
65609467b48Spatrick case ELF::R_MIPS16_TLS_DTPREL_LO16:
65709467b48Spatrick case ELF::R_MIPS16_TLS_GOTTPREL:
65809467b48Spatrick case ELF::R_MIPS16_TLS_TPREL_HI16:
65909467b48Spatrick case ELF::R_MIPS16_TLS_TPREL_LO16:
66009467b48Spatrick llvm_unreachable("Unsupported MIPS16 relocation");
66109467b48Spatrick return true;
66209467b48Spatrick }
66309467b48Spatrick }
66409467b48Spatrick
66509467b48Spatrick std::unique_ptr<MCObjectTargetWriter>
createMipsELFObjectWriter(const Triple & TT,bool IsN32)66609467b48Spatrick llvm::createMipsELFObjectWriter(const Triple &TT, bool IsN32) {
66709467b48Spatrick uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TT.getOS());
66809467b48Spatrick bool IsN64 = TT.isArch64Bit() && !IsN32;
66909467b48Spatrick bool HasRelocationAddend = TT.isArch64Bit();
67009467b48Spatrick return std::make_unique<MipsELFObjectWriter>(OSABI, HasRelocationAddend,
67109467b48Spatrick IsN64);
67209467b48Spatrick }
673