1//===-- X86WinCOFFObjectWriter.cpp - X86 Win COFF 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
9#include "MCTargetDesc/X86FixupKinds.h"
10#include "MCTargetDesc/X86MCTargetDesc.h"
11#include "llvm/BinaryFormat/COFF.h"
12#include "llvm/MC/MCContext.h"
13#include "llvm/MC/MCExpr.h"
14#include "llvm/MC/MCFixup.h"
15#include "llvm/MC/MCObjectWriter.h"
16#include "llvm/MC/MCValue.h"
17#include "llvm/MC/MCWinCOFFObjectWriter.h"
18#include "llvm/Support/ErrorHandling.h"
19
20using namespace llvm;
21
22namespace {
23
24class X86WinCOFFObjectWriter : public MCWinCOFFObjectTargetWriter {
25public:
26 X86WinCOFFObjectWriter(bool Is64Bit);
27 ~X86WinCOFFObjectWriter() override = default;
28
29 unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
30 const MCFixup &Fixup, bool IsCrossSection,
31 const MCAsmBackend &MAB) const override;
32};
33
34} // end anonymous namespace
35
36X86WinCOFFObjectWriter::X86WinCOFFObjectWriter(bool Is64Bit)
37 : MCWinCOFFObjectTargetWriter(Is64Bit ? COFF::IMAGE_FILE_MACHINE_AMD64
38 : COFF::IMAGE_FILE_MACHINE_I386) {}
39
40unsigned X86WinCOFFObjectWriter::getRelocType(MCContext &Ctx,
41 const MCValue &Target,
42 const MCFixup &Fixup,
43 bool IsCrossSection,
44 const MCAsmBackend &MAB) const {
45 const bool Is64Bit = getMachine() == COFF::IMAGE_FILE_MACHINE_AMD64;
46 unsigned FixupKind = Fixup.getKind();
47 if (IsCrossSection) {
48 // IMAGE_REL_AMD64_REL64 does not exist. We treat FK_Data_8 as FK_PCRel_4 so
49 // that .quad a-b can lower to IMAGE_REL_AMD64_REL32. This allows generic
50 // instrumentation to not bother with the COFF limitation. A negative value
51 // needs attention.
52 if (FixupKind == FK_Data_4 || FixupKind == llvm::X86::reloc_signed_4byte ||
53 (FixupKind == FK_Data_8 && Is64Bit)) {
54 FixupKind = FK_PCRel_4;
55 } else {
56 Ctx.reportError(L: Fixup.getLoc(), Msg: "Cannot represent this expression");
57 return COFF::IMAGE_REL_AMD64_ADDR32;
58 }
59 }
60
61 MCSymbolRefExpr::VariantKind Modifier = Target.isAbsolute() ?
62 MCSymbolRefExpr::VK_None : Target.getSymA()->getKind();
63
64 if (Is64Bit) {
65 switch (FixupKind) {
66 case FK_PCRel_4:
67 case X86::reloc_riprel_4byte:
68 case X86::reloc_riprel_4byte_movq_load:
69 case X86::reloc_riprel_4byte_relax:
70 case X86::reloc_riprel_4byte_relax_rex:
71 case X86::reloc_branch_4byte_pcrel:
72 return COFF::IMAGE_REL_AMD64_REL32;
73 case FK_Data_4:
74 case X86::reloc_signed_4byte:
75 case X86::reloc_signed_4byte_relax:
76 if (Modifier == MCSymbolRefExpr::VK_COFF_IMGREL32)
77 return COFF::IMAGE_REL_AMD64_ADDR32NB;
78 if (Modifier == MCSymbolRefExpr::VK_SECREL)
79 return COFF::IMAGE_REL_AMD64_SECREL;
80 return COFF::IMAGE_REL_AMD64_ADDR32;
81 case FK_Data_8:
82 return COFF::IMAGE_REL_AMD64_ADDR64;
83 case FK_SecRel_2:
84 return COFF::IMAGE_REL_AMD64_SECTION;
85 case FK_SecRel_4:
86 return COFF::IMAGE_REL_AMD64_SECREL;
87 default:
88 Ctx.reportError(L: Fixup.getLoc(), Msg: "unsupported relocation type");
89 return COFF::IMAGE_REL_AMD64_ADDR32;
90 }
91 } else if (getMachine() == COFF::IMAGE_FILE_MACHINE_I386) {
92 switch (FixupKind) {
93 case FK_PCRel_4:
94 case X86::reloc_riprel_4byte:
95 case X86::reloc_riprel_4byte_movq_load:
96 return COFF::IMAGE_REL_I386_REL32;
97 case FK_Data_4:
98 case X86::reloc_signed_4byte:
99 case X86::reloc_signed_4byte_relax:
100 if (Modifier == MCSymbolRefExpr::VK_COFF_IMGREL32)
101 return COFF::IMAGE_REL_I386_DIR32NB;
102 if (Modifier == MCSymbolRefExpr::VK_SECREL)
103 return COFF::IMAGE_REL_I386_SECREL;
104 return COFF::IMAGE_REL_I386_DIR32;
105 case FK_SecRel_2:
106 return COFF::IMAGE_REL_I386_SECTION;
107 case FK_SecRel_4:
108 return COFF::IMAGE_REL_I386_SECREL;
109 default:
110 Ctx.reportError(L: Fixup.getLoc(), Msg: "unsupported relocation type");
111 return COFF::IMAGE_REL_I386_DIR32;
112 }
113 } else
114 llvm_unreachable("Unsupported COFF machine type.");
115}
116
117std::unique_ptr<MCObjectTargetWriter>
118llvm::createX86WinCOFFObjectWriter(bool Is64Bit) {
119 return std::make_unique<X86WinCOFFObjectWriter>(args&: Is64Bit);
120}
121