10b57cec5SDimitry Andric //===-- ARMWinCOFFObjectWriter.cpp - ARM Windows COFF Object Writer -- C++ -==// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "MCTargetDesc/ARMFixupKinds.h" 100b57cec5SDimitry Andric #include "llvm/ADT/Twine.h" 110b57cec5SDimitry Andric #include "llvm/BinaryFormat/COFF.h" 120b57cec5SDimitry Andric #include "llvm/MC/MCAsmBackend.h" 13*fe6060f1SDimitry Andric #include "llvm/MC/MCContext.h" 140b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h" 150b57cec5SDimitry Andric #include "llvm/MC/MCFixup.h" 160b57cec5SDimitry Andric #include "llvm/MC/MCFixupKindInfo.h" 170b57cec5SDimitry Andric #include "llvm/MC/MCObjectWriter.h" 180b57cec5SDimitry Andric #include "llvm/MC/MCValue.h" 190b57cec5SDimitry Andric #include "llvm/MC/MCWinCOFFObjectWriter.h" 200b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 210b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 220b57cec5SDimitry Andric 230b57cec5SDimitry Andric using namespace llvm; 240b57cec5SDimitry Andric 250b57cec5SDimitry Andric namespace { 260b57cec5SDimitry Andric 270b57cec5SDimitry Andric class ARMWinCOFFObjectWriter : public MCWinCOFFObjectTargetWriter { 280b57cec5SDimitry Andric public: 29*fe6060f1SDimitry Andric ARMWinCOFFObjectWriter() 300b57cec5SDimitry Andric : MCWinCOFFObjectTargetWriter(COFF::IMAGE_FILE_MACHINE_ARMNT) { 310b57cec5SDimitry Andric } 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric ~ARMWinCOFFObjectWriter() override = default; 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric unsigned getRelocType(MCContext &Ctx, const MCValue &Target, 360b57cec5SDimitry Andric const MCFixup &Fixup, bool IsCrossSection, 370b57cec5SDimitry Andric const MCAsmBackend &MAB) const override; 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric bool recordRelocation(const MCFixup &) const override; 400b57cec5SDimitry Andric }; 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric } // end anonymous namespace 430b57cec5SDimitry Andric 440b57cec5SDimitry Andric unsigned ARMWinCOFFObjectWriter::getRelocType(MCContext &Ctx, 450b57cec5SDimitry Andric const MCValue &Target, 460b57cec5SDimitry Andric const MCFixup &Fixup, 470b57cec5SDimitry Andric bool IsCrossSection, 480b57cec5SDimitry Andric const MCAsmBackend &MAB) const { 490b57cec5SDimitry Andric MCSymbolRefExpr::VariantKind Modifier = 500b57cec5SDimitry Andric Target.isAbsolute() ? MCSymbolRefExpr::VK_None : Target.getSymA()->getKind(); 510b57cec5SDimitry Andric 52*fe6060f1SDimitry Andric unsigned FixupKind = Fixup.getKind(); 53*fe6060f1SDimitry Andric if (IsCrossSection) { 54*fe6060f1SDimitry Andric if (FixupKind != FK_Data_4) { 55*fe6060f1SDimitry Andric Ctx.reportError(Fixup.getLoc(), "Cannot represent this expression"); 56*fe6060f1SDimitry Andric return COFF::IMAGE_REL_ARM_ADDR32; 57*fe6060f1SDimitry Andric } 58*fe6060f1SDimitry Andric FixupKind = FK_PCRel_4; 59*fe6060f1SDimitry Andric } 60*fe6060f1SDimitry Andric 61*fe6060f1SDimitry Andric 62*fe6060f1SDimitry Andric switch (FixupKind) { 630b57cec5SDimitry Andric default: { 640b57cec5SDimitry Andric const MCFixupKindInfo &Info = MAB.getFixupKindInfo(Fixup.getKind()); 650b57cec5SDimitry Andric report_fatal_error(Twine("unsupported relocation type: ") + Info.Name); 660b57cec5SDimitry Andric } 670b57cec5SDimitry Andric case FK_Data_4: 680b57cec5SDimitry Andric switch (Modifier) { 690b57cec5SDimitry Andric case MCSymbolRefExpr::VK_COFF_IMGREL32: 700b57cec5SDimitry Andric return COFF::IMAGE_REL_ARM_ADDR32NB; 710b57cec5SDimitry Andric case MCSymbolRefExpr::VK_SECREL: 720b57cec5SDimitry Andric return COFF::IMAGE_REL_ARM_SECREL; 730b57cec5SDimitry Andric default: 740b57cec5SDimitry Andric return COFF::IMAGE_REL_ARM_ADDR32; 750b57cec5SDimitry Andric } 76*fe6060f1SDimitry Andric case FK_PCRel_4: 77*fe6060f1SDimitry Andric return COFF::IMAGE_REL_ARM_REL32; 780b57cec5SDimitry Andric case FK_SecRel_2: 790b57cec5SDimitry Andric return COFF::IMAGE_REL_ARM_SECTION; 800b57cec5SDimitry Andric case FK_SecRel_4: 810b57cec5SDimitry Andric return COFF::IMAGE_REL_ARM_SECREL; 820b57cec5SDimitry Andric case ARM::fixup_t2_condbranch: 830b57cec5SDimitry Andric return COFF::IMAGE_REL_ARM_BRANCH20T; 840b57cec5SDimitry Andric case ARM::fixup_t2_uncondbranch: 850b57cec5SDimitry Andric case ARM::fixup_arm_thumb_bl: 860b57cec5SDimitry Andric return COFF::IMAGE_REL_ARM_BRANCH24T; 870b57cec5SDimitry Andric case ARM::fixup_arm_thumb_blx: 880b57cec5SDimitry Andric return COFF::IMAGE_REL_ARM_BLX23T; 890b57cec5SDimitry Andric case ARM::fixup_t2_movw_lo16: 900b57cec5SDimitry Andric case ARM::fixup_t2_movt_hi16: 910b57cec5SDimitry Andric return COFF::IMAGE_REL_ARM_MOV32T; 920b57cec5SDimitry Andric } 930b57cec5SDimitry Andric } 940b57cec5SDimitry Andric 950b57cec5SDimitry Andric bool ARMWinCOFFObjectWriter::recordRelocation(const MCFixup &Fixup) const { 960b57cec5SDimitry Andric return static_cast<unsigned>(Fixup.getKind()) != ARM::fixup_t2_movt_hi16; 970b57cec5SDimitry Andric } 980b57cec5SDimitry Andric 990b57cec5SDimitry Andric namespace llvm { 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andric std::unique_ptr<MCObjectTargetWriter> 102*fe6060f1SDimitry Andric createARMWinCOFFObjectWriter() { 103*fe6060f1SDimitry Andric return std::make_unique<ARMWinCOFFObjectWriter>(); 1040b57cec5SDimitry Andric } 1050b57cec5SDimitry Andric 1060b57cec5SDimitry Andric } // end namespace llvm 107