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