xref: /llvm-project/bolt/lib/Rewrite/SDTRewriter.cpp (revision f841ca0c355ae53c96f615996d0aff4648da8618)
198e2d630SMaksim Panchenko //===- bolt/Rewrite/SDTRewriter.cpp ---------------------------------------===//
298e2d630SMaksim Panchenko //
398e2d630SMaksim Panchenko // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
498e2d630SMaksim Panchenko // See https://llvm.org/LICENSE.txt for license information.
598e2d630SMaksim Panchenko // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
698e2d630SMaksim Panchenko //
798e2d630SMaksim Panchenko //===----------------------------------------------------------------------===//
898e2d630SMaksim Panchenko //
998e2d630SMaksim Panchenko // Implement support for System Tap Statically-Defined Trace points stored in
1098e2d630SMaksim Panchenko // .note.stapsdt section.
1198e2d630SMaksim Panchenko //
1298e2d630SMaksim Panchenko //===----------------------------------------------------------------------===//
1398e2d630SMaksim Panchenko 
1498e2d630SMaksim Panchenko #include "bolt/Core/BinaryFunction.h"
1598e2d630SMaksim Panchenko #include "bolt/Core/DebugData.h"
1698e2d630SMaksim Panchenko #include "bolt/Rewrite/MetadataRewriter.h"
1798e2d630SMaksim Panchenko #include "bolt/Rewrite/MetadataRewriters.h"
1898e2d630SMaksim Panchenko #include "bolt/Utils/CommandLineOpts.h"
1998e2d630SMaksim Panchenko #include "llvm/Support/CommandLine.h"
2098e2d630SMaksim Panchenko #include "llvm/Support/Errc.h"
2198e2d630SMaksim Panchenko #include "llvm/Support/Timer.h"
2298e2d630SMaksim Panchenko 
2398e2d630SMaksim Panchenko using namespace llvm;
2498e2d630SMaksim Panchenko using namespace bolt;
2598e2d630SMaksim Panchenko 
2698e2d630SMaksim Panchenko namespace opts {
2798e2d630SMaksim Panchenko static cl::opt<bool> PrintSDTMarkers("print-sdt",
2898e2d630SMaksim Panchenko                                      cl::desc("print all SDT markers"),
2998e2d630SMaksim Panchenko                                      cl::Hidden, cl::cat(BoltCategory));
3098e2d630SMaksim Panchenko }
3198e2d630SMaksim Panchenko 
3298e2d630SMaksim Panchenko namespace {
3398e2d630SMaksim Panchenko class SDTRewriter final : public MetadataRewriter {
3498e2d630SMaksim Panchenko   ErrorOr<BinarySection &> SDTSection{std::errc::bad_address};
3598e2d630SMaksim Panchenko 
3698e2d630SMaksim Panchenko   struct SDTMarkerInfo {
3798e2d630SMaksim Panchenko     uint64_t PC;
3898e2d630SMaksim Panchenko     uint64_t Base;
3998e2d630SMaksim Panchenko     uint64_t Semaphore;
4098e2d630SMaksim Panchenko     StringRef Provider;
4198e2d630SMaksim Panchenko     StringRef Name;
4298e2d630SMaksim Panchenko     StringRef Args;
4398e2d630SMaksim Panchenko 
4498e2d630SMaksim Panchenko     /// The offset of PC within the note section
4598e2d630SMaksim Panchenko     unsigned PCOffset;
4698e2d630SMaksim Panchenko   };
4798e2d630SMaksim Panchenko 
4898e2d630SMaksim Panchenko   /// Map SDT locations to SDT markers info
4998e2d630SMaksim Panchenko   using SDTMarkersListType = std::unordered_map<uint64_t, SDTMarkerInfo>;
5098e2d630SMaksim Panchenko   SDTMarkersListType SDTMarkers;
5198e2d630SMaksim Panchenko 
5298e2d630SMaksim Panchenko   /// Read section to populate SDTMarkers.
5398e2d630SMaksim Panchenko   void readSection();
5498e2d630SMaksim Panchenko 
5598e2d630SMaksim Panchenko   void printSDTMarkers() const;
5698e2d630SMaksim Panchenko 
5798e2d630SMaksim Panchenko public:
SDTRewriter(StringRef Name,BinaryContext & BC)5898e2d630SMaksim Panchenko   SDTRewriter(StringRef Name, BinaryContext &BC) : MetadataRewriter(Name, BC) {}
5998e2d630SMaksim Panchenko 
6098e2d630SMaksim Panchenko   Error preCFGInitializer() override;
6198e2d630SMaksim Panchenko 
6298e2d630SMaksim Panchenko   Error postEmitFinalizer() override;
6398e2d630SMaksim Panchenko };
6498e2d630SMaksim Panchenko 
readSection()6598e2d630SMaksim Panchenko void SDTRewriter::readSection() {
6698e2d630SMaksim Panchenko   SDTSection = BC.getUniqueSectionByName(".note.stapsdt");
6798e2d630SMaksim Panchenko   if (!SDTSection)
6898e2d630SMaksim Panchenko     return;
6998e2d630SMaksim Panchenko 
7098e2d630SMaksim Panchenko   StringRef Buf = SDTSection->getContents();
7198e2d630SMaksim Panchenko   DataExtractor DE = DataExtractor(Buf, BC.AsmInfo->isLittleEndian(),
7298e2d630SMaksim Panchenko                                    BC.AsmInfo->getCodePointerSize());
7398e2d630SMaksim Panchenko   uint64_t Offset = 0;
7498e2d630SMaksim Panchenko 
7598e2d630SMaksim Panchenko   while (DE.isValidOffset(Offset)) {
7698e2d630SMaksim Panchenko     uint32_t NameSz = DE.getU32(&Offset);
7798e2d630SMaksim Panchenko     DE.getU32(&Offset); // skip over DescSz
7898e2d630SMaksim Panchenko     uint32_t Type = DE.getU32(&Offset);
7998e2d630SMaksim Panchenko     Offset = alignTo(Offset, 4);
8098e2d630SMaksim Panchenko 
8198e2d630SMaksim Panchenko     if (Type != 3)
8298e2d630SMaksim Panchenko       errs() << "BOLT-WARNING: SDT note type \"" << Type
8398e2d630SMaksim Panchenko              << "\" is not expected\n";
8498e2d630SMaksim Panchenko 
8598e2d630SMaksim Panchenko     if (NameSz == 0)
8698e2d630SMaksim Panchenko       errs() << "BOLT-WARNING: SDT note has empty name\n";
8798e2d630SMaksim Panchenko 
8898e2d630SMaksim Panchenko     StringRef Name = DE.getCStr(&Offset);
8998e2d630SMaksim Panchenko 
90*f841ca0cSKazu Hirata     if (Name != "stapsdt")
9198e2d630SMaksim Panchenko       errs() << "BOLT-WARNING: SDT note name \"" << Name
9298e2d630SMaksim Panchenko              << "\" is not expected\n";
9398e2d630SMaksim Panchenko 
9498e2d630SMaksim Panchenko     // Parse description
9598e2d630SMaksim Panchenko     SDTMarkerInfo Marker;
9698e2d630SMaksim Panchenko     Marker.PCOffset = Offset;
9798e2d630SMaksim Panchenko     Marker.PC = DE.getU64(&Offset);
9898e2d630SMaksim Panchenko     Marker.Base = DE.getU64(&Offset);
9998e2d630SMaksim Panchenko     Marker.Semaphore = DE.getU64(&Offset);
10098e2d630SMaksim Panchenko     Marker.Provider = DE.getCStr(&Offset);
10198e2d630SMaksim Panchenko     Marker.Name = DE.getCStr(&Offset);
10298e2d630SMaksim Panchenko     Marker.Args = DE.getCStr(&Offset);
10398e2d630SMaksim Panchenko     Offset = alignTo(Offset, 4);
10498e2d630SMaksim Panchenko     SDTMarkers[Marker.PC] = Marker;
10598e2d630SMaksim Panchenko   }
10698e2d630SMaksim Panchenko 
10798e2d630SMaksim Panchenko   if (opts::PrintSDTMarkers)
10898e2d630SMaksim Panchenko     printSDTMarkers();
10998e2d630SMaksim Panchenko }
11098e2d630SMaksim Panchenko 
preCFGInitializer()11198e2d630SMaksim Panchenko Error SDTRewriter::preCFGInitializer() {
11298e2d630SMaksim Panchenko   // Populate SDTMarkers.
11398e2d630SMaksim Panchenko   readSection();
11498e2d630SMaksim Panchenko 
11598e2d630SMaksim Panchenko   // Mark nop instructions referenced by SDT and the containing function.
11698e2d630SMaksim Panchenko   for (const uint64_t PC : llvm::make_first_range(SDTMarkers)) {
11798e2d630SMaksim Panchenko     BinaryFunction *BF = BC.getBinaryFunctionContainingAddress(PC);
11898e2d630SMaksim Panchenko 
11998e2d630SMaksim Panchenko     if (!BF || !BC.shouldEmit(*BF))
12098e2d630SMaksim Panchenko       continue;
12198e2d630SMaksim Panchenko 
12298e2d630SMaksim Panchenko     const uint64_t Offset = PC - BF->getAddress();
12398e2d630SMaksim Panchenko     MCInst *Inst = BF->getInstructionAtOffset(Offset);
12498e2d630SMaksim Panchenko     if (!Inst)
12598e2d630SMaksim Panchenko       return createStringError(errc::executable_format_error,
12698e2d630SMaksim Panchenko                                "no instruction matches SDT offset");
12798e2d630SMaksim Panchenko 
12898e2d630SMaksim Panchenko     if (!BC.MIB->isNoop(*Inst))
12998e2d630SMaksim Panchenko       return createStringError(std::make_error_code(std::errc::not_supported),
13098e2d630SMaksim Panchenko                                "nop instruction expected at SDT offset");
13198e2d630SMaksim Panchenko 
13298e2d630SMaksim Panchenko     BC.MIB->setOffset(*Inst, static_cast<uint32_t>(Offset));
13398e2d630SMaksim Panchenko 
13498e2d630SMaksim Panchenko     BF->setHasSDTMarker(true);
13598e2d630SMaksim Panchenko   }
13698e2d630SMaksim Panchenko 
13798e2d630SMaksim Panchenko   return Error::success();
13898e2d630SMaksim Panchenko }
13998e2d630SMaksim Panchenko 
postEmitFinalizer()14098e2d630SMaksim Panchenko Error SDTRewriter::postEmitFinalizer() {
14198e2d630SMaksim Panchenko   if (!SDTSection)
14298e2d630SMaksim Panchenko     return Error::success();
14398e2d630SMaksim Panchenko 
14498e2d630SMaksim Panchenko   SDTSection->registerPatcher(std::make_unique<SimpleBinaryPatcher>());
14598e2d630SMaksim Panchenko 
14698e2d630SMaksim Panchenko   SimpleBinaryPatcher *SDTNotePatcher =
14798e2d630SMaksim Panchenko       static_cast<SimpleBinaryPatcher *>(SDTSection->getPatcher());
14898e2d630SMaksim Panchenko   for (auto &SDTInfoKV : SDTMarkers) {
14998e2d630SMaksim Panchenko     const uint64_t OriginalAddress = SDTInfoKV.first;
15098e2d630SMaksim Panchenko     const SDTMarkerInfo &SDTInfo = SDTInfoKV.second;
15198e2d630SMaksim Panchenko     const BinaryFunction *F =
15298e2d630SMaksim Panchenko         BC.getBinaryFunctionContainingAddress(OriginalAddress);
15398e2d630SMaksim Panchenko     if (!F)
15498e2d630SMaksim Panchenko       continue;
15598e2d630SMaksim Panchenko     const uint64_t NewAddress =
15698e2d630SMaksim Panchenko         F->translateInputToOutputAddress(OriginalAddress);
15798e2d630SMaksim Panchenko     SDTNotePatcher->addLE64Patch(SDTInfo.PCOffset, NewAddress);
15898e2d630SMaksim Panchenko   }
15998e2d630SMaksim Panchenko 
16098e2d630SMaksim Panchenko   return Error::success();
16198e2d630SMaksim Panchenko }
16298e2d630SMaksim Panchenko 
printSDTMarkers() const16398e2d630SMaksim Panchenko void SDTRewriter::printSDTMarkers() const {
16498e2d630SMaksim Panchenko   outs() << "BOLT-INFO: Number of SDT markers is " << SDTMarkers.size() << "\n";
16598e2d630SMaksim Panchenko   for (const SDTMarkerInfo &Marker : llvm::make_second_range(SDTMarkers)) {
16698e2d630SMaksim Panchenko     outs() << "BOLT-INFO: PC: " << utohexstr(Marker.PC)
16798e2d630SMaksim Panchenko            << ", Base: " << utohexstr(Marker.Base)
16898e2d630SMaksim Panchenko            << ", Semaphore: " << utohexstr(Marker.Semaphore)
16998e2d630SMaksim Panchenko            << ", Provider: " << Marker.Provider << ", Name: " << Marker.Name
17098e2d630SMaksim Panchenko            << ", Args: " << Marker.Args << "\n";
17198e2d630SMaksim Panchenko   }
17298e2d630SMaksim Panchenko }
17398e2d630SMaksim Panchenko } // namespace
17498e2d630SMaksim Panchenko 
17598e2d630SMaksim Panchenko std::unique_ptr<MetadataRewriter>
createSDTRewriter(BinaryContext & BC)17698e2d630SMaksim Panchenko llvm::bolt::createSDTRewriter(BinaryContext &BC) {
17798e2d630SMaksim Panchenko   return std::make_unique<SDTRewriter>("sdt-rewriter", BC);
17898e2d630SMaksim Panchenko }
179