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 20 using namespace llvm; 21 22 namespace { 23 24 class X86WinCOFFObjectWriter : public MCWinCOFFObjectTargetWriter { 25 public: 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 36 X86WinCOFFObjectWriter::X86WinCOFFObjectWriter(bool Is64Bit) 37 : MCWinCOFFObjectTargetWriter(Is64Bit ? COFF::IMAGE_FILE_MACHINE_AMD64 38 : COFF::IMAGE_FILE_MACHINE_I386) {} 39 40 unsigned 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(Fixup.getLoc(), "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(Fixup.getLoc(), "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(Fixup.getLoc(), "unsupported relocation type"); 111 return COFF::IMAGE_REL_I386_DIR32; 112 } 113 } else 114 llvm_unreachable("Unsupported COFF machine type."); 115 } 116 117 std::unique_ptr<MCObjectTargetWriter> 118 llvm::createX86WinCOFFObjectWriter(bool Is64Bit) { 119 return std::make_unique<X86WinCOFFObjectWriter>(Is64Bit); 120 } 121