/src/keystone/llvm/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===-- ARMELFObjectWriter.cpp - ARM 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/ARMMCTargetDesc.h" |
11 | | #include "MCTargetDesc/ARMFixupKinds.h" |
12 | | #include "llvm/ADT/StringSwitch.h" |
13 | | #include "llvm/MC/MCELFObjectWriter.h" |
14 | | #include "llvm/MC/MCExpr.h" |
15 | | #include "llvm/MC/MCSectionELF.h" |
16 | | #include "llvm/MC/MCValue.h" |
17 | | #include "llvm/Support/Debug.h" |
18 | | #include "llvm/Support/ErrorHandling.h" |
19 | | #include "llvm/Support/raw_ostream.h" |
20 | | |
21 | | using namespace llvm_ks; |
22 | | |
23 | | namespace { |
24 | | class ARMELFObjectWriter : public MCELFObjectTargetWriter { |
25 | | enum { DefaultEABIVersion = 0x05000000U }; |
26 | | unsigned GetRelocTypeInner(const MCValue &Target, |
27 | | const MCFixup &Fixup, |
28 | | bool IsPCRel) const; |
29 | | |
30 | | |
31 | | public: |
32 | | ARMELFObjectWriter(uint8_t OSABI); |
33 | | |
34 | | ~ARMELFObjectWriter() override; |
35 | | |
36 | | unsigned getRelocType(MCContext &Ctx, const MCValue &Target, |
37 | | const MCFixup &Fixup, bool IsPCRel) const override; |
38 | | |
39 | | bool needsRelocateWithSymbol(const MCSymbol &Sym, |
40 | | unsigned Type) const override; |
41 | | }; |
42 | | } |
43 | | |
44 | | ARMELFObjectWriter::ARMELFObjectWriter(uint8_t OSABI) |
45 | 61.7k | : MCELFObjectTargetWriter(/*Is64Bit*/ false, OSABI, |
46 | 61.7k | ELF::EM_ARM, |
47 | 61.7k | /*HasRelocationAddend*/ false) {} |
48 | | |
49 | | ARMELFObjectWriter::~ARMELFObjectWriter() {} |
50 | | |
51 | | bool ARMELFObjectWriter::needsRelocateWithSymbol(const MCSymbol &Sym, |
52 | 55.2k | unsigned Type) const { |
53 | | // FIXME: This is extremely conservative. This really needs to use a |
54 | | // whitelist with a clear explanation for why each realocation needs to |
55 | | // point to the symbol, not to the section. |
56 | 55.2k | switch (Type) { |
57 | 1.21k | default: |
58 | 1.21k | return true; |
59 | | |
60 | 0 | case ELF::R_ARM_PREL31: |
61 | 54.0k | case ELF::R_ARM_ABS32: |
62 | 54.0k | return false; |
63 | 55.2k | } |
64 | 55.2k | } |
65 | | |
66 | | // Need to examine the Fixup when determining whether to |
67 | | // emit the relocation as an explicit symbol or as a section relative |
68 | | // offset |
69 | | unsigned ARMELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target, |
70 | | const MCFixup &Fixup, |
71 | 59.2k | bool IsPCRel) const { |
72 | 59.2k | return GetRelocTypeInner(Target, Fixup, IsPCRel); |
73 | 59.2k | } |
74 | | |
75 | | unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target, |
76 | | const MCFixup &Fixup, |
77 | 59.2k | bool IsPCRel) const { |
78 | 59.2k | MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant(); |
79 | | |
80 | 59.2k | unsigned Type = 0; |
81 | 59.2k | if (IsPCRel) { |
82 | 4.58k | switch ((unsigned)Fixup.getKind()) { |
83 | 0 | default: |
84 | 0 | report_fatal_error("unsupported relocation on symbol"); |
85 | 0 | return ELF::R_ARM_NONE; |
86 | 2.34k | case FK_Data_4: |
87 | 2.34k | switch (Modifier) { |
88 | 0 | default: llvm_unreachable("Unsupported Modifier"); |
89 | 2.34k | case MCSymbolRefExpr::VK_None: |
90 | 2.34k | Type = ELF::R_ARM_REL32; |
91 | 2.34k | break; |
92 | 0 | case MCSymbolRefExpr::VK_TLSGD: |
93 | 0 | llvm_unreachable("unimplemented"); |
94 | 0 | case MCSymbolRefExpr::VK_GOTTPOFF: |
95 | 0 | Type = ELF::R_ARM_TLS_IE32; |
96 | 0 | break; |
97 | 0 | case MCSymbolRefExpr::VK_ARM_GOT_PREL: |
98 | 0 | Type = ELF::R_ARM_GOT_PREL; |
99 | 0 | break; |
100 | 2.34k | } |
101 | 2.34k | break; |
102 | 2.34k | case ARM::fixup_arm_blx: |
103 | 403 | case ARM::fixup_arm_uncondbl: |
104 | 403 | switch (Modifier) { |
105 | 0 | case MCSymbolRefExpr::VK_PLT: |
106 | 0 | Type = ELF::R_ARM_CALL; |
107 | 0 | break; |
108 | 0 | case MCSymbolRefExpr::VK_ARM_TLSCALL: |
109 | 0 | Type = ELF::R_ARM_TLS_CALL; |
110 | 0 | break; |
111 | 403 | default: |
112 | 403 | Type = ELF::R_ARM_CALL; |
113 | 403 | break; |
114 | 403 | } |
115 | 403 | break; |
116 | 403 | case ARM::fixup_arm_condbl: |
117 | 419 | case ARM::fixup_arm_condbranch: |
118 | 804 | case ARM::fixup_arm_uncondbranch: |
119 | 804 | Type = ELF::R_ARM_JUMP24; |
120 | 804 | break; |
121 | 63 | case ARM::fixup_t2_condbranch: |
122 | 228 | case ARM::fixup_t2_uncondbranch: |
123 | 228 | Type = ELF::R_ARM_THM_JUMP24; |
124 | 228 | break; |
125 | 0 | case ARM::fixup_arm_movt_hi16: |
126 | 0 | Type = ELF::R_ARM_MOVT_PREL; |
127 | 0 | break; |
128 | 0 | case ARM::fixup_arm_movw_lo16: |
129 | 0 | Type = ELF::R_ARM_MOVW_PREL_NC; |
130 | 0 | break; |
131 | 0 | case ARM::fixup_t2_movt_hi16: |
132 | 0 | Type = ELF::R_ARM_THM_MOVT_PREL; |
133 | 0 | break; |
134 | 0 | case ARM::fixup_t2_movw_lo16: |
135 | 0 | Type = ELF::R_ARM_THM_MOVW_PREL_NC; |
136 | 0 | break; |
137 | 692 | case ARM::fixup_arm_thumb_bl: |
138 | 803 | case ARM::fixup_arm_thumb_blx: |
139 | 803 | switch (Modifier) { |
140 | 0 | case MCSymbolRefExpr::VK_ARM_TLSCALL: |
141 | 0 | Type = ELF::R_ARM_THM_TLS_CALL; |
142 | 0 | break; |
143 | 803 | default: |
144 | 803 | Type = ELF::R_ARM_THM_CALL; |
145 | 803 | break; |
146 | 803 | } |
147 | 803 | break; |
148 | 4.58k | } |
149 | 54.6k | } else { |
150 | 54.6k | switch ((unsigned)Fixup.getKind()) { |
151 | 0 | default: |
152 | 0 | report_fatal_error("unsupported relocation on symbol"); |
153 | 0 | return ELF::R_ARM_NONE; |
154 | 413 | case FK_Data_1: |
155 | 413 | switch (Modifier) { |
156 | 0 | default: llvm_unreachable("unsupported Modifier"); |
157 | 413 | case MCSymbolRefExpr::VK_None: |
158 | 413 | Type = ELF::R_ARM_ABS8; |
159 | 413 | break; |
160 | 413 | } |
161 | 413 | break; |
162 | 413 | case FK_Data_2: |
163 | 259 | switch (Modifier) { |
164 | 0 | default: llvm_unreachable("unsupported modifier"); |
165 | 259 | case MCSymbolRefExpr::VK_None: |
166 | 259 | Type = ELF::R_ARM_ABS16; |
167 | 259 | break; |
168 | 259 | } |
169 | 259 | break; |
170 | 54.0k | case FK_Data_4: |
171 | 54.0k | switch (Modifier) { |
172 | 0 | default: llvm_unreachable("Unsupported Modifier"); |
173 | 0 | case MCSymbolRefExpr::VK_ARM_NONE: |
174 | 0 | Type = ELF::R_ARM_NONE; |
175 | 0 | break; |
176 | 0 | case MCSymbolRefExpr::VK_GOT: |
177 | 0 | Type = ELF::R_ARM_GOT_BREL; |
178 | 0 | break; |
179 | 0 | case MCSymbolRefExpr::VK_TLSGD: |
180 | 0 | Type = ELF::R_ARM_TLS_GD32; |
181 | 0 | break; |
182 | 0 | case MCSymbolRefExpr::VK_TPOFF: |
183 | 0 | Type = ELF::R_ARM_TLS_LE32; |
184 | 0 | break; |
185 | 0 | case MCSymbolRefExpr::VK_GOTTPOFF: |
186 | 0 | Type = ELF::R_ARM_TLS_IE32; |
187 | 0 | break; |
188 | 54.0k | case MCSymbolRefExpr::VK_None: |
189 | 54.0k | Type = ELF::R_ARM_ABS32; |
190 | 54.0k | break; |
191 | 0 | case MCSymbolRefExpr::VK_GOTOFF: |
192 | 0 | Type = ELF::R_ARM_GOTOFF32; |
193 | 0 | break; |
194 | 0 | case MCSymbolRefExpr::VK_ARM_GOT_PREL: |
195 | 0 | Type = ELF::R_ARM_GOT_PREL; |
196 | 0 | break; |
197 | 0 | case MCSymbolRefExpr::VK_ARM_TARGET1: |
198 | 0 | Type = ELF::R_ARM_TARGET1; |
199 | 0 | break; |
200 | 0 | case MCSymbolRefExpr::VK_ARM_TARGET2: |
201 | 0 | Type = ELF::R_ARM_TARGET2; |
202 | 0 | break; |
203 | 0 | case MCSymbolRefExpr::VK_ARM_PREL31: |
204 | 0 | Type = ELF::R_ARM_PREL31; |
205 | 0 | break; |
206 | 0 | case MCSymbolRefExpr::VK_ARM_SBREL: |
207 | 0 | Type = ELF::R_ARM_SBREL32; |
208 | 0 | break; |
209 | 0 | case MCSymbolRefExpr::VK_ARM_TLSLDO: |
210 | 0 | Type = ELF::R_ARM_TLS_LDO32; |
211 | 0 | break; |
212 | 0 | case MCSymbolRefExpr::VK_ARM_TLSCALL: |
213 | 0 | Type = ELF::R_ARM_TLS_CALL; |
214 | 0 | break; |
215 | 0 | case MCSymbolRefExpr::VK_ARM_TLSDESC: |
216 | 0 | Type = ELF::R_ARM_TLS_GOTDESC; |
217 | 0 | break; |
218 | 0 | case MCSymbolRefExpr::VK_ARM_TLSDESCSEQ: |
219 | 0 | Type = ELF::R_ARM_TLS_DESCSEQ; |
220 | 0 | break; |
221 | 54.0k | } |
222 | 54.0k | break; |
223 | 54.0k | case ARM::fixup_arm_ldst_pcrel_12: |
224 | 0 | case ARM::fixup_arm_pcrel_10: |
225 | 0 | case ARM::fixup_arm_adr_pcrel_12: |
226 | 0 | case ARM::fixup_arm_thumb_bl: |
227 | 0 | case ARM::fixup_arm_thumb_cb: |
228 | 0 | case ARM::fixup_arm_thumb_cp: |
229 | 0 | case ARM::fixup_arm_thumb_br: |
230 | 0 | llvm_unreachable("Unimplemented"); |
231 | 0 | case ARM::fixup_arm_condbranch: |
232 | 0 | case ARM::fixup_arm_uncondbranch: |
233 | 0 | Type = ELF::R_ARM_JUMP24; |
234 | 0 | break; |
235 | 0 | case ARM::fixup_arm_movt_hi16: |
236 | 0 | Type = ELF::R_ARM_MOVT_ABS; |
237 | 0 | break; |
238 | 0 | case ARM::fixup_arm_movw_lo16: |
239 | 0 | Type = ELF::R_ARM_MOVW_ABS_NC; |
240 | 0 | break; |
241 | 0 | case ARM::fixup_t2_movt_hi16: |
242 | 0 | Type = ELF::R_ARM_THM_MOVT_ABS; |
243 | 0 | break; |
244 | 0 | case ARM::fixup_t2_movw_lo16: |
245 | 0 | Type = ELF::R_ARM_THM_MOVW_ABS_NC; |
246 | 0 | break; |
247 | 54.6k | } |
248 | 54.6k | } |
249 | | |
250 | 59.2k | return Type; |
251 | 59.2k | } |
252 | | |
253 | | MCObjectWriter *llvm_ks::createARMELFObjectWriter(raw_pwrite_stream &OS, |
254 | | uint8_t OSABI, |
255 | 61.7k | bool IsLittleEndian) { |
256 | 61.7k | MCELFObjectTargetWriter *MOTW = new ARMELFObjectWriter(OSABI); |
257 | 61.7k | return createELFObjectWriter(MOTW, OS, IsLittleEndian); |
258 | 61.7k | } |