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