1 //= AArch64WinCOFFObjectWriter.cpp - AArch64 Windows COFF Object Writer C++ =//
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
7 //===---------------------------------------------------------------------===//
9 #include "AArch64MCTargetDesc.h"
10 #include "MCTargetDesc/AArch64FixupKinds.h"
11 #include "MCTargetDesc/AArch64MCExpr.h"
12 #include "llvm/ADT/Twine.h"
13 #include "llvm/BinaryFormat/COFF.h"
14 #include "llvm/MC/MCAsmBackend.h"
15 #include "llvm/MC/MCContext.h"
16 #include "llvm/MC/MCExpr.h"
17 #include "llvm/MC/MCFixup.h"
18 #include "llvm/MC/MCFixupKindInfo.h"
19 #include "llvm/MC/MCObjectWriter.h"
20 #include "llvm/MC/MCValue.h"
21 #include "llvm/MC/MCWinCOFFObjectWriter.h"
22 #include "llvm/Support/Casting.h"
23 #include "llvm/Support/ErrorHandling.h"
30 class AArch64WinCOFFObjectWriter
: public MCWinCOFFObjectTargetWriter
{
32 AArch64WinCOFFObjectWriter(const Triple
&TheTriple
)
33 : MCWinCOFFObjectTargetWriter(TheTriple
.isWindowsArm64EC()
34 ? COFF::IMAGE_FILE_MACHINE_ARM64EC
35 : COFF::IMAGE_FILE_MACHINE_ARM64
) {}
37 ~AArch64WinCOFFObjectWriter() override
= default;
39 unsigned getRelocType(MCContext
&Ctx
, const MCValue
&Target
,
40 const MCFixup
&Fixup
, bool IsCrossSection
,
41 const MCAsmBackend
&MAB
) const override
;
43 bool recordRelocation(const MCFixup
&) const override
;
46 } // end anonymous namespace
48 unsigned AArch64WinCOFFObjectWriter::getRelocType(
49 MCContext
&Ctx
, const MCValue
&Target
, const MCFixup
&Fixup
,
50 bool IsCrossSection
, const MCAsmBackend
&MAB
) const {
51 unsigned FixupKind
= Fixup
.getKind();
53 // IMAGE_REL_ARM64_REL64 does not exist. We treat FK_Data_8 as FK_PCRel_4 so
54 // that .xword a-b can lower to IMAGE_REL_ARM64_REL32. This allows generic
55 // instrumentation to not bother with the COFF limitation. A negative value
57 if (FixupKind
!= FK_Data_4
&& FixupKind
!= FK_Data_8
) {
58 Ctx
.reportError(Fixup
.getLoc(), "Cannot represent this expression");
59 return COFF::IMAGE_REL_ARM64_ADDR32
;
61 FixupKind
= FK_PCRel_4
;
64 auto Modifier
= Target
.isAbsolute() ? MCSymbolRefExpr::VK_None
65 : Target
.getSymA()->getKind();
66 const MCExpr
*Expr
= Fixup
.getValue();
68 if (const AArch64MCExpr
*A64E
= dyn_cast
<AArch64MCExpr
>(Expr
)) {
69 AArch64MCExpr::VariantKind RefKind
= A64E
->getKind();
70 switch (AArch64MCExpr::getSymbolLoc(RefKind
)) {
71 case AArch64MCExpr::VK_ABS
:
72 case AArch64MCExpr::VK_SECREL
:
76 Ctx
.reportError(Fixup
.getLoc(), "relocation variant " +
77 A64E
->getVariantKindName() +
78 " unsupported on COFF targets");
79 return COFF::IMAGE_REL_ARM64_ABSOLUTE
; // Dummy return value
85 if (const AArch64MCExpr
*A64E
= dyn_cast
<AArch64MCExpr
>(Expr
)) {
86 Ctx
.reportError(Fixup
.getLoc(), "relocation type " +
87 A64E
->getVariantKindName() +
88 " unsupported on COFF targets");
90 const MCFixupKindInfo
&Info
= MAB
.getFixupKindInfo(Fixup
.getKind());
91 Ctx
.reportError(Fixup
.getLoc(), Twine("relocation type ") + Info
.Name
+
92 " unsupported on COFF targets");
94 return COFF::IMAGE_REL_ARM64_ABSOLUTE
; // Dummy return value
98 return COFF::IMAGE_REL_ARM64_REL32
;
103 return COFF::IMAGE_REL_ARM64_ADDR32
;
104 case MCSymbolRefExpr::VK_COFF_IMGREL32
:
105 return COFF::IMAGE_REL_ARM64_ADDR32NB
;
106 case MCSymbolRefExpr::VK_SECREL
:
107 return COFF::IMAGE_REL_ARM64_SECREL
;
111 return COFF::IMAGE_REL_ARM64_ADDR64
;
114 return COFF::IMAGE_REL_ARM64_SECTION
;
117 return COFF::IMAGE_REL_ARM64_SECREL
;
119 case AArch64::fixup_aarch64_add_imm12
:
120 if (const AArch64MCExpr
*A64E
= dyn_cast
<AArch64MCExpr
>(Expr
)) {
121 AArch64MCExpr::VariantKind RefKind
= A64E
->getKind();
122 if (RefKind
== AArch64MCExpr::VK_SECREL_LO12
)
123 return COFF::IMAGE_REL_ARM64_SECREL_LOW12A
;
124 if (RefKind
== AArch64MCExpr::VK_SECREL_HI12
)
125 return COFF::IMAGE_REL_ARM64_SECREL_HIGH12A
;
127 return COFF::IMAGE_REL_ARM64_PAGEOFFSET_12A
;
129 case AArch64::fixup_aarch64_ldst_imm12_scale1
:
130 case AArch64::fixup_aarch64_ldst_imm12_scale2
:
131 case AArch64::fixup_aarch64_ldst_imm12_scale4
:
132 case AArch64::fixup_aarch64_ldst_imm12_scale8
:
133 case AArch64::fixup_aarch64_ldst_imm12_scale16
:
134 if (const AArch64MCExpr
*A64E
= dyn_cast
<AArch64MCExpr
>(Expr
)) {
135 AArch64MCExpr::VariantKind RefKind
= A64E
->getKind();
136 if (RefKind
== AArch64MCExpr::VK_SECREL_LO12
)
137 return COFF::IMAGE_REL_ARM64_SECREL_LOW12L
;
139 return COFF::IMAGE_REL_ARM64_PAGEOFFSET_12L
;
141 case AArch64::fixup_aarch64_pcrel_adr_imm21
:
142 return COFF::IMAGE_REL_ARM64_REL21
;
144 case AArch64::fixup_aarch64_pcrel_adrp_imm21
:
145 return COFF::IMAGE_REL_ARM64_PAGEBASE_REL21
;
147 case AArch64::fixup_aarch64_pcrel_branch14
:
148 return COFF::IMAGE_REL_ARM64_BRANCH14
;
150 case AArch64::fixup_aarch64_pcrel_branch19
:
151 return COFF::IMAGE_REL_ARM64_BRANCH19
;
153 case AArch64::fixup_aarch64_pcrel_branch26
:
154 case AArch64::fixup_aarch64_pcrel_call26
:
155 return COFF::IMAGE_REL_ARM64_BRANCH26
;
159 bool AArch64WinCOFFObjectWriter::recordRelocation(const MCFixup
&Fixup
) const {
163 std::unique_ptr
<MCObjectTargetWriter
>
164 llvm::createAArch64WinCOFFObjectWriter(const Triple
&TheTriple
) {
165 return std::make_unique
<AArch64WinCOFFObjectWriter
>(TheTriple
);