brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.6 KiB · d742b28 Raw
250 lines · cpp
1//===- AArch64TargetStreamer.cpp - AArch64TargetStreamer class ------------===//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// This file implements the AArch64TargetStreamer class.10//11//===----------------------------------------------------------------------===//12 13#include "AArch64TargetStreamer.h"14#include "AArch64MCAsmInfo.h"15#include "llvm/BinaryFormat/ELF.h"16#include "llvm/MC/ConstantPools.h"17#include "llvm/MC/MCContext.h"18#include "llvm/MC/MCELFStreamer.h"19#include "llvm/MC/MCSection.h"20#include "llvm/MC/MCSectionELF.h"21#include "llvm/MC/MCSubtargetInfo.h"22#include "llvm/Support/CommandLine.h"23 24using namespace llvm;25 26static cl::opt<bool> MarkBTIProperty(27    "aarch64-mark-bti-property", cl::Hidden,28    cl::desc("Add .note.gnu.property with BTI to assembly files"),29    cl::init(false));30 31//32// AArch64TargetStreamer Implementation33//34AArch64TargetStreamer::AArch64TargetStreamer(MCStreamer &S)35    : MCTargetStreamer(S), ConstantPools(new AssemblerConstantPools()) {}36 37AArch64TargetStreamer::~AArch64TargetStreamer() = default;38 39void AArch64TargetStreamer::emitAuthValue(const MCExpr *Expr,40                                          uint16_t Discriminator,41                                          AArch64PACKey::ID Key,42                                          bool HasAddressDiversity) {43  Streamer.emitValueImpl(AArch64AuthMCExpr::create(Expr, Discriminator, Key,44                                                   HasAddressDiversity,45                                                   Streamer.getContext()),46                         8);47}48 49// The constant pool handling is shared by all AArch64TargetStreamer50// implementations.51const MCExpr *AArch64TargetStreamer::addConstantPoolEntry(const MCExpr *Expr,52                                                          unsigned Size,53                                                          SMLoc Loc) {54  return ConstantPools->addEntry(Streamer, Expr, Size, Loc);55}56 57void AArch64TargetStreamer::emitCurrentConstantPool() {58  ConstantPools->emitForCurrentSection(Streamer);59}60 61void AArch64TargetStreamer::emitConstantPools() {62  ConstantPools->emitAll(Streamer);63}64 65// finish() - write out any non-empty assembler constant pools and66//   write out note.gnu.properties if need.67void AArch64TargetStreamer::finish() {68  if (MarkBTIProperty)69    emitNoteSection(ELF::GNU_PROPERTY_AARCH64_FEATURE_1_BTI);70}71 72void AArch64TargetStreamer::emitNoteSection(unsigned Flags,73                                            uint64_t PAuthABIPlatform,74                                            uint64_t PAuthABIVersion) {75  assert((PAuthABIPlatform == uint64_t(-1)) ==76         (PAuthABIVersion == uint64_t(-1)));77  uint64_t DescSz = 0;78  if (Flags != 0)79    DescSz += 4 * 4;80  if (PAuthABIPlatform != uint64_t(-1))81    DescSz += 4 + 4 + 8 * 2;82  if (DescSz == 0)83    return;84 85  MCStreamer &OutStreamer = getStreamer();86  MCContext &Context = OutStreamer.getContext();87  // Emit a .note.gnu.property section with the flags.88  MCSectionELF *Nt = Context.getELFSection(".note.gnu.property", ELF::SHT_NOTE,89                                           ELF::SHF_ALLOC);90  if (Nt->isRegistered()) {91    SMLoc Loc;92    Context.reportWarning(93        Loc,94        "The .note.gnu.property is not emitted because it is already present.");95    return;96  }97  MCSection *Cur = OutStreamer.getCurrentSectionOnly();98  OutStreamer.switchSection(Nt);99 100  // Emit the note header.101  OutStreamer.emitValueToAlignment(Align(8));102  OutStreamer.emitIntValue(4, 4);     // data size for "GNU\0"103  OutStreamer.emitIntValue(DescSz, 4); // Elf_Prop array size104  OutStreamer.emitIntValue(ELF::NT_GNU_PROPERTY_TYPE_0, 4);105  OutStreamer.emitBytes(StringRef("GNU", 4)); // note name106 107  // Emit the PAC/BTI properties.108  if (Flags != 0) {109    OutStreamer.emitIntValue(ELF::GNU_PROPERTY_AARCH64_FEATURE_1_AND, 4);110    OutStreamer.emitIntValue(4, 4);     // data size111    OutStreamer.emitIntValue(Flags, 4); // data112    OutStreamer.emitIntValue(0, 4);     // pad113  }114 115  // Emit the PAuth ABI compatibility info116  if (PAuthABIPlatform != uint64_t(-1)) {117    OutStreamer.emitIntValue(ELF::GNU_PROPERTY_AARCH64_FEATURE_PAUTH, 4);118    OutStreamer.emitIntValue(8 * 2, 4); // data size119    OutStreamer.emitIntValue(PAuthABIPlatform, 8);120    OutStreamer.emitIntValue(PAuthABIVersion, 8);121  }122 123  OutStreamer.endSection(Nt);124  OutStreamer.switchSection(Cur);125}126 127void AArch64TargetStreamer::emitInst(uint32_t Inst) {128  char Buffer[4];129 130  // We can't just use EmitIntValue here, as that will swap the131  // endianness on big-endian systems (instructions are always132  // little-endian).133  for (char &C : Buffer) {134    C = uint8_t(Inst);135    Inst >>= 8;136  }137 138  getStreamer().emitBytes(StringRef(Buffer, 4));139}140 141MCTargetStreamer *142llvm::createAArch64ObjectTargetStreamer(MCStreamer &S,143                                        const MCSubtargetInfo &STI) {144  const Triple &TT = STI.getTargetTriple();145  if (TT.isOSBinFormatELF())146    return new AArch64TargetELFStreamer(S);147  if (TT.isOSBinFormatCOFF())148    return new AArch64TargetWinCOFFStreamer(S);149  return nullptr;150}151 152MCTargetStreamer *llvm::createAArch64NullTargetStreamer(MCStreamer &S) {153  return new AArch64TargetStreamer(S);154}155 156void AArch64TargetStreamer::emitAttributesSubsection(157    StringRef VendorName, AArch64BuildAttributes::SubsectionOptional IsOptional,158    AArch64BuildAttributes::SubsectionType ParameterType) {159 160  // If exists, return.161  for (MCELFStreamer::AttributeSubSection &SubSection : AttributeSubSections) {162    if (VendorName == SubSection.VendorName) {163      activateAttributesSubsection(VendorName);164      return;165    }166  }167  // else, add the subsection168  MCELFStreamer::AttributeSubSection AttSubSection;169  AttSubSection.VendorName = VendorName;170  AttSubSection.IsOptional = IsOptional;171  AttSubSection.ParameterType = ParameterType;172  AttributeSubSections.push_back(AttSubSection);173  activateAttributesSubsection(VendorName);174}175 176std::unique_ptr<MCELFStreamer::AttributeSubSection>177AArch64TargetStreamer::getActiveAttributesSubsection() {178  for (MCELFStreamer::AttributeSubSection &SubSection : AttributeSubSections) {179    if (SubSection.IsActive) {180      return std::make_unique<MCELFStreamer::AttributeSubSection>(SubSection);181    }182  }183  return nullptr;184}185 186std::unique_ptr<MCELFStreamer::AttributeSubSection>187AArch64TargetStreamer::getAttributesSubsectionByName(StringRef Name) {188  for (MCELFStreamer::AttributeSubSection &SubSection : AttributeSubSections) {189    if (Name == SubSection.VendorName) {190      return std::make_unique<MCELFStreamer::AttributeSubSection>(SubSection);191    }192  }193  return nullptr;194}195 196void AArch64TargetStreamer::emitAttribute(StringRef VendorName, unsigned Tag,197                                          unsigned Value, std::string String) {198 199  if (unsigned(-1) == Value && "" == String) {200    assert(0 && "Arguments error");201    return;202  }203  if (AttributeSubSections.size() == 0) {204    assert(0 &&205           "Can not add AArch64 build attribute: no AArch64 subsection exists");206    return;207  }208 209  for (MCELFStreamer::AttributeSubSection &SubSection : AttributeSubSections) {210    if (VendorName == SubSection.VendorName) {211      if (!SubSection.IsActive) {212        assert(0 &&213               "Can not add AArch64 build attribute: subsection is not active");214        return;215      }216      for (MCELFStreamer::AttributeItem &Item : SubSection.Content) {217        // Tag already exists218        if (Item.Tag == Tag) {219          Item.Type = unsigned(-1) != Value220                          ? MCELFStreamer::AttributeItem::NumericAttribute221                          : MCELFStreamer::AttributeItem::TextAttribute;222          Item.IntValue = unsigned(-1) != Value ? Value : unsigned(-1);223          Item.StringValue = unsigned(-1) != Value ? "" : String;224          return;225        }226      }227      if (unsigned(-1) != Value)228        SubSection.Content.push_back(MCELFStreamer::AttributeItem(229            MCELFStreamer::AttributeItem::NumericAttribute, Tag, Value, ""));230      if ("" != String)231        SubSection.Content.push_back(MCELFStreamer::AttributeItem(232            MCELFStreamer::AttributeItem::TextAttribute, Tag, unsigned(-1),233            String));234      return;235    }236  }237  assert(0 && "Can not add AArch64 build attribute: required subsection does "238              "not exist");239}240 241void AArch64TargetStreamer::activateAttributesSubsection(StringRef VendorName) {242  for (MCELFStreamer::AttributeSubSection &SubSection : AttributeSubSections) {243    if (VendorName == SubSection.VendorName) {244      SubSection.IsActive = true;245    } else {246      SubSection.IsActive = false;247    }248  }249}250