/src/llvm-project/llvm/lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFObjectWriter.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //= AArch64WinCOFFObjectWriter.cpp - AArch64 Windows COFF Object Writer C++ =// |
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 "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" |
24 | | #include "llvm/Support/raw_ostream.h" |
25 | | #include <cassert> |
26 | | |
27 | | using namespace llvm; |
28 | | |
29 | | namespace { |
30 | | |
31 | | class AArch64WinCOFFObjectWriter : public MCWinCOFFObjectTargetWriter { |
32 | | public: |
33 | | AArch64WinCOFFObjectWriter(const Triple &TheTriple) |
34 | | : MCWinCOFFObjectTargetWriter(TheTriple.isWindowsArm64EC() |
35 | | ? COFF::IMAGE_FILE_MACHINE_ARM64EC |
36 | 0 | : COFF::IMAGE_FILE_MACHINE_ARM64) {} |
37 | | |
38 | | ~AArch64WinCOFFObjectWriter() override = default; |
39 | | |
40 | | unsigned getRelocType(MCContext &Ctx, const MCValue &Target, |
41 | | const MCFixup &Fixup, bool IsCrossSection, |
42 | | const MCAsmBackend &MAB) const override; |
43 | | |
44 | | bool recordRelocation(const MCFixup &) const override; |
45 | | }; |
46 | | |
47 | | } // end anonymous namespace |
48 | | |
49 | | unsigned AArch64WinCOFFObjectWriter::getRelocType( |
50 | | MCContext &Ctx, const MCValue &Target, const MCFixup &Fixup, |
51 | 0 | bool IsCrossSection, const MCAsmBackend &MAB) const { |
52 | 0 | unsigned FixupKind = Fixup.getKind(); |
53 | 0 | if (IsCrossSection) { |
54 | | // IMAGE_REL_ARM64_REL64 does not exist. We treat FK_Data_8 as FK_PCRel_4 so |
55 | | // that .xword a-b can lower to IMAGE_REL_ARM64_REL32. This allows generic |
56 | | // instrumentation to not bother with the COFF limitation. A negative value |
57 | | // needs attention. |
58 | 0 | if (FixupKind != FK_Data_4 && FixupKind != FK_Data_8) { |
59 | 0 | Ctx.reportError(Fixup.getLoc(), "Cannot represent this expression"); |
60 | 0 | return COFF::IMAGE_REL_ARM64_ADDR32; |
61 | 0 | } |
62 | 0 | FixupKind = FK_PCRel_4; |
63 | 0 | } |
64 | | |
65 | 0 | auto Modifier = Target.isAbsolute() ? MCSymbolRefExpr::VK_None |
66 | 0 | : Target.getSymA()->getKind(); |
67 | 0 | const MCExpr *Expr = Fixup.getValue(); |
68 | |
|
69 | 0 | if (const AArch64MCExpr *A64E = dyn_cast<AArch64MCExpr>(Expr)) { |
70 | 0 | AArch64MCExpr::VariantKind RefKind = A64E->getKind(); |
71 | 0 | switch (AArch64MCExpr::getSymbolLoc(RefKind)) { |
72 | 0 | case AArch64MCExpr::VK_ABS: |
73 | 0 | case AArch64MCExpr::VK_SECREL: |
74 | | // Supported |
75 | 0 | break; |
76 | 0 | default: |
77 | 0 | Ctx.reportError(Fixup.getLoc(), "relocation variant " + |
78 | 0 | A64E->getVariantKindName() + |
79 | 0 | " unsupported on COFF targets"); |
80 | 0 | return COFF::IMAGE_REL_ARM64_ABSOLUTE; // Dummy return value |
81 | 0 | } |
82 | 0 | } |
83 | | |
84 | 0 | switch (FixupKind) { |
85 | 0 | default: { |
86 | 0 | if (const AArch64MCExpr *A64E = dyn_cast<AArch64MCExpr>(Expr)) { |
87 | 0 | Ctx.reportError(Fixup.getLoc(), "relocation type " + |
88 | 0 | A64E->getVariantKindName() + |
89 | 0 | " unsupported on COFF targets"); |
90 | 0 | } else { |
91 | 0 | const MCFixupKindInfo &Info = MAB.getFixupKindInfo(Fixup.getKind()); |
92 | 0 | Ctx.reportError(Fixup.getLoc(), Twine("relocation type ") + Info.Name + |
93 | 0 | " unsupported on COFF targets"); |
94 | 0 | } |
95 | 0 | return COFF::IMAGE_REL_ARM64_ABSOLUTE; // Dummy return value |
96 | 0 | } |
97 | | |
98 | 0 | case FK_PCRel_4: |
99 | 0 | return COFF::IMAGE_REL_ARM64_REL32; |
100 | | |
101 | 0 | case FK_Data_4: |
102 | 0 | switch (Modifier) { |
103 | 0 | default: |
104 | 0 | return COFF::IMAGE_REL_ARM64_ADDR32; |
105 | 0 | case MCSymbolRefExpr::VK_COFF_IMGREL32: |
106 | 0 | return COFF::IMAGE_REL_ARM64_ADDR32NB; |
107 | 0 | case MCSymbolRefExpr::VK_SECREL: |
108 | 0 | return COFF::IMAGE_REL_ARM64_SECREL; |
109 | 0 | } |
110 | | |
111 | 0 | case FK_Data_8: |
112 | 0 | return COFF::IMAGE_REL_ARM64_ADDR64; |
113 | | |
114 | 0 | case FK_SecRel_2: |
115 | 0 | return COFF::IMAGE_REL_ARM64_SECTION; |
116 | | |
117 | 0 | case FK_SecRel_4: |
118 | 0 | return COFF::IMAGE_REL_ARM64_SECREL; |
119 | | |
120 | 0 | case AArch64::fixup_aarch64_add_imm12: |
121 | 0 | if (const AArch64MCExpr *A64E = dyn_cast<AArch64MCExpr>(Expr)) { |
122 | 0 | AArch64MCExpr::VariantKind RefKind = A64E->getKind(); |
123 | 0 | if (RefKind == AArch64MCExpr::VK_SECREL_LO12) |
124 | 0 | return COFF::IMAGE_REL_ARM64_SECREL_LOW12A; |
125 | 0 | if (RefKind == AArch64MCExpr::VK_SECREL_HI12) |
126 | 0 | return COFF::IMAGE_REL_ARM64_SECREL_HIGH12A; |
127 | 0 | } |
128 | 0 | return COFF::IMAGE_REL_ARM64_PAGEOFFSET_12A; |
129 | | |
130 | 0 | case AArch64::fixup_aarch64_ldst_imm12_scale1: |
131 | 0 | case AArch64::fixup_aarch64_ldst_imm12_scale2: |
132 | 0 | case AArch64::fixup_aarch64_ldst_imm12_scale4: |
133 | 0 | case AArch64::fixup_aarch64_ldst_imm12_scale8: |
134 | 0 | case AArch64::fixup_aarch64_ldst_imm12_scale16: |
135 | 0 | if (const AArch64MCExpr *A64E = dyn_cast<AArch64MCExpr>(Expr)) { |
136 | 0 | AArch64MCExpr::VariantKind RefKind = A64E->getKind(); |
137 | 0 | if (RefKind == AArch64MCExpr::VK_SECREL_LO12) |
138 | 0 | return COFF::IMAGE_REL_ARM64_SECREL_LOW12L; |
139 | 0 | } |
140 | 0 | return COFF::IMAGE_REL_ARM64_PAGEOFFSET_12L; |
141 | | |
142 | 0 | case AArch64::fixup_aarch64_pcrel_adr_imm21: |
143 | 0 | return COFF::IMAGE_REL_ARM64_REL21; |
144 | | |
145 | 0 | case AArch64::fixup_aarch64_pcrel_adrp_imm21: |
146 | 0 | return COFF::IMAGE_REL_ARM64_PAGEBASE_REL21; |
147 | | |
148 | 0 | case AArch64::fixup_aarch64_pcrel_branch14: |
149 | 0 | return COFF::IMAGE_REL_ARM64_BRANCH14; |
150 | | |
151 | 0 | case AArch64::fixup_aarch64_pcrel_branch19: |
152 | 0 | return COFF::IMAGE_REL_ARM64_BRANCH19; |
153 | | |
154 | 0 | case AArch64::fixup_aarch64_pcrel_branch26: |
155 | 0 | case AArch64::fixup_aarch64_pcrel_call26: |
156 | 0 | return COFF::IMAGE_REL_ARM64_BRANCH26; |
157 | 0 | } |
158 | 0 | } |
159 | | |
160 | 0 | bool AArch64WinCOFFObjectWriter::recordRelocation(const MCFixup &Fixup) const { |
161 | 0 | return true; |
162 | 0 | } |
163 | | |
164 | | std::unique_ptr<MCObjectTargetWriter> |
165 | 0 | llvm::createAArch64WinCOFFObjectWriter(const Triple &TheTriple) { |
166 | 0 | return std::make_unique<AArch64WinCOFFObjectWriter>(TheTriple); |
167 | 0 | } |