//===- SymbolRewriter.cpp - Symbol Rewriter -------------------------------===// // // 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 // //===----------------------------------------------------------------------===// // // SymbolRewriter is a LLVM pass which can rewrite symbols transparently within // existing code. It is implemented as a compiler pass and is configured via a // YAML configuration file. // // The YAML configuration file format is as follows: // // RewriteMapFile := RewriteDescriptors // RewriteDescriptors := RewriteDescriptor | RewriteDescriptors // RewriteDescriptor := RewriteDescriptorType ':' '{' RewriteDescriptorFields '}' // RewriteDescriptorFields := RewriteDescriptorField | RewriteDescriptorFields // RewriteDescriptorField := FieldIdentifier ':' FieldValue ',' // RewriteDescriptorType := Identifier // FieldIdentifier := Identifier // FieldValue := Identifier // Identifier := [0-9a-zA-Z]+ // // Currently, the following descriptor types are supported: // // - function: (function rewriting) // + Source (original name of the function) // + Target (explicit transformation) // + Transform (pattern transformation) // + Naked (boolean, whether the function is undecorated) // - global variable: (external linkage global variable rewriting) // + Source (original name of externally visible variable) // + Target (explicit transformation) // + Transform (pattern transformation) // - global alias: (global alias rewriting) // + Source (original name of the aliased name) // + Target (explicit transformation) // + Transform (pattern transformation) // // Note that source and exactly one of [Target, Transform] must be provided // // New rewrite descriptors can be created. Addding a new rewrite descriptor // involves: // // a) extended the rewrite descriptor kind enumeration // (<anonymous>::RewriteDescriptor::RewriteDescriptorType) // b) implementing the new descriptor // (c.f. <anonymous>::ExplicitRewriteFunctionDescriptor) // c) extending the rewrite map parser // (<anonymous>::RewriteMapParser::parseEntry) // // Specify to rewrite the symbols using the `-rewrite-symbols` option, and // specify the map file to use for the rewriting via the `-rewrite-map-file` // option. // //===----------------------------------------------------------------------===// #include "llvm/Transforms/Utils/SymbolRewriter.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/ilist.h" #include "llvm/ADT/iterator_range.h" #include "llvm/IR/Comdat.h" #include "llvm/IR/Function.h" #include "llvm/IR/GlobalAlias.h" #include "llvm/IR/GlobalObject.h" #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/Module.h" #include "llvm/IR/Value.h" #include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ErrorOr.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Regex.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/YAMLParser.h" #include <memory> #include <string> #include <vector> usingnamespacellvm; usingnamespaceSymbolRewriter; #define DEBUG_TYPE … static cl::list<std::string> RewriteMapFiles("rewrite-map-file", cl::desc("Symbol Rewrite Map"), cl::value_desc("filename"), cl::Hidden); static void rewriteComdat(Module &M, GlobalObject *GO, const std::string &Source, const std::string &Target) { … } namespace { template <RewriteDescriptor::Type DT, typename ValueType, ValueType *(Module::*Get)(StringRef) const> class ExplicitRewriteDescriptor : public RewriteDescriptor { … }; } // end anonymous namespace template <RewriteDescriptor::Type DT, typename ValueType, ValueType *(Module::*Get)(StringRef) const> bool ExplicitRewriteDescriptor<DT, ValueType, Get>::performOnModule(Module &M) { … } namespace { template <RewriteDescriptor::Type DT, typename ValueType, ValueType *(Module::*Get)(StringRef) const, iterator_range<typename iplist<ValueType>::iterator> (Module::*Iterator)()> class PatternRewriteDescriptor : public RewriteDescriptor { … }; } // end anonymous namespace template <RewriteDescriptor::Type DT, typename ValueType, ValueType *(Module::*Get)(StringRef) const, iterator_range<typename iplist<ValueType>::iterator> (Module::*Iterator)()> bool PatternRewriteDescriptor<DT, ValueType, Get, Iterator>:: performOnModule(Module &M) { … } namespace { /// Represents a rewrite for an explicitly named (function) symbol. Both the /// source function name and target function name of the transformation are /// explicitly spelt out. ExplicitRewriteFunctionDescriptor; /// Represents a rewrite for an explicitly named (global variable) symbol. Both /// the source variable name and target variable name are spelt out. This /// applies only to module level variables. ExplicitRewriteGlobalVariableDescriptor; /// Represents a rewrite for an explicitly named global alias. Both the source /// and target name are explicitly spelt out. ExplicitRewriteNamedAliasDescriptor; /// Represents a rewrite for a regular expression based pattern for functions. /// A pattern for the function name is provided and a transformation for that /// pattern to determine the target function name create the rewrite rule. PatternRewriteFunctionDescriptor; /// Represents a rewrite for a global variable based upon a matching pattern. /// Each global variable matching the provided pattern will be transformed as /// described in the transformation pattern for the target. Applies only to /// module level variables. PatternRewriteGlobalVariableDescriptor; /// PatternRewriteNamedAliasDescriptor - represents a rewrite for global /// aliases which match a given pattern. The provided transformation will be /// applied to each of the matching names. PatternRewriteNamedAliasDescriptor; } // end anonymous namespace bool RewriteMapParser::parse(const std::string &MapFile, RewriteDescriptorList *DL) { … } bool RewriteMapParser::parse(std::unique_ptr<MemoryBuffer> &MapFile, RewriteDescriptorList *DL) { … } bool RewriteMapParser::parseEntry(yaml::Stream &YS, yaml::KeyValueNode &Entry, RewriteDescriptorList *DL) { … } bool RewriteMapParser:: parseRewriteFunctionDescriptor(yaml::Stream &YS, yaml::ScalarNode *K, yaml::MappingNode *Descriptor, RewriteDescriptorList *DL) { … } bool RewriteMapParser:: parseRewriteGlobalVariableDescriptor(yaml::Stream &YS, yaml::ScalarNode *K, yaml::MappingNode *Descriptor, RewriteDescriptorList *DL) { … } bool RewriteMapParser:: parseRewriteGlobalAliasDescriptor(yaml::Stream &YS, yaml::ScalarNode *K, yaml::MappingNode *Descriptor, RewriteDescriptorList *DL) { … } PreservedAnalyses RewriteSymbolPass::run(Module &M, ModuleAnalysisManager &AM) { … } bool RewriteSymbolPass::runImpl(Module &M) { … } void RewriteSymbolPass::loadAndParseMapFiles() { … }