MipsELFObjectWriter.cpp revision 288943
1//===-- MipsELFObjectWriter.cpp - Mips ELF Writer -------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "MCTargetDesc/MipsBaseInfo.h"
11#include "MCTargetDesc/MipsFixupKinds.h"
12#include "MCTargetDesc/MipsMCTargetDesc.h"
13#include "llvm/ADT/STLExtras.h"
14#include "llvm/MC/MCAssembler.h"
15#include "llvm/MC/MCELFObjectWriter.h"
16#include "llvm/MC/MCExpr.h"
17#include "llvm/MC/MCSection.h"
18#include "llvm/MC/MCSymbolELF.h"
19#include "llvm/MC/MCValue.h"
20#include "llvm/Support/ErrorHandling.h"
21#include <list>
22
23using namespace llvm;
24
25namespace {
26// A helper structure based on ELFRelocationEntry, used for sorting entries in
27// the relocation table.
28struct MipsRelocationEntry {
29  MipsRelocationEntry(const ELFRelocationEntry &R)
30      : R(R), SortOffset(R.Offset), HasMatchingHi(false) {}
31  const ELFRelocationEntry R;
32  // SortOffset equals R.Offset except for the *HI16 relocations, for which it
33  // will be set based on the R.Offset of the matching *LO16 relocation.
34  int64_t SortOffset;
35  // True when this is a *LO16 relocation chosen as a match for a *HI16
36  // relocation.
37  bool HasMatchingHi;
38};
39
40  class MipsELFObjectWriter : public MCELFObjectTargetWriter {
41  public:
42    MipsELFObjectWriter(bool _is64Bit, uint8_t OSABI,
43                        bool _isN64, bool IsLittleEndian);
44
45    ~MipsELFObjectWriter() override;
46
47    unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup,
48                          bool IsPCRel) const override;
49    bool needsRelocateWithSymbol(const MCSymbol &Sym,
50                                 unsigned Type) const override;
51    virtual void sortRelocs(const MCAssembler &Asm,
52                            std::vector<ELFRelocationEntry> &Relocs) override;
53  };
54}
55
56MipsELFObjectWriter::MipsELFObjectWriter(bool _is64Bit, uint8_t OSABI,
57                                         bool _isN64, bool IsLittleEndian)
58    : MCELFObjectTargetWriter(_is64Bit, OSABI, ELF::EM_MIPS,
59                              /*HasRelocationAddend*/ _isN64,
60                              /*IsN64*/ _isN64) {}
61
62MipsELFObjectWriter::~MipsELFObjectWriter() {}
63
64unsigned MipsELFObjectWriter::GetRelocType(const MCValue &Target,
65                                           const MCFixup &Fixup,
66                                           bool IsPCRel) const {
67  // Determine the type of the relocation.
68  unsigned Kind = (unsigned)Fixup.getKind();
69
70  switch (Kind) {
71  case Mips::fixup_Mips_16:
72  case FK_Data_2:
73    return IsPCRel ? ELF::R_MIPS_PC16 : ELF::R_MIPS_16;
74  case Mips::fixup_Mips_32:
75  case FK_Data_4:
76    return IsPCRel ? ELF::R_MIPS_PC32 : ELF::R_MIPS_32;
77  }
78
79  if (IsPCRel) {
80    switch (Kind) {
81    case Mips::fixup_Mips_Branch_PCRel:
82    case Mips::fixup_Mips_PC16:
83      return ELF::R_MIPS_PC16;
84    case Mips::fixup_MICROMIPS_PC7_S1:
85      return ELF::R_MICROMIPS_PC7_S1;
86    case Mips::fixup_MICROMIPS_PC10_S1:
87      return ELF::R_MICROMIPS_PC10_S1;
88    case Mips::fixup_MICROMIPS_PC16_S1:
89      return ELF::R_MICROMIPS_PC16_S1;
90    case Mips::fixup_MIPS_PC19_S2:
91      return ELF::R_MIPS_PC19_S2;
92    case Mips::fixup_MIPS_PC18_S3:
93      return ELF::R_MIPS_PC18_S3;
94    case Mips::fixup_MIPS_PC21_S2:
95      return ELF::R_MIPS_PC21_S2;
96    case Mips::fixup_MIPS_PC26_S2:
97      return ELF::R_MIPS_PC26_S2;
98    case Mips::fixup_MIPS_PCHI16:
99      return ELF::R_MIPS_PCHI16;
100    case Mips::fixup_MIPS_PCLO16:
101      return ELF::R_MIPS_PCLO16;
102    }
103
104    llvm_unreachable("invalid PC-relative fixup kind!");
105  }
106
107  switch (Kind) {
108  case Mips::fixup_Mips_64:
109  case FK_Data_8:
110    return ELF::R_MIPS_64;
111  case FK_GPRel_4:
112    if (isN64()) {
113      unsigned Type = (unsigned)ELF::R_MIPS_NONE;
114      Type = setRType((unsigned)ELF::R_MIPS_GPREL32, Type);
115      Type = setRType2((unsigned)ELF::R_MIPS_64, Type);
116      Type = setRType3((unsigned)ELF::R_MIPS_NONE, Type);
117      return Type;
118    }
119    return ELF::R_MIPS_GPREL32;
120  case Mips::fixup_Mips_GPREL16:
121    return ELF::R_MIPS_GPREL16;
122  case Mips::fixup_Mips_26:
123    return ELF::R_MIPS_26;
124  case Mips::fixup_Mips_CALL16:
125    return ELF::R_MIPS_CALL16;
126  case Mips::fixup_Mips_GOT_Global:
127  case Mips::fixup_Mips_GOT_Local:
128    return ELF::R_MIPS_GOT16;
129  case Mips::fixup_Mips_HI16:
130    return ELF::R_MIPS_HI16;
131  case Mips::fixup_Mips_LO16:
132    return ELF::R_MIPS_LO16;
133  case Mips::fixup_Mips_TLSGD:
134    return ELF::R_MIPS_TLS_GD;
135  case Mips::fixup_Mips_GOTTPREL:
136    return ELF::R_MIPS_TLS_GOTTPREL;
137  case Mips::fixup_Mips_TPREL_HI:
138    return ELF::R_MIPS_TLS_TPREL_HI16;
139  case Mips::fixup_Mips_TPREL_LO:
140    return ELF::R_MIPS_TLS_TPREL_LO16;
141  case Mips::fixup_Mips_TLSLDM:
142    return ELF::R_MIPS_TLS_LDM;
143  case Mips::fixup_Mips_DTPREL_HI:
144    return ELF::R_MIPS_TLS_DTPREL_HI16;
145  case Mips::fixup_Mips_DTPREL_LO:
146    return ELF::R_MIPS_TLS_DTPREL_LO16;
147  case Mips::fixup_Mips_GOT_PAGE:
148    return ELF::R_MIPS_GOT_PAGE;
149  case Mips::fixup_Mips_GOT_OFST:
150    return ELF::R_MIPS_GOT_OFST;
151  case Mips::fixup_Mips_GOT_DISP:
152    return ELF::R_MIPS_GOT_DISP;
153  case Mips::fixup_Mips_GPOFF_HI: {
154    unsigned Type = (unsigned)ELF::R_MIPS_NONE;
155    Type = setRType((unsigned)ELF::R_MIPS_GPREL16, Type);
156    Type = setRType2((unsigned)ELF::R_MIPS_SUB, Type);
157    Type = setRType3((unsigned)ELF::R_MIPS_HI16, Type);
158    return Type;
159  }
160  case Mips::fixup_Mips_GPOFF_LO: {
161    unsigned Type = (unsigned)ELF::R_MIPS_NONE;
162    Type = setRType((unsigned)ELF::R_MIPS_GPREL16, Type);
163    Type = setRType2((unsigned)ELF::R_MIPS_SUB, Type);
164    Type = setRType3((unsigned)ELF::R_MIPS_LO16, Type);
165    return Type;
166  }
167  case Mips::fixup_Mips_HIGHER:
168    return ELF::R_MIPS_HIGHER;
169  case Mips::fixup_Mips_HIGHEST:
170    return ELF::R_MIPS_HIGHEST;
171  case Mips::fixup_Mips_GOT_HI16:
172    return ELF::R_MIPS_GOT_HI16;
173  case Mips::fixup_Mips_GOT_LO16:
174    return ELF::R_MIPS_GOT_LO16;
175  case Mips::fixup_Mips_CALL_HI16:
176    return ELF::R_MIPS_CALL_HI16;
177  case Mips::fixup_Mips_CALL_LO16:
178    return ELF::R_MIPS_CALL_LO16;
179  case Mips::fixup_MICROMIPS_26_S1:
180    return ELF::R_MICROMIPS_26_S1;
181  case Mips::fixup_MICROMIPS_HI16:
182    return ELF::R_MICROMIPS_HI16;
183  case Mips::fixup_MICROMIPS_LO16:
184    return ELF::R_MICROMIPS_LO16;
185  case Mips::fixup_MICROMIPS_GOT16:
186    return ELF::R_MICROMIPS_GOT16;
187  case Mips::fixup_MICROMIPS_CALL16:
188    return ELF::R_MICROMIPS_CALL16;
189  case Mips::fixup_MICROMIPS_GOT_DISP:
190    return ELF::R_MICROMIPS_GOT_DISP;
191  case Mips::fixup_MICROMIPS_GOT_PAGE:
192    return ELF::R_MICROMIPS_GOT_PAGE;
193  case Mips::fixup_MICROMIPS_GOT_OFST:
194    return ELF::R_MICROMIPS_GOT_OFST;
195  case Mips::fixup_MICROMIPS_TLS_GD:
196    return ELF::R_MICROMIPS_TLS_GD;
197  case Mips::fixup_MICROMIPS_TLS_LDM:
198    return ELF::R_MICROMIPS_TLS_LDM;
199  case Mips::fixup_MICROMIPS_TLS_DTPREL_HI16:
200    return ELF::R_MICROMIPS_TLS_DTPREL_HI16;
201  case Mips::fixup_MICROMIPS_TLS_DTPREL_LO16:
202    return ELF::R_MICROMIPS_TLS_DTPREL_LO16;
203  case Mips::fixup_MICROMIPS_TLS_TPREL_HI16:
204    return ELF::R_MICROMIPS_TLS_TPREL_HI16;
205  case Mips::fixup_MICROMIPS_TLS_TPREL_LO16:
206    return ELF::R_MICROMIPS_TLS_TPREL_LO16;
207  }
208
209  llvm_unreachable("invalid fixup kind!");
210}
211
212// Sort entries by SortOffset in descending order.
213// When there are more *HI16 relocs paired with one *LO16 reloc, the 2nd rule
214// sorts them in ascending order of R.Offset.
215static int cmpRelMips(const MipsRelocationEntry *AP,
216                      const MipsRelocationEntry *BP) {
217  const MipsRelocationEntry &A = *AP;
218  const MipsRelocationEntry &B = *BP;
219  if (A.SortOffset != B.SortOffset)
220    return B.SortOffset - A.SortOffset;
221  if (A.R.Offset != B.R.Offset)
222    return A.R.Offset - B.R.Offset;
223  if (B.R.Type != A.R.Type)
224    return B.R.Type - A.R.Type;
225  //llvm_unreachable("ELFRelocs might be unstable!");
226  return 0;
227}
228
229// For the given Reloc.Type, return the matching relocation type, as in the
230// table below.
231static unsigned getMatchingLoType(const MCAssembler &Asm,
232                                  const ELFRelocationEntry &Reloc) {
233  unsigned Type = Reloc.Type;
234  if (Type == ELF::R_MIPS_HI16)
235    return ELF::R_MIPS_LO16;
236  if (Type == ELF::R_MICROMIPS_HI16)
237    return ELF::R_MICROMIPS_LO16;
238  if (Type == ELF::R_MIPS16_HI16)
239    return ELF::R_MIPS16_LO16;
240
241  if (Reloc.Symbol->getBinding() != ELF::STB_LOCAL)
242    return ELF::R_MIPS_NONE;
243
244  if (Type == ELF::R_MIPS_GOT16)
245    return ELF::R_MIPS_LO16;
246  if (Type == ELF::R_MICROMIPS_GOT16)
247    return ELF::R_MICROMIPS_LO16;
248  if (Type == ELF::R_MIPS16_GOT16)
249    return ELF::R_MIPS16_LO16;
250
251  return ELF::R_MIPS_NONE;
252}
253
254// Return true if First needs a matching *LO16, its matching *LO16 type equals
255// Second's type and both relocations are against the same symbol.
256static bool areMatchingHiAndLo(const MCAssembler &Asm,
257                               const ELFRelocationEntry &First,
258                               const ELFRelocationEntry &Second) {
259  return getMatchingLoType(Asm, First) != ELF::R_MIPS_NONE &&
260         getMatchingLoType(Asm, First) == Second.Type &&
261         First.Symbol && First.Symbol == Second.Symbol;
262}
263
264// Return true if MipsRelocs[Index] is a *LO16 preceded by a matching *HI16.
265static bool
266isPrecededByMatchingHi(const MCAssembler &Asm, uint32_t Index,
267                       std::vector<MipsRelocationEntry> &MipsRelocs) {
268  return Index < MipsRelocs.size() - 1 &&
269         areMatchingHiAndLo(Asm, MipsRelocs[Index + 1].R, MipsRelocs[Index].R);
270}
271
272// Return true if MipsRelocs[Index] is a *LO16 not preceded by a matching *HI16
273// and not chosen by a *HI16 as a match.
274static bool isFreeLo(const MCAssembler &Asm, uint32_t Index,
275                     std::vector<MipsRelocationEntry> &MipsRelocs) {
276  return Index < MipsRelocs.size() && !MipsRelocs[Index].HasMatchingHi &&
277         !isPrecededByMatchingHi(Asm, Index, MipsRelocs);
278}
279
280// Lo is chosen as a match for Hi, set their fields accordingly.
281// Mips instructions have fixed length of at least two bytes (two for
282// micromips/mips16, four for mips32/64), so we can set HI's SortOffset to
283// matching LO's Offset minus one to simplify the sorting function.
284static void setMatch(MipsRelocationEntry &Hi, MipsRelocationEntry &Lo) {
285  Lo.HasMatchingHi = true;
286  Hi.SortOffset = Lo.R.Offset - 1;
287}
288
289// We sort relocation table entries by offset, except for one additional rule
290// required by MIPS ABI: every *HI16 relocation must be immediately followed by
291// the corresponding *LO16 relocation. We also support a GNU extension that
292// allows more *HI16s paired with one *LO16.
293//
294// *HI16 relocations and their matching *LO16 are:
295//
296// +---------------------------------------------+-------------------+
297// |               *HI16                         |  matching *LO16   |
298// |---------------------------------------------+-------------------|
299// |  R_MIPS_HI16, local R_MIPS_GOT16            |    R_MIPS_LO16    |
300// |  R_MICROMIPS_HI16, local R_MICROMIPS_GOT16  | R_MICROMIPS_LO16  |
301// |  R_MIPS16_HI16, local R_MIPS16_GOT16        |  R_MIPS16_LO16    |
302// +---------------------------------------------+-------------------+
303//
304// (local R_*_GOT16 meaning R_*_GOT16 against the local symbol.)
305//
306// To handle *HI16 and *LO16 relocations, the linker needs a combined addend
307// ("AHL") calculated from both *HI16 ("AHI") and *LO16 ("ALO") relocations:
308// AHL = (AHI << 16) + (short)ALO;
309//
310// We are reusing gnu as sorting algorithm so we are emitting the relocation
311// table sorted the same way as gnu as would sort it, for easier comparison of
312// the generated .o files.
313//
314// The logic is:
315// search the table (starting from the highest offset and going back to zero)
316// for all *HI16 relocations that don't have a matching *LO16.
317// For every such HI, find a matching LO with highest offset that isn't already
318// matched with another HI. If there are no free LOs, match it with the first
319// found (starting from lowest offset).
320// When there are more HIs matched with one LO, sort them in descending order by
321// offset.
322//
323// In other words, when searching for a matching LO:
324// - don't look for a 'better' match for the HIs that are already followed by a
325//   matching LO;
326// - prefer LOs without a pair;
327// - prefer LOs with higher offset;
328void MipsELFObjectWriter::sortRelocs(const MCAssembler &Asm,
329                                     std::vector<ELFRelocationEntry> &Relocs) {
330  if (Relocs.size() < 2)
331    return;
332
333  // The default function sorts entries by Offset in descending order.
334  MCELFObjectTargetWriter::sortRelocs(Asm, Relocs);
335
336  // Init MipsRelocs from Relocs.
337  std::vector<MipsRelocationEntry> MipsRelocs;
338  for (unsigned I = 0, E = Relocs.size(); I != E; ++I)
339    MipsRelocs.push_back(MipsRelocationEntry(Relocs[I]));
340
341  // Find a matching LO for all HIs that need it.
342  for (int32_t I = 0, E = MipsRelocs.size(); I != E; ++I) {
343    if (getMatchingLoType(Asm, MipsRelocs[I].R) == ELF::R_MIPS_NONE ||
344        (I > 0 && isPrecededByMatchingHi(Asm, I - 1, MipsRelocs)))
345      continue;
346
347    int32_t MatchedLoIndex = -1;
348
349    // Search the list in the ascending order of Offset.
350    for (int32_t J = MipsRelocs.size() - 1, N = -1; J != N; --J) {
351      // check for a match
352      if (areMatchingHiAndLo(Asm, MipsRelocs[I].R, MipsRelocs[J].R) &&
353          (MatchedLoIndex == -1 || // first match
354           // or we already have a match,
355           // but this one is with higher offset and it's free
356           (MatchedLoIndex > J && isFreeLo(Asm, J, MipsRelocs))))
357        MatchedLoIndex = J;
358    }
359
360    if (MatchedLoIndex != -1)
361      // We have a match.
362      setMatch(MipsRelocs[I], MipsRelocs[MatchedLoIndex]);
363  }
364
365  // SortOffsets are calculated, call the sorting function.
366  array_pod_sort(MipsRelocs.begin(), MipsRelocs.end(), cmpRelMips);
367
368  // Copy sorted MipsRelocs back to Relocs.
369  for (unsigned I = 0, E = MipsRelocs.size(); I != E; ++I)
370    Relocs[I] = MipsRelocs[I].R;
371}
372
373bool MipsELFObjectWriter::needsRelocateWithSymbol(const MCSymbol &Sym,
374                                                  unsigned Type) const {
375  // FIXME: This is extremely conservative. This really needs to use a
376  // whitelist with a clear explanation for why each realocation needs to
377  // point to the symbol, not to the section.
378  switch (Type) {
379  default:
380    return true;
381
382  case ELF::R_MIPS_GOT16:
383  case ELF::R_MIPS16_GOT16:
384  case ELF::R_MICROMIPS_GOT16:
385    llvm_unreachable("Should have been handled already");
386
387  // These relocations might be paired with another relocation. The pairing is
388  // done by the static linker by matching the symbol. Since we only see one
389  // relocation at a time, we have to force them to relocate with a symbol to
390  // avoid ending up with a pair where one points to a section and another
391  // points to a symbol.
392  case ELF::R_MIPS_HI16:
393  case ELF::R_MIPS16_HI16:
394  case ELF::R_MICROMIPS_HI16:
395  case ELF::R_MIPS_LO16:
396  case ELF::R_MIPS16_LO16:
397  case ELF::R_MICROMIPS_LO16:
398    return true;
399
400  case ELF::R_MIPS_32:
401    if (cast<MCSymbolELF>(Sym).getOther() & ELF::STO_MIPS_MICROMIPS)
402      return true;
403    // falltrough
404  case ELF::R_MIPS_26:
405  case ELF::R_MIPS_64:
406  case ELF::R_MIPS_GPREL16:
407    return false;
408  }
409}
410
411MCObjectWriter *llvm::createMipsELFObjectWriter(raw_pwrite_stream &OS,
412                                                uint8_t OSABI,
413                                                bool IsLittleEndian,
414                                                bool Is64Bit) {
415  MCELFObjectTargetWriter *MOTW =
416      new MipsELFObjectWriter(Is64Bit, OSABI, Is64Bit, IsLittleEndian);
417  return createELFObjectWriter(MOTW, OS, IsLittleEndian);
418}
419