LLVM 19.0.0git
ARMELFObjectWriter.cpp
Go to the documentation of this file.
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
12#include "llvm/MC/MCContext.h"
14#include "llvm/MC/MCExpr.h"
15#include "llvm/MC/MCFixup.h"
18#include "llvm/MC/MCValue.h"
19#include "llvm/Object/ELF.h"
22#include <cstdint>
23
24using namespace llvm;
25
26namespace {
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 ~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 MCValue &Val, const MCSymbol &Sym,
43 unsigned Type) const override;
44
45 void addTargetSectionFlags(MCContext &Ctx, MCSectionELF &Sec) override;
46 };
47
48} // end anonymous namespace
49
50ARMELFObjectWriter::ARMELFObjectWriter(uint8_t OSABI)
51 : MCELFObjectTargetWriter(/*Is64Bit*/ false, OSABI,
52 ELF::EM_ARM,
53 /*HasRelocationAddend*/ false) {}
54
55bool ARMELFObjectWriter::needsRelocateWithSymbol(const MCValue &,
56 const MCSymbol &,
57 unsigned Type) const {
58 // FIXME: This is extremely conservative. This really needs to use an
59 // explicit list with a clear explanation for why each realocation needs to
60 // point to the symbol, not to the section.
61 switch (Type) {
62 default:
63 return true;
64
65 case ELF::R_ARM_PREL31:
66 case ELF::R_ARM_ABS32:
67 return false;
68 }
69}
70
71// Need to examine the Fixup when determining whether to
72// emit the relocation as an explicit symbol or as a section relative
73// offset
74unsigned ARMELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target,
75 const MCFixup &Fixup,
76 bool IsPCRel) const {
77 return GetRelocTypeInner(Target, Fixup, IsPCRel, Ctx);
78}
79
80unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target,
81 const MCFixup &Fixup,
82 bool IsPCRel,
83 MCContext &Ctx) const {
84 unsigned Kind = Fixup.getTargetKind();
87 MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant();
88 auto CheckFDPIC = [&](uint32_t Type) {
89 if (getOSABI() != ELF::ELFOSABI_ARM_FDPIC)
90 Ctx.reportError(Fixup.getLoc(),
91 "relocation " +
93 " only supported in FDPIC mode");
94 return Type;
95 };
96
97 if (IsPCRel) {
98 switch (Fixup.getTargetKind()) {
99 default:
100 Ctx.reportError(Fixup.getLoc(), "unsupported relocation type");
101 return ELF::R_ARM_NONE;
102 case FK_Data_4:
103 switch (Modifier) {
104 default:
105 Ctx.reportError(Fixup.getLoc(),
106 "invalid fixup for 4-byte pc-relative data relocation");
107 return ELF::R_ARM_NONE;
109 if (const MCSymbolRefExpr *SymRef = Target.getSymA()) {
110 // For GNU AS compatibility expressions such as
111 // _GLOBAL_OFFSET_TABLE_ - label emit a R_ARM_BASE_PREL relocation.
112 if (SymRef->getSymbol().getName() == "_GLOBAL_OFFSET_TABLE_")
113 return ELF::R_ARM_BASE_PREL;
114 }
115 return ELF::R_ARM_REL32;
116 }
118 return ELF::R_ARM_TLS_IE32;
120 return ELF::R_ARM_GOT_PREL;
122 return ELF::R_ARM_PREL31;
123 }
126 switch (Modifier) {
128 return ELF::R_ARM_CALL;
130 return ELF::R_ARM_TLS_CALL;
131 default:
132 return ELF::R_ARM_CALL;
133 }
137 return ELF::R_ARM_JUMP24;
139 return ELF::R_ARM_THM_JUMP19;
141 return ELF::R_ARM_THM_JUMP24;
143 return ELF::R_ARM_MOVT_PREL;
145 return ELF::R_ARM_MOVW_PREL_NC;
147 return ELF::R_ARM_THM_MOVT_PREL;
149 return ELF::R_ARM_THM_MOVW_PREL_NC;
151 return ELF::R_ARM_THM_ALU_ABS_G3;
153 return ELF::R_ARM_THM_ALU_ABS_G2_NC;
155 return ELF::R_ARM_THM_ALU_ABS_G1_NC;
157 return ELF::R_ARM_THM_ALU_ABS_G0_NC;
159 return ELF::R_ARM_THM_JUMP11;
161 return ELF::R_ARM_THM_JUMP8;
164 switch (Modifier) {
166 return ELF::R_ARM_THM_TLS_CALL;
167 default:
168 return ELF::R_ARM_THM_CALL;
169 }
171 return ELF::R_ARM_LDR_PC_G0;
173 return ELF::R_ARM_LDRS_PC_G0;
175 return ELF::R_ARM_THM_PC12;
177 return ELF::R_ARM_ALU_PC_G0;
179 return ELF::R_ARM_THM_PC8;
181 return ELF::R_ARM_THM_ALU_PREL_11_0;
183 return ELF::R_ARM_THM_BF16;
185 return ELF::R_ARM_THM_BF12;
187 return ELF::R_ARM_THM_BF18;
188 }
189 }
190 switch (Kind) {
191 default:
192 Ctx.reportError(Fixup.getLoc(), "unsupported relocation type");
193 return ELF::R_ARM_NONE;
194 case FK_Data_1:
195 switch (Modifier) {
196 default:
197 Ctx.reportError(Fixup.getLoc(),
198 "invalid fixup for 1-byte data relocation");
199 return ELF::R_ARM_NONE;
201 return ELF::R_ARM_ABS8;
202 }
203 case FK_Data_2:
204 switch (Modifier) {
205 default:
206 Ctx.reportError(Fixup.getLoc(),
207 "invalid fixup for 2-byte data relocation");
208 return ELF::R_ARM_NONE;
210 return ELF::R_ARM_ABS16;
211 }
212 case FK_Data_4:
213 switch (Modifier) {
214 default:
215 Ctx.reportError(Fixup.getLoc(),
216 "invalid fixup for 4-byte data relocation");
217 return ELF::R_ARM_NONE;
219 return ELF::R_ARM_NONE;
221 return ELF::R_ARM_GOT_BREL;
223 return ELF::R_ARM_TLS_GD32;
225 return ELF::R_ARM_TLS_LE32;
227 return ELF::R_ARM_TLS_IE32;
229 return ELF::R_ARM_ABS32;
231 return ELF::R_ARM_GOTOFF32;
233 return ELF::R_ARM_GOT_PREL;
235 return ELF::R_ARM_TARGET1;
237 return ELF::R_ARM_TARGET2;
239 return ELF::R_ARM_PREL31;
241 return ELF::R_ARM_SBREL32;
243 return ELF::R_ARM_TLS_LDO32;
245 return ELF::R_ARM_TLS_CALL;
247 return ELF::R_ARM_TLS_GOTDESC;
249 return ELF::R_ARM_TLS_LDM32;
251 return ELF::R_ARM_TLS_DESCSEQ;
253 return CheckFDPIC(ELF::R_ARM_FUNCDESC);
255 return CheckFDPIC(ELF::R_ARM_GOTFUNCDESC);
257 return CheckFDPIC(ELF::R_ARM_GOTOFFFUNCDESC);
259 return CheckFDPIC(ELF::R_ARM_TLS_GD32_FDPIC);
261 return CheckFDPIC(ELF::R_ARM_TLS_LDM32_FDPIC);
263 return CheckFDPIC(ELF::R_ARM_TLS_IE32_FDPIC);
264 }
267 return ELF::R_ARM_JUMP24;
269 switch (Modifier) {
270 default:
271 Ctx.reportError(Fixup.getLoc(), "invalid fixup for ARM MOVT instruction");
272 return ELF::R_ARM_NONE;
274 return ELF::R_ARM_MOVT_ABS;
276 return ELF::R_ARM_MOVT_BREL;
277 }
279 switch (Modifier) {
280 default:
281 Ctx.reportError(Fixup.getLoc(), "invalid fixup for ARM MOVW instruction");
282 return ELF::R_ARM_NONE;
284 return ELF::R_ARM_MOVW_ABS_NC;
286 return ELF::R_ARM_MOVW_BREL_NC;
287 }
289 switch (Modifier) {
290 default:
291 Ctx.reportError(Fixup.getLoc(),
292 "invalid fixup for Thumb MOVT instruction");
293 return ELF::R_ARM_NONE;
295 return ELF::R_ARM_THM_MOVT_ABS;
297 return ELF::R_ARM_THM_MOVT_BREL;
298 }
300 switch (Modifier) {
301 default:
302 Ctx.reportError(Fixup.getLoc(),
303 "invalid fixup for Thumb MOVW instruction");
304 return ELF::R_ARM_NONE;
306 return ELF::R_ARM_THM_MOVW_ABS_NC;
308 return ELF::R_ARM_THM_MOVW_BREL_NC;
309 }
310
312 return ELF::R_ARM_THM_ALU_ABS_G3;
314 return ELF::R_ARM_THM_ALU_ABS_G2_NC;
316 return ELF::R_ARM_THM_ALU_ABS_G1_NC;
318 return ELF::R_ARM_THM_ALU_ABS_G0_NC;
319 }
320}
321
322void ARMELFObjectWriter::addTargetSectionFlags(MCContext &Ctx,
323 MCSectionELF &Sec) {
324 // The mix of execute-only and non-execute-only at link time is
325 // non-execute-only. To avoid the empty implicitly created .text
326 // section from making the whole .text section non-execute-only, we
327 // mark it execute-only if it is empty and there is at least one
328 // execute-only section in the object.
329 MCSectionELF *TextSection =
330 static_cast<MCSectionELF *>(Ctx.getObjectFileInfo()->getTextSection());
331 if (Sec.getKind().isExecuteOnly() && !TextSection->hasInstructions()) {
332 for (auto &F : TextSection->getFragmentList())
333 if (auto *DF = dyn_cast<MCDataFragment>(&F))
334 if (!DF->getContents().empty())
335 return;
336 TextSection->setFlags(TextSection->getFlags() | ELF::SHF_ARM_PURECODE);
337 }
338}
339
340std::unique_ptr<MCObjectTargetWriter>
342 return std::make_unique<ARMELFObjectWriter>(OSABI);
343}
static RegisterPass< DebugifyFunctionPass > DF("debugify-function", "Attach debug info to a function")
Symbol * Sym
Definition: ELF_riscv.cpp:479
#define F(x, y, z)
Definition: MD5.cpp:55
PowerPC TLS Dynamic Call Fixup
Context object for machine code objects.
Definition: MCContext.h:76
const MCObjectFileInfo * getObjectFileInfo() const
Definition: MCContext.h:450
void reportError(SMLoc L, const Twine &Msg)
Definition: MCContext.cpp:1064
virtual bool needsRelocateWithSymbol(const MCValue &Val, const MCSymbol &Sym, unsigned Type) const
virtual unsigned getRelocType(MCContext &Ctx, const MCValue &Target, const MCFixup &Fixup, bool IsPCRel) const =0
virtual void addTargetSectionFlags(MCContext &Ctx, MCSectionELF &Sec)
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
Definition: MCFixup.h:71
MCSection * getTextSection() const
This represents a section on linux, lots of unix variants and some bare metal systems.
Definition: MCSectionELF.h:26
unsigned getFlags() const
Definition: MCSectionELF.h:73
void setFlags(unsigned F)
Definition: MCSectionELF.h:75
MCSection::FragmentListType & getFragmentList()
Definition: MCSection.h:172
bool hasInstructions() const
Definition: MCSection.h:166
SectionKind getKind() const
Definition: MCSection.h:125
Represent a reference to a symbol from inside an expression.
Definition: MCExpr.h:192
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:40
This represents an "assembler immediate".
Definition: MCValue.h:36
bool isExecuteOnly() const
Definition: SectionKind.h:129
Target - Wrapper for Target specific information.
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
@ fixup_arm_thumb_br
Definition: ARMFixupKinds.h:60
@ fixup_thumb_adr_pcrel_10
Definition: ARMFixupKinds.h:43
@ fixup_arm_thumb_upper_8_15
@ fixup_arm_adr_pcrel_12
Definition: ARMFixupKinds.h:45
@ fixup_arm_uncondbranch
Definition: ARMFixupKinds.h:51
@ fixup_arm_movw_lo16
Definition: ARMFixupKinds.h:98
@ fixup_t2_movt_hi16
Definition: ARMFixupKinds.h:99
@ fixup_t2_ldst_pcrel_12
Definition: ARMFixupKinds.h:21
@ fixup_arm_thumb_lower_0_7
@ fixup_arm_movt_hi16
Definition: ARMFixupKinds.h:97
@ fixup_arm_thumb_blx
Definition: ARMFixupKinds.h:84
@ fixup_t2_uncondbranch
Definition: ARMFixupKinds.h:57
@ fixup_arm_uncondbl
Definition: ARMFixupKinds.h:72
@ fixup_arm_pcrel_10_unscaled
Definition: ARMFixupKinds.h:25
@ fixup_arm_thumb_bcc
Definition: ARMFixupKinds.h:93
@ fixup_arm_thumb_upper_0_7
@ fixup_t2_adr_pcrel_12
Definition: ARMFixupKinds.h:47
@ fixup_t2_condbranch
Definition: ARMFixupKinds.h:54
@ fixup_arm_condbl
Definition: ARMFixupKinds.h:75
@ fixup_arm_ldst_pcrel_12
Definition: ARMFixupKinds.h:18
@ fixup_arm_thumb_lower_8_15
@ fixup_arm_thumb_bl
Definition: ARMFixupKinds.h:81
@ fixup_t2_movw_lo16
@ fixup_arm_condbranch
Definition: ARMFixupKinds.h:49
@ SHF_ARM_PURECODE
Definition: ELF.h:1252
@ EM_ARM
Definition: ELF.h:156
@ ELFOSABI_ARM_FDPIC
Definition: ELF.h:365
StringRef getELFRelocationTypeName(uint32_t Machine, uint32_t Type)
Definition: ELF.cpp:23
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ FirstLiteralRelocationKind
The range [FirstLiteralRelocationKind, MaxTargetFixupKind) is used for relocations coming from ....
Definition: MCFixup.h:50
@ FK_Data_1
A one-byte fixup.
Definition: MCFixup.h:23
@ FK_Data_4
A four-byte fixup.
Definition: MCFixup.h:25
@ FK_Data_2
A two-byte fixup.
Definition: MCFixup.h:24
std::unique_ptr< MCObjectTargetWriter > createARMELFObjectWriter(uint8_t OSABI)
Construct an ELF Mach-O object writer.