/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===-- ARMELFObjectWriter.cpp - ARM ELF Writer ---------------------------===// |
2 | | // |
3 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | | // See https://llvm.org/LICENSE.txt for license information. |
5 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | |
9 | | #include "MCTargetDesc/ARMFixupKinds.h" |
10 | | #include "MCTargetDesc/ARMMCTargetDesc.h" |
11 | | #include "llvm/BinaryFormat/ELF.h" |
12 | | #include "llvm/MC/MCContext.h" |
13 | | #include "llvm/MC/MCELFObjectWriter.h" |
14 | | #include "llvm/MC/MCExpr.h" |
15 | | #include "llvm/MC/MCFixup.h" |
16 | | #include "llvm/MC/MCObjectFileInfo.h" |
17 | | #include "llvm/MC/MCObjectWriter.h" |
18 | | #include "llvm/MC/MCValue.h" |
19 | | #include "llvm/Support/ErrorHandling.h" |
20 | | #include "llvm/Support/raw_ostream.h" |
21 | | #include <cstdint> |
22 | | |
23 | | using namespace llvm; |
24 | | |
25 | | namespace { |
26 | | |
27 | | class ARMELFObjectWriter : public MCELFObjectTargetWriter { |
28 | | enum { DefaultEABIVersion = 0x05000000U }; |
29 | | |
30 | | unsigned GetRelocTypeInner(const MCValue &Target, const MCFixup &Fixup, |
31 | | bool IsPCRel, MCContext &Ctx) const; |
32 | | |
33 | | public: |
34 | | ARMELFObjectWriter(uint8_t OSABI); |
35 | | |
36 | 3.38k | ~ARMELFObjectWriter() override = default; |
37 | | |
38 | | unsigned getRelocType(MCContext &Ctx, const MCValue &Target, |
39 | | const MCFixup &Fixup, bool IsPCRel) const override; |
40 | | |
41 | | bool needsRelocateWithSymbol(const MCSymbol &Sym, |
42 | | unsigned Type) const override; |
43 | | |
44 | | void addTargetSectionFlags(MCContext &Ctx, MCSectionELF &Sec) override; |
45 | | }; |
46 | | |
47 | | } // end anonymous namespace |
48 | | |
49 | | ARMELFObjectWriter::ARMELFObjectWriter(uint8_t OSABI) |
50 | | : MCELFObjectTargetWriter(/*Is64Bit*/ false, OSABI, |
51 | | ELF::EM_ARM, |
52 | 3.40k | /*HasRelocationAddend*/ false) {} |
53 | | |
54 | | bool ARMELFObjectWriter::needsRelocateWithSymbol(const MCSymbol &Sym, |
55 | 1.06k | unsigned Type) const { |
56 | 1.06k | // FIXME: This is extremely conservative. This really needs to use a |
57 | 1.06k | // whitelist with a clear explanation for why each realocation needs to |
58 | 1.06k | // point to the symbol, not to the section. |
59 | 1.06k | switch (Type) { |
60 | 1.06k | default: |
61 | 89 | return true; |
62 | 1.06k | |
63 | 1.06k | case ELF::R_ARM_PREL31: |
64 | 972 | case ELF::R_ARM_ABS32: |
65 | 972 | return false; |
66 | 1.06k | } |
67 | 1.06k | } |
68 | | |
69 | | // Need to examine the Fixup when determining whether to |
70 | | // emit the relocation as an explicit symbol or as a section relative |
71 | | // offset |
72 | | unsigned ARMELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target, |
73 | | const MCFixup &Fixup, |
74 | 2.57k | bool IsPCRel) const { |
75 | 2.57k | return GetRelocTypeInner(Target, Fixup, IsPCRel, Ctx); |
76 | 2.57k | } |
77 | | |
78 | | unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target, |
79 | | const MCFixup &Fixup, |
80 | | bool IsPCRel, |
81 | 2.57k | MCContext &Ctx) const { |
82 | 2.57k | MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant(); |
83 | 2.57k | |
84 | 2.57k | if (IsPCRel) { |
85 | 733 | switch ((unsigned)Fixup.getKind()) { |
86 | 733 | default: |
87 | 2 | Ctx.reportFatalError(Fixup.getLoc(), "unsupported relocation on symbol"); |
88 | 2 | return ELF::R_ARM_NONE; |
89 | 733 | case FK_Data_4: |
90 | 9 | switch (Modifier) { |
91 | 9 | default: |
92 | 0 | llvm_unreachable("Unsupported Modifier"); |
93 | 9 | case MCSymbolRefExpr::VK_None: |
94 | 5 | return ELF::R_ARM_REL32; |
95 | 9 | case MCSymbolRefExpr::VK_GOTTPOFF: |
96 | 0 | return ELF::R_ARM_TLS_IE32; |
97 | 9 | case MCSymbolRefExpr::VK_ARM_GOT_PREL: |
98 | 0 | return ELF::R_ARM_GOT_PREL; |
99 | 9 | case MCSymbolRefExpr::VK_ARM_PREL31: |
100 | 4 | return ELF::R_ARM_PREL31; |
101 | 0 | } |
102 | 239 | case ARM::fixup_arm_blx: |
103 | 239 | case ARM::fixup_arm_uncondbl: |
104 | 239 | switch (Modifier) { |
105 | 239 | case MCSymbolRefExpr::VK_PLT: |
106 | 2 | return ELF::R_ARM_CALL; |
107 | 239 | case MCSymbolRefExpr::VK_TLSCALL: |
108 | 0 | return ELF::R_ARM_TLS_CALL; |
109 | 239 | default: |
110 | 237 | return ELF::R_ARM_CALL; |
111 | 0 | } |
112 | 38 | case ARM::fixup_arm_condbl: |
113 | 38 | case ARM::fixup_arm_condbranch: |
114 | 38 | case ARM::fixup_arm_uncondbranch: |
115 | 38 | return ELF::R_ARM_JUMP24; |
116 | 38 | case ARM::fixup_t2_condbranch: |
117 | 21 | return ELF::R_ARM_THM_JUMP19; |
118 | 40 | case ARM::fixup_t2_uncondbranch: |
119 | 40 | return ELF::R_ARM_THM_JUMP24; |
120 | 38 | case ARM::fixup_arm_movt_hi16: |
121 | 8 | return ELF::R_ARM_MOVT_PREL; |
122 | 38 | case ARM::fixup_arm_movw_lo16: |
123 | 7 | return ELF::R_ARM_MOVW_PREL_NC; |
124 | 38 | case ARM::fixup_t2_movt_hi16: |
125 | 8 | return ELF::R_ARM_THM_MOVT_PREL; |
126 | 38 | case ARM::fixup_t2_movw_lo16: |
127 | 7 | return ELF::R_ARM_THM_MOVW_PREL_NC; |
128 | 38 | case ARM::fixup_arm_thumb_br: |
129 | 1 | return ELF::R_ARM_THM_JUMP11; |
130 | 38 | case ARM::fixup_arm_thumb_bcc: |
131 | 1 | return ELF::R_ARM_THM_JUMP8; |
132 | 352 | case ARM::fixup_arm_thumb_bl: |
133 | 352 | case ARM::fixup_arm_thumb_blx: |
134 | 352 | switch (Modifier) { |
135 | 352 | case MCSymbolRefExpr::VK_TLSCALL: |
136 | 0 | return ELF::R_ARM_THM_TLS_CALL; |
137 | 352 | default: |
138 | 352 | return ELF::R_ARM_THM_CALL; |
139 | 0 | } |
140 | 0 | case ARM::fixup_bf_target: |
141 | 0 | return ELF::R_ARM_THM_BF16; |
142 | 0 | case ARM::fixup_bfc_target: |
143 | 0 | return ELF::R_ARM_THM_BF12; |
144 | 0 | case ARM::fixup_bfl_target: |
145 | 0 | return ELF::R_ARM_THM_BF18; |
146 | 1.84k | } |
147 | 1.84k | } |
148 | 1.84k | switch ((unsigned)Fixup.getKind()) { |
149 | 1.84k | default: |
150 | 2 | Ctx.reportFatalError(Fixup.getLoc(), "unsupported relocation on symbol"); |
151 | 2 | return ELF::R_ARM_NONE; |
152 | 1.84k | case FK_NONE: |
153 | 7 | return ELF::R_ARM_NONE; |
154 | 1.84k | case FK_Data_1: |
155 | 4 | switch (Modifier) { |
156 | 4 | default: |
157 | 0 | llvm_unreachable("unsupported Modifier"); |
158 | 4 | case MCSymbolRefExpr::VK_None: |
159 | 4 | return ELF::R_ARM_ABS8; |
160 | 0 | } |
161 | 4 | case FK_Data_2: |
162 | 4 | switch (Modifier) { |
163 | 4 | default: |
164 | 0 | llvm_unreachable("unsupported modifier"); |
165 | 4 | case MCSymbolRefExpr::VK_None: |
166 | 4 | return ELF::R_ARM_ABS16; |
167 | 0 | } |
168 | 1.75k | case FK_Data_4: |
169 | 1.75k | switch (Modifier) { |
170 | 1.75k | default: |
171 | 0 | llvm_unreachable("Unsupported Modifier"); |
172 | 1.75k | case MCSymbolRefExpr::VK_ARM_NONE: |
173 | 460 | return ELF::R_ARM_NONE; |
174 | 1.75k | case MCSymbolRefExpr::VK_GOT: |
175 | 11 | return ELF::R_ARM_GOT_BREL; |
176 | 1.75k | case MCSymbolRefExpr::VK_TLSGD: |
177 | 17 | return ELF::R_ARM_TLS_GD32; |
178 | 1.75k | case MCSymbolRefExpr::VK_TPOFF: |
179 | 8 | return ELF::R_ARM_TLS_LE32; |
180 | 1.75k | case MCSymbolRefExpr::VK_GOTTPOFF: |
181 | 8 | return ELF::R_ARM_TLS_IE32; |
182 | 1.75k | case MCSymbolRefExpr::VK_None: |
183 | 304 | return ELF::R_ARM_ABS32; |
184 | 1.75k | case MCSymbolRefExpr::VK_GOTOFF: |
185 | 7 | return ELF::R_ARM_GOTOFF32; |
186 | 1.75k | case MCSymbolRefExpr::VK_ARM_GOT_PREL: |
187 | 5 | return ELF::R_ARM_GOT_PREL; |
188 | 1.75k | case MCSymbolRefExpr::VK_ARM_TARGET1: |
189 | 7 | return ELF::R_ARM_TARGET1; |
190 | 1.75k | case MCSymbolRefExpr::VK_ARM_TARGET2: |
191 | 5 | return ELF::R_ARM_TARGET2; |
192 | 1.75k | case MCSymbolRefExpr::VK_ARM_PREL31: |
193 | 892 | return ELF::R_ARM_PREL31; |
194 | 1.75k | case MCSymbolRefExpr::VK_ARM_SBREL: |
195 | 8 | return ELF::R_ARM_SBREL32; |
196 | 1.75k | case MCSymbolRefExpr::VK_ARM_TLSLDO: |
197 | 8 | return ELF::R_ARM_TLS_LDO32; |
198 | 1.75k | case MCSymbolRefExpr::VK_TLSCALL: |
199 | 4 | return ELF::R_ARM_TLS_CALL; |
200 | 1.75k | case MCSymbolRefExpr::VK_TLSDESC: |
201 | 5 | return ELF::R_ARM_TLS_GOTDESC; |
202 | 1.75k | case MCSymbolRefExpr::VK_TLSLDM: |
203 | 6 | return ELF::R_ARM_TLS_LDM32; |
204 | 1.75k | case MCSymbolRefExpr::VK_ARM_TLSDESCSEQ: |
205 | 3 | return ELF::R_ARM_TLS_DESCSEQ; |
206 | 0 | } |
207 | 0 | case ARM::fixup_arm_condbranch: |
208 | 0 | case ARM::fixup_arm_uncondbranch: |
209 | 0 | return ELF::R_ARM_JUMP24; |
210 | 19 | case ARM::fixup_arm_movt_hi16: |
211 | 19 | switch (Modifier) { |
212 | 19 | default: |
213 | 0 | llvm_unreachable("Unsupported Modifier"); |
214 | 19 | case MCSymbolRefExpr::VK_None: |
215 | 19 | return ELF::R_ARM_MOVT_ABS; |
216 | 19 | case MCSymbolRefExpr::VK_ARM_SBREL: |
217 | 0 | return ELF::R_ARM_MOVT_BREL; |
218 | 0 | } |
219 | 22 | case ARM::fixup_arm_movw_lo16: |
220 | 22 | switch (Modifier) { |
221 | 22 | default: |
222 | 0 | llvm_unreachable("Unsupported Modifier"); |
223 | 22 | case MCSymbolRefExpr::VK_None: |
224 | 22 | return ELF::R_ARM_MOVW_ABS_NC; |
225 | 22 | case MCSymbolRefExpr::VK_ARM_SBREL: |
226 | 0 | return ELF::R_ARM_MOVW_BREL_NC; |
227 | 0 | } |
228 | 12 | case ARM::fixup_t2_movt_hi16: |
229 | 12 | switch (Modifier) { |
230 | 12 | default: |
231 | 0 | llvm_unreachable("Unsupported Modifier"); |
232 | 12 | case MCSymbolRefExpr::VK_None: |
233 | 12 | return ELF::R_ARM_THM_MOVT_ABS; |
234 | 12 | case MCSymbolRefExpr::VK_ARM_SBREL: |
235 | 0 | return ELF::R_ARM_THM_MOVT_BREL; |
236 | 0 | } |
237 | 13 | case ARM::fixup_t2_movw_lo16: |
238 | 13 | switch (Modifier) { |
239 | 13 | default: |
240 | 0 | llvm_unreachable("Unsupported Modifier"); |
241 | 13 | case MCSymbolRefExpr::VK_None: |
242 | 13 | return ELF::R_ARM_THM_MOVW_ABS_NC; |
243 | 13 | case MCSymbolRefExpr::VK_ARM_SBREL: |
244 | 0 | return ELF::R_ARM_THM_MOVW_BREL_NC; |
245 | 13 | } |
246 | 1.84k | } |
247 | 1.84k | } |
248 | | |
249 | | void ARMELFObjectWriter::addTargetSectionFlags(MCContext &Ctx, |
250 | 1.76k | MCSectionELF &Sec) { |
251 | 1.76k | // The mix of execute-only and non-execute-only at link time is |
252 | 1.76k | // non-execute-only. To avoid the empty implicitly created .text |
253 | 1.76k | // section from making the whole .text section non-execute-only, we |
254 | 1.76k | // mark it execute-only if it is empty and there is at least one |
255 | 1.76k | // execute-only section in the object. |
256 | 1.76k | MCSectionELF *TextSection = |
257 | 1.76k | static_cast<MCSectionELF *>(Ctx.getObjectFileInfo()->getTextSection()); |
258 | 1.76k | if (Sec.getKind().isExecuteOnly() && !TextSection->hasInstructions()7 && |
259 | 1.76k | !TextSection->hasData()2 ) { |
260 | 1 | TextSection->setFlags(TextSection->getFlags() | ELF::SHF_ARM_PURECODE); |
261 | 1 | } |
262 | 1.76k | } |
263 | | |
264 | | std::unique_ptr<MCObjectTargetWriter> |
265 | 3.40k | llvm::createARMELFObjectWriter(uint8_t OSABI) { |
266 | 3.40k | return llvm::make_unique<ARMELFObjectWriter>(OSABI); |
267 | 3.40k | } |