1 //= AArch64WinCOFFObjectWriter.cpp - AArch64 Windows COFF Object Writer C++ =//
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/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/MCExpr.h"
16 #include "llvm/MC/MCFixup.h"
17 #include "llvm/MC/MCFixupKindInfo.h"
18 #include "llvm/MC/MCObjectWriter.h"
19 #include "llvm/MC/MCValue.h"
20 #include "llvm/MC/MCWinCOFFObjectWriter.h"
21 #include "llvm/Support/ErrorHandling.h"
22 #include "llvm/Support/raw_ostream.h"
23 #include <cassert>
24
25 using namespace llvm;
26
27 namespace {
28
29 class AArch64WinCOFFObjectWriter : public MCWinCOFFObjectTargetWriter {
30 public:
AArch64WinCOFFObjectWriter()31 AArch64WinCOFFObjectWriter()
32 : MCWinCOFFObjectTargetWriter(COFF::IMAGE_FILE_MACHINE_ARM64) {}
33
34 ~AArch64WinCOFFObjectWriter() override = default;
35
36 unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
37 const MCFixup &Fixup, bool IsCrossSection,
38 const MCAsmBackend &MAB) const override;
39
40 bool recordRelocation(const MCFixup &) const override;
41 };
42
43 } // end anonymous namespace
44
getRelocType(MCContext & Ctx,const MCValue & Target,const MCFixup & Fixup,bool IsCrossSection,const MCAsmBackend & MAB) const45 unsigned AArch64WinCOFFObjectWriter::getRelocType(
46 MCContext &Ctx, const MCValue &Target, const MCFixup &Fixup,
47 bool IsCrossSection, const MCAsmBackend &MAB) const {
48 auto Modifier = Target.isAbsolute() ? MCSymbolRefExpr::VK_None
49 : Target.getSymA()->getKind();
50 const MCExpr *Expr = Fixup.getValue();
51
52 switch (static_cast<unsigned>(Fixup.getKind())) {
53 default: {
54 const MCFixupKindInfo &Info = MAB.getFixupKindInfo(Fixup.getKind());
55 report_fatal_error(Twine("unsupported relocation type: ") + Info.Name);
56 }
57
58 case FK_Data_4:
59 switch (Modifier) {
60 default:
61 return COFF::IMAGE_REL_ARM64_ADDR32;
62 case MCSymbolRefExpr::VK_COFF_IMGREL32:
63 return COFF::IMAGE_REL_ARM64_ADDR32NB;
64 case MCSymbolRefExpr::VK_SECREL:
65 return COFF::IMAGE_REL_ARM64_SECREL;
66 }
67
68 case FK_Data_8:
69 return COFF::IMAGE_REL_ARM64_ADDR64;
70
71 case FK_SecRel_2:
72 return COFF::IMAGE_REL_ARM64_SECTION;
73
74 case FK_SecRel_4:
75 return COFF::IMAGE_REL_ARM64_SECREL;
76
77 case AArch64::fixup_aarch64_add_imm12:
78 if (const AArch64MCExpr *A64E = dyn_cast<AArch64MCExpr>(Expr)) {
79 AArch64MCExpr::VariantKind RefKind = A64E->getKind();
80 if (RefKind == AArch64MCExpr::VK_SECREL_LO12)
81 return COFF::IMAGE_REL_ARM64_SECREL_LOW12A;
82 if (RefKind == AArch64MCExpr::VK_SECREL_HI12)
83 return COFF::IMAGE_REL_ARM64_SECREL_HIGH12A;
84 }
85 return COFF::IMAGE_REL_ARM64_PAGEOFFSET_12A;
86
87 case AArch64::fixup_aarch64_ldst_imm12_scale1:
88 case AArch64::fixup_aarch64_ldst_imm12_scale2:
89 case AArch64::fixup_aarch64_ldst_imm12_scale4:
90 case AArch64::fixup_aarch64_ldst_imm12_scale8:
91 case AArch64::fixup_aarch64_ldst_imm12_scale16:
92 if (const AArch64MCExpr *A64E = dyn_cast<AArch64MCExpr>(Expr)) {
93 AArch64MCExpr::VariantKind RefKind = A64E->getKind();
94 if (RefKind == AArch64MCExpr::VK_SECREL_LO12)
95 return COFF::IMAGE_REL_ARM64_SECREL_LOW12L;
96 }
97 return COFF::IMAGE_REL_ARM64_PAGEOFFSET_12L;
98
99 case AArch64::fixup_aarch64_pcrel_adr_imm21:
100 return COFF::IMAGE_REL_ARM64_REL21;
101
102 case AArch64::fixup_aarch64_pcrel_adrp_imm21:
103 return COFF::IMAGE_REL_ARM64_PAGEBASE_REL21;
104
105 case AArch64::fixup_aarch64_pcrel_branch14:
106 return COFF::IMAGE_REL_ARM64_BRANCH14;
107
108 case AArch64::fixup_aarch64_pcrel_branch19:
109 return COFF::IMAGE_REL_ARM64_BRANCH19;
110
111 case AArch64::fixup_aarch64_pcrel_branch26:
112 case AArch64::fixup_aarch64_pcrel_call26:
113 return COFF::IMAGE_REL_ARM64_BRANCH26;
114 }
115 }
116
recordRelocation(const MCFixup & Fixup) const117 bool AArch64WinCOFFObjectWriter::recordRelocation(const MCFixup &Fixup) const {
118 return true;
119 }
120
121 namespace llvm {
122
createAArch64WinCOFFObjectWriter()123 std::unique_ptr<MCObjectTargetWriter> createAArch64WinCOFFObjectWriter() {
124 return llvm::make_unique<AArch64WinCOFFObjectWriter>();
125 }
126
127 } // end namespace llvm
128