1 //===-- ARMWinCOFFObjectWriter.cpp - ARM 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 "MCTargetDesc/ARMFixupKinds.h" 10 #include "MCTargetDesc/ARMMCAsmInfo.h" 11 #include "llvm/ADT/Twine.h" 12 #include "llvm/BinaryFormat/COFF.h" 13 #include "llvm/MC/MCAsmBackend.h" 14 #include "llvm/MC/MCContext.h" 15 #include "llvm/MC/MCExpr.h" 16 #include "llvm/MC/MCFixup.h" 17 #include "llvm/MC/MCObjectWriter.h" 18 #include "llvm/MC/MCValue.h" 19 #include "llvm/MC/MCWinCOFFObjectWriter.h" 20 #include "llvm/Support/ErrorHandling.h" 21 22 using namespace llvm; 23 24 namespace { 25 26 class ARMWinCOFFObjectWriter : public MCWinCOFFObjectTargetWriter { 27 public: 28 ARMWinCOFFObjectWriter() 29 : MCWinCOFFObjectTargetWriter(COFF::IMAGE_FILE_MACHINE_ARMNT) { 30 } 31 32 ~ARMWinCOFFObjectWriter() override = default; 33 34 unsigned getRelocType(MCContext &Ctx, const MCValue &Target, 35 const MCFixup &Fixup, bool IsCrossSection, 36 const MCAsmBackend &MAB) const override; 37 38 bool recordRelocation(const MCFixup &) const override; 39 }; 40 41 } // end anonymous namespace 42 43 unsigned ARMWinCOFFObjectWriter::getRelocType(MCContext &Ctx, 44 const MCValue &Target, 45 const MCFixup &Fixup, 46 bool IsCrossSection, 47 const MCAsmBackend &MAB) const { 48 auto Spec = Target.getSpecifier(); 49 unsigned FixupKind = Fixup.getKind(); 50 bool PCRel = false; 51 if (IsCrossSection) { 52 if (PCRel || FixupKind != FK_Data_4) { 53 Ctx.reportError(Fixup.getLoc(), "Cannot represent this expression"); 54 return COFF::IMAGE_REL_ARM_ADDR32; 55 } 56 FixupKind = FK_Data_4; 57 PCRel = true; 58 } 59 60 61 switch (FixupKind) { 62 default: { 63 Ctx.reportError(Fixup.getLoc(), "unsupported relocation type"); 64 return COFF::IMAGE_REL_ARM_ABSOLUTE; 65 } 66 case FK_Data_4: 67 if (PCRel) 68 return COFF::IMAGE_REL_ARM_REL32; 69 switch (Spec) { 70 case MCSymbolRefExpr::VK_COFF_IMGREL32: 71 return COFF::IMAGE_REL_ARM_ADDR32NB; 72 case ARM::S_COFF_SECREL: 73 return COFF::IMAGE_REL_ARM_SECREL; 74 default: 75 return COFF::IMAGE_REL_ARM_ADDR32; 76 } 77 case FK_SecRel_2: 78 return COFF::IMAGE_REL_ARM_SECTION; 79 case FK_SecRel_4: 80 return COFF::IMAGE_REL_ARM_SECREL; 81 case ARM::fixup_t2_condbranch: 82 return COFF::IMAGE_REL_ARM_BRANCH20T; 83 case ARM::fixup_t2_uncondbranch: 84 case ARM::fixup_arm_thumb_bl: 85 return COFF::IMAGE_REL_ARM_BRANCH24T; 86 case ARM::fixup_arm_thumb_blx: 87 return COFF::IMAGE_REL_ARM_BLX23T; 88 case ARM::fixup_t2_movw_lo16: 89 case ARM::fixup_t2_movt_hi16: 90 return COFF::IMAGE_REL_ARM_MOV32T; 91 } 92 } 93 94 bool ARMWinCOFFObjectWriter::recordRelocation(const MCFixup &Fixup) const { 95 return static_cast<unsigned>(Fixup.getKind()) != ARM::fixup_t2_movt_hi16; 96 } 97 98 namespace llvm { 99 100 std::unique_ptr<MCObjectTargetWriter> 101 createARMWinCOFFObjectWriter() { 102 return std::make_unique<ARMWinCOFFObjectWriter>(); 103 } 104 105 } // end namespace llvm 106