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