brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.4 KiB · a3928c5 Raw
179 lines · cpp
1//===- bolt/Rewrite/SDTRewriter.cpp ---------------------------------------===//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// Implement support for System Tap Statically-Defined Trace points stored in10// .note.stapsdt section.11//12//===----------------------------------------------------------------------===//13 14#include "bolt/Core/BinaryFunction.h"15#include "bolt/Core/DebugData.h"16#include "bolt/Rewrite/MetadataRewriter.h"17#include "bolt/Rewrite/MetadataRewriters.h"18#include "bolt/Utils/CommandLineOpts.h"19#include "llvm/Support/CommandLine.h"20#include "llvm/Support/Errc.h"21#include "llvm/Support/Timer.h"22 23using namespace llvm;24using namespace bolt;25 26namespace opts {27static cl::opt<bool> PrintSDTMarkers("print-sdt",28                                     cl::desc("print all SDT markers"),29                                     cl::Hidden, cl::cat(BoltCategory));30}31 32namespace {33class SDTRewriter final : public MetadataRewriter {34  ErrorOr<BinarySection &> SDTSection{std::errc::bad_address};35 36  struct SDTMarkerInfo {37    uint64_t PC;38    uint64_t Base;39    uint64_t Semaphore;40    StringRef Provider;41    StringRef Name;42    StringRef Args;43 44    /// The offset of PC within the note section45    unsigned PCOffset;46  };47 48  /// Map SDT locations to SDT markers info49  using SDTMarkersListType = std::unordered_map<uint64_t, SDTMarkerInfo>;50  SDTMarkersListType SDTMarkers;51 52  /// Read section to populate SDTMarkers.53  void readSection();54 55  void printSDTMarkers() const;56 57public:58  SDTRewriter(StringRef Name, BinaryContext &BC) : MetadataRewriter(Name, BC) {}59 60  Error preCFGInitializer() override;61 62  Error postEmitFinalizer() override;63};64 65void SDTRewriter::readSection() {66  SDTSection = BC.getUniqueSectionByName(".note.stapsdt");67  if (!SDTSection)68    return;69 70  StringRef Buf = SDTSection->getContents();71  DataExtractor DE = DataExtractor(Buf, BC.AsmInfo->isLittleEndian(),72                                   BC.AsmInfo->getCodePointerSize());73  uint64_t Offset = 0;74 75  while (DE.isValidOffset(Offset)) {76    uint32_t NameSz = DE.getU32(&Offset);77    DE.getU32(&Offset); // skip over DescSz78    uint32_t Type = DE.getU32(&Offset);79    Offset = alignTo(Offset, 4);80 81    if (Type != 3)82      errs() << "BOLT-WARNING: SDT note type \"" << Type83             << "\" is not expected\n";84 85    if (NameSz == 0)86      errs() << "BOLT-WARNING: SDT note has empty name\n";87 88    StringRef Name = DE.getCStr(&Offset);89 90    if (Name != "stapsdt")91      errs() << "BOLT-WARNING: SDT note name \"" << Name92             << "\" is not expected\n";93 94    // Parse description95    SDTMarkerInfo Marker;96    Marker.PCOffset = Offset;97    Marker.PC = DE.getU64(&Offset);98    Marker.Base = DE.getU64(&Offset);99    Marker.Semaphore = DE.getU64(&Offset);100    Marker.Provider = DE.getCStr(&Offset);101    Marker.Name = DE.getCStr(&Offset);102    Marker.Args = DE.getCStr(&Offset);103    Offset = alignTo(Offset, 4);104    SDTMarkers[Marker.PC] = Marker;105  }106 107  if (opts::PrintSDTMarkers)108    printSDTMarkers();109}110 111Error SDTRewriter::preCFGInitializer() {112  // Populate SDTMarkers.113  readSection();114 115  // Mark nop instructions referenced by SDT and the containing function.116  for (const uint64_t PC : llvm::make_first_range(SDTMarkers)) {117    BinaryFunction *BF = BC.getBinaryFunctionContainingAddress(PC);118 119    if (!BF || !BC.shouldEmit(*BF))120      continue;121 122    const uint64_t Offset = PC - BF->getAddress();123    MCInst *Inst = BF->getInstructionAtOffset(Offset);124    if (!Inst)125      return createStringError(errc::executable_format_error,126                               "no instruction matches SDT offset");127 128    if (!BC.MIB->isNoop(*Inst))129      return createStringError(std::make_error_code(std::errc::not_supported),130                               "nop instruction expected at SDT offset");131 132    BC.MIB->setOffset(*Inst, static_cast<uint32_t>(Offset));133 134    BF->setHasSDTMarker(true);135  }136 137  return Error::success();138}139 140Error SDTRewriter::postEmitFinalizer() {141  if (!SDTSection)142    return Error::success();143 144  SDTSection->registerPatcher(std::make_unique<SimpleBinaryPatcher>());145 146  SimpleBinaryPatcher *SDTNotePatcher =147      static_cast<SimpleBinaryPatcher *>(SDTSection->getPatcher());148  for (auto &SDTInfoKV : SDTMarkers) {149    const uint64_t OriginalAddress = SDTInfoKV.first;150    const SDTMarkerInfo &SDTInfo = SDTInfoKV.second;151    const BinaryFunction *F =152        BC.getBinaryFunctionContainingAddress(OriginalAddress);153    if (!F)154      continue;155    const uint64_t NewAddress =156        F->translateInputToOutputAddress(OriginalAddress);157    SDTNotePatcher->addLE64Patch(SDTInfo.PCOffset, NewAddress);158  }159 160  return Error::success();161}162 163void SDTRewriter::printSDTMarkers() const {164  outs() << "BOLT-INFO: Number of SDT markers is " << SDTMarkers.size() << "\n";165  for (const SDTMarkerInfo &Marker : llvm::make_second_range(SDTMarkers)) {166    outs() << "BOLT-INFO: PC: " << utohexstr(Marker.PC)167           << ", Base: " << utohexstr(Marker.Base)168           << ", Semaphore: " << utohexstr(Marker.Semaphore)169           << ", Provider: " << Marker.Provider << ", Name: " << Marker.Name170           << ", Args: " << Marker.Args << "\n";171  }172}173} // namespace174 175std::unique_ptr<MetadataRewriter>176llvm::bolt::createSDTRewriter(BinaryContext &BC) {177  return std::make_unique<SDTRewriter>("sdt-rewriter", BC);178}179