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