166 lines · cpp
1//= AArch64WinCOFFObjectWriter.cpp - AArch64 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-exception6//7//===---------------------------------------------------------------------===//8 9#include "AArch64MCTargetDesc.h"10#include "MCTargetDesc/AArch64FixupKinds.h"11#include "MCTargetDesc/AArch64MCAsmInfo.h"12#include "llvm/ADT/Twine.h"13#include "llvm/BinaryFormat/COFF.h"14#include "llvm/MC/MCAsmBackend.h"15#include "llvm/MC/MCContext.h"16#include "llvm/MC/MCExpr.h"17#include "llvm/MC/MCFixup.h"18#include "llvm/MC/MCObjectWriter.h"19#include "llvm/MC/MCValue.h"20#include "llvm/MC/MCWinCOFFObjectWriter.h"21#include "llvm/Support/Casting.h"22#include "llvm/Support/ErrorHandling.h"23#include <cassert>24 25using namespace llvm;26 27namespace {28 29class AArch64WinCOFFObjectWriter : public MCWinCOFFObjectTargetWriter {30public:31 AArch64WinCOFFObjectWriter(const Triple &TheTriple)32 : MCWinCOFFObjectTargetWriter(TheTriple.isWindowsArm64EC()33 ? COFF::IMAGE_FILE_MACHINE_ARM64EC34 : COFF::IMAGE_FILE_MACHINE_ARM64) {}35 36 ~AArch64WinCOFFObjectWriter() override = default;37 38 unsigned getRelocType(MCContext &Ctx, const MCValue &Target,39 const MCFixup &Fixup, bool IsCrossSection,40 const MCAsmBackend &MAB) const override;41 42 bool recordRelocation(const MCFixup &) const override;43};44 45} // end anonymous namespace46 47unsigned AArch64WinCOFFObjectWriter::getRelocType(48 MCContext &Ctx, const MCValue &Target, const MCFixup &Fixup,49 bool IsCrossSection, const MCAsmBackend &MAB) const {50 unsigned FixupKind = Fixup.getKind();51 bool PCRel = Fixup.isPCRel();52 if (IsCrossSection) {53 // IMAGE_REL_ARM64_REL64 does not exist. We treat FK_Data_8 as FK_PCRel_4 so54 // that .xword a-b can lower to IMAGE_REL_ARM64_REL32. This allows generic55 // instrumentation to not bother with the COFF limitation. A negative value56 // needs attention.57 if (PCRel || (FixupKind != FK_Data_4 && FixupKind != FK_Data_8)) {58 Ctx.reportError(Fixup.getLoc(), "Cannot represent this expression");59 return COFF::IMAGE_REL_ARM64_ADDR32;60 }61 FixupKind = FK_Data_4;62 PCRel = true;63 }64 65 auto Spec = Target.getSpecifier();66 const MCExpr *Expr = Fixup.getValue();67 68 if (auto *A64E = dyn_cast<MCSpecifierExpr>(Expr)) {69 AArch64::Specifier Spec = A64E->getSpecifier();70 switch (AArch64::getSymbolLoc(Spec)) {71 case AArch64::S_ABS:72 case AArch64::S_SECREL:73 // Supported74 break;75 default:76 Ctx.reportError(Fixup.getLoc(),77 "relocation specifier " +78 AArch64::getSpecifierName(A64E->getSpecifier()) +79 " unsupported on COFF targets");80 return COFF::IMAGE_REL_ARM64_ABSOLUTE; // Dummy return value81 }82 }83 84 switch (FixupKind) {85 default: {86 if (auto *A64E = dyn_cast<MCSpecifierExpr>(Expr)) {87 Ctx.reportError(Fixup.getLoc(),88 "relocation specifier " +89 AArch64::getSpecifierName(A64E->getSpecifier()) +90 " unsupported on COFF targets");91 } else {92 MCFixupKindInfo Info = MAB.getFixupKindInfo(Fixup.getKind());93 Ctx.reportError(Fixup.getLoc(), Twine("relocation type ") + Info.Name +94 " unsupported on COFF targets");95 }96 return COFF::IMAGE_REL_ARM64_ABSOLUTE; // Dummy return value97 }98 99 case FK_Data_4:100 if (PCRel)101 return COFF::IMAGE_REL_ARM64_REL32;102 switch (Spec) {103 default:104 return COFF::IMAGE_REL_ARM64_ADDR32;105 case MCSymbolRefExpr::VK_COFF_IMGREL32:106 return COFF::IMAGE_REL_ARM64_ADDR32NB;107 }108 109 case FK_Data_8:110 return COFF::IMAGE_REL_ARM64_ADDR64;111 112 case FK_SecRel_2:113 return COFF::IMAGE_REL_ARM64_SECTION;114 115 case FK_SecRel_4:116 return COFF::IMAGE_REL_ARM64_SECREL;117 118 case AArch64::fixup_aarch64_add_imm12:119 if (auto *A64E = dyn_cast<MCSpecifierExpr>(Expr)) {120 AArch64::Specifier Spec = A64E->getSpecifier();121 if (Spec == AArch64::S_SECREL_LO12)122 return COFF::IMAGE_REL_ARM64_SECREL_LOW12A;123 if (Spec == AArch64::S_SECREL_HI12)124 return COFF::IMAGE_REL_ARM64_SECREL_HIGH12A;125 }126 return COFF::IMAGE_REL_ARM64_PAGEOFFSET_12A;127 128 case AArch64::fixup_aarch64_ldst_imm12_scale1:129 case AArch64::fixup_aarch64_ldst_imm12_scale2:130 case AArch64::fixup_aarch64_ldst_imm12_scale4:131 case AArch64::fixup_aarch64_ldst_imm12_scale8:132 case AArch64::fixup_aarch64_ldst_imm12_scale16:133 if (auto *A64E = dyn_cast<MCSpecifierExpr>(Expr)) {134 AArch64::Specifier Spec = A64E->getSpecifier();135 if (Spec == AArch64::S_SECREL_LO12)136 return COFF::IMAGE_REL_ARM64_SECREL_LOW12L;137 }138 return COFF::IMAGE_REL_ARM64_PAGEOFFSET_12L;139 140 case AArch64::fixup_aarch64_pcrel_adr_imm21:141 return COFF::IMAGE_REL_ARM64_REL21;142 143 case AArch64::fixup_aarch64_pcrel_adrp_imm21:144 return COFF::IMAGE_REL_ARM64_PAGEBASE_REL21;145 146 case AArch64::fixup_aarch64_pcrel_branch14:147 return COFF::IMAGE_REL_ARM64_BRANCH14;148 149 case AArch64::fixup_aarch64_pcrel_branch19:150 return COFF::IMAGE_REL_ARM64_BRANCH19;151 152 case AArch64::fixup_aarch64_pcrel_branch26:153 case AArch64::fixup_aarch64_pcrel_call26:154 return COFF::IMAGE_REL_ARM64_BRANCH26;155 }156}157 158bool AArch64WinCOFFObjectWriter::recordRelocation(const MCFixup &Fixup) const {159 return true;160}161 162std::unique_ptr<MCObjectTargetWriter>163llvm::createAArch64WinCOFFObjectWriter(const Triple &TheTriple) {164 return std::make_unique<AArch64WinCOFFObjectWriter>(TheTriple);165}166