Coverage Report

Created: 2024-01-17 10:31

/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
}