diff --git a/bolt/include/bolt/Rewrite/MetadataManager.h b/bolt/include/bolt/Rewrite/MetadataManager.h new file mode 100644 --- /dev/null +++ b/bolt/include/bolt/Rewrite/MetadataManager.h @@ -0,0 +1,43 @@ +//===- bolt/Rewrite/MetadataManager.h ---------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef BOLT_REWRITE_METADATA_MANAGER_H +#define BOLT_REWRITE_METADATA_MANAGER_H + +#include "bolt/Rewrite/MetadataRewriter.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Error.h" + +namespace llvm { +namespace bolt { + +class BinaryContext; + +/// This class manages a collection of metadata handlers/rewriters. +/// It is responsible for registering new rewriters and invoking them at +/// certain stages of the binary processing pipeline. +class MetadataManager { + using RewritersListType = SmallVector, 1>; + RewritersListType Rewriters; + +public: + /// Register a new \p Rewriter. + void registerRewriter(std::unique_ptr Rewriter); + + /// Execute initialization of rewriters while functions are disassembled, but + /// CFG is not yet built. + void runInitializersPreCFG(); + + /// Run finalization step of rewriters after code has been emitted. + void runFinalizersAfterEmit(); +}; + +} // namespace bolt +} // namespace llvm + +#endif // BOLT_REWRITE_METADATA_MANAGER_H diff --git a/bolt/include/bolt/Rewrite/MetadataRewriter.h b/bolt/include/bolt/Rewrite/MetadataRewriter.h new file mode 100644 --- /dev/null +++ b/bolt/include/bolt/Rewrite/MetadataRewriter.h @@ -0,0 +1,60 @@ +//===- bolt/Rewrite/MetadataRewriter.h --------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Interface for reading and updating metadata in a file. +// +//===----------------------------------------------------------------------===// + +#ifndef BOLT_REWRITE_METADATA_REWRITER_H +#define BOLT_REWRITE_METADATA_REWRITER_H + +#include "bolt/Core/BinaryContext.h" +#include "llvm/Support/Error.h" + +namespace llvm { +namespace bolt { + +/// Base class for handling file sections with metadata. In this context, +/// metadata encompasses a wide range of data that references code and other +/// data. Such metadata may or may not have an impact on program execution. +/// Examples include: debug information, unwind information, exception handling +/// tables, etc. +// +/// The metadata can occupy a section (e.g. .note.stapsdt), span a number of +/// sections (e.g., DWARF debug info), or exist as subsection of another +/// section in the binary (e.g., static-key jump tables embedded in .rodata +/// section in the Linux Kernel). +class MetadataRewriter { + /// The name of the data type handled by an instance of this class. + StringRef Name; + +protected: + /// Provides access to the binary context. + BinaryContext &BC; + + MetadataRewriter(StringRef Name, BinaryContext &BC) : Name(Name), BC(BC) {} + +public: + virtual ~MetadataRewriter() = default; + + /// Return name for the rewriter. + StringRef getName() const { return Name; } + + /// Interface for modifying/annotating functions in the binary based on the + /// contents of the section. Functions are in pre-cfg state. + virtual Error preCFGInitializer() { return Error::success(); } + + /// Finalize section contents based on the new context after the new code is + /// emitted. + virtual Error postEmitFinalizer() { return Error::success(); } +}; + +} // namespace bolt +} // namespace llvm + +#endif // BOLT_REWRITE_METADATA_REWRITER_H diff --git a/bolt/include/bolt/Rewrite/MetadataRewriters.h b/bolt/include/bolt/Rewrite/MetadataRewriters.h new file mode 100644 --- /dev/null +++ b/bolt/include/bolt/Rewrite/MetadataRewriters.h @@ -0,0 +1,25 @@ +//===- bolt/Rewrite/MetadataRewriters.h -------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef BOLT_REWRITE_METADATA_REWRITERS_H +#define BOLT_REWRITE_METADATA_REWRITERS_H + +#include + +namespace llvm { +namespace bolt { + +class MetadataRewriter; + +/// The list of rewriter build functions (e.g. createNewMetadataRewriter()) that +/// return std::unique_ptr. + +} // namespace bolt +} // namespace llvm + +#endif // BOLT_REWRITE_METADATA_REWRITERS_H diff --git a/bolt/include/bolt/Rewrite/RewriteInstance.h b/bolt/include/bolt/Rewrite/RewriteInstance.h --- a/bolt/include/bolt/Rewrite/RewriteInstance.h +++ b/bolt/include/bolt/Rewrite/RewriteInstance.h @@ -15,6 +15,7 @@ #include "bolt/Core/BinaryContext.h" #include "bolt/Core/Linker.h" +#include "bolt/Rewrite/MetadataManager.h" #include "bolt/Utils/NameResolver.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/MC/StringTableBuilder.h" @@ -94,6 +95,9 @@ /// from meta data in the file. void discoverFileObjects(); + /// Create and initialize metadata rewriters for this instance. + void initializeMetadataManager(); + /// Process fragments, locate parent functions. void registerFragments(); @@ -188,6 +192,9 @@ /// Link additional runtime code to support instrumentation. void linkRuntime(); + /// Process metadata in special sections before CFG is built for functions. + void processMetadataPreCFG(); + /// Update debug and other auxiliary information in the file. void updateMetadata(); @@ -424,6 +431,9 @@ } private: + /// Manage a pipeline of metadata handlers. + MetadataManager MetadataManager; + /// Get the contents of the LSDA section for this binary. ArrayRef getLSDAData(); diff --git a/bolt/lib/Rewrite/CMakeLists.txt b/bolt/lib/Rewrite/CMakeLists.txt --- a/bolt/lib/Rewrite/CMakeLists.txt +++ b/bolt/lib/Rewrite/CMakeLists.txt @@ -15,6 +15,7 @@ ExecutableFileMemoryManager.cpp JITLinkLinker.cpp MachORewriteInstance.cpp + MetadataManager.cpp RewriteInstance.cpp DISABLE_LLVM_LINK_LLVM_DYLIB diff --git a/bolt/lib/Rewrite/MetadataManager.cpp b/bolt/lib/Rewrite/MetadataManager.cpp new file mode 100644 --- /dev/null +++ b/bolt/lib/Rewrite/MetadataManager.cpp @@ -0,0 +1,45 @@ +//===- bolt/Rewrite/MetadataManager.cpp -----------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "bolt/Rewrite/MetadataManager.h" +#include "llvm/Support/Debug.h" + +#undef DEBUG_TYPE +#define DEBUG_TYPE "bolt-metadata" + +using namespace llvm; +using namespace bolt; + +void MetadataManager::registerRewriter( + std::unique_ptr Rewriter) { + Rewriters.emplace_back(std::move(Rewriter)); +} + +void MetadataManager::runInitializersPreCFG() { + for (auto &Rewriter : Rewriters) { + LLVM_DEBUG(dbgs() << "BOLT-DEBUG: invoking " << Rewriter->getName() + << " before CFG construction\n"); + if (Error E = Rewriter->preCFGInitializer()) { + errs() << "BOLT-ERROR: while running " << Rewriter->getName() + << " in pre-CFG state: " << toString(std::move(E)) << '\n'; + exit(1); + } + } +} + +void MetadataManager::runFinalizersAfterEmit() { + for (auto &Rewriter : Rewriters) { + LLVM_DEBUG(dbgs() << "BOLT-DEBUG: invoking " << Rewriter->getName() + << " after emit\n"); + if (Error E = Rewriter->postEmitFinalizer()) { + errs() << "BOLT-ERROR: while running " << Rewriter->getName() + << " after emit: " << toString(std::move(E)) << '\n'; + exit(1); + } + } +} diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp --- a/bolt/lib/Rewrite/RewriteInstance.cpp +++ b/bolt/lib/Rewrite/RewriteInstance.cpp @@ -27,6 +27,7 @@ #include "bolt/Rewrite/DWARFRewriter.h" #include "bolt/Rewrite/ExecutableFileMemoryManager.h" #include "bolt/Rewrite/JITLinkLinker.h" +#include "bolt/Rewrite/MetadataRewriters.h" #include "bolt/RuntimeLibs/HugifyRuntimeLibrary.h" #include "bolt/RuntimeLibs/InstrumentationRuntimeLibrary.h" #include "bolt/Utils/CommandLineOpts.h" @@ -844,7 +845,7 @@ disassembleFunctions(); - processProfileDataPreCFG(); + processMetadataPreCFG(); buildFunctionsCFG(); @@ -3243,6 +3244,18 @@ } } +void RewriteInstance::initializeMetadataManager() { + // TODO +} + +void RewriteInstance::processMetadataPreCFG() { + initializeMetadataManager(); + + MetadataManager.runInitializersPreCFG(); + + processProfileDataPreCFG(); +} + void RewriteInstance::processProfileDataPreCFG() { if (!ProfileReader) return; @@ -3605,6 +3618,9 @@ } void RewriteInstance::updateMetadata() { + MetadataManager.runFinalizersAfterEmit(); + + // TODO: use MetadataManager for updates. updateSDTMarkers(); updateLKMarkers(); parsePseudoProbe();