Line data Source code
1 : //===- SymbolRewriter.h - Symbol Rewriting Pass -----------------*- C++ -*-===//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 : //
10 : // This file provides the prototypes and definitions related to the Symbol
11 : // Rewriter pass.
12 : //
13 : // The Symbol Rewriter pass takes a set of rewrite descriptors which define
14 : // transformations for symbol names. These can be either single name to name
15 : // trnsformation or more broad regular expression based transformations.
16 : //
17 : // All the functions are re-written at the IR level. The Symbol Rewriter itself
18 : // is exposed as a module level pass. All symbols at the module level are
19 : // iterated. For any matching symbol, the requested transformation is applied,
20 : // updating references to it as well (a la RAUW). The resulting binary will
21 : // only contain the rewritten symbols.
22 : //
23 : // By performing this operation in the compiler, we are able to catch symbols
24 : // that would otherwise not be possible to catch (e.g. inlined symbols).
25 : //
26 : // This makes it possible to cleanly transform symbols without resorting to
27 : // overly-complex macro tricks and the pre-processor. An example of where this
28 : // is useful is the sanitizers where we would like to intercept a well-defined
29 : // set of functions across the module.
30 : //
31 : //===----------------------------------------------------------------------===//
32 :
33 : #ifndef LLVM_TRANSFORMS_UTILS_SYMBOLREWRITER_H
34 : #define LLVM_TRANSFORMS_UTILS_SYMBOLREWRITER_H
35 :
36 : #include "llvm/IR/PassManager.h"
37 : #include <list>
38 : #include <memory>
39 : #include <string>
40 :
41 : namespace llvm {
42 :
43 : class MemoryBuffer;
44 : class Module;
45 : class ModulePass;
46 :
47 : namespace yaml {
48 :
49 : class KeyValueNode;
50 : class MappingNode;
51 : class ScalarNode;
52 : class Stream;
53 :
54 : } // end namespace yaml
55 :
56 : namespace SymbolRewriter {
57 :
58 : /// The basic entity representing a rewrite operation. It serves as the base
59 : /// class for any rewrite descriptor. It has a certain set of specializations
60 : /// which describe a particular rewrite.
61 : ///
62 : /// The RewriteMapParser can be used to parse a mapping file that provides the
63 : /// mapping for rewriting the symbols. The descriptors individually describe
64 : /// whether to rewrite a function, global variable, or global alias. Each of
65 : /// these can be selected either by explicitly providing a name for the ones to
66 : /// be rewritten or providing a (posix compatible) regular expression that will
67 : /// select the symbols to rewrite. This descriptor list is passed to the
68 : /// SymbolRewriter pass.
69 : class RewriteDescriptor {
70 : public:
71 : enum class Type {
72 : Invalid, /// invalid
73 : Function, /// function - descriptor rewrites a function
74 : GlobalVariable, /// global variable - descriptor rewrites a global variable
75 : NamedAlias, /// named alias - descriptor rewrites a global alias
76 : };
77 :
78 : RewriteDescriptor(const RewriteDescriptor &) = delete;
79 : RewriteDescriptor &operator=(const RewriteDescriptor &) = delete;
80 0 : virtual ~RewriteDescriptor() = default;
81 :
82 : Type getType() const { return Kind; }
83 :
84 : virtual bool performOnModule(Module &M) = 0;
85 :
86 : protected:
87 26 : explicit RewriteDescriptor(Type T) : Kind(T) {}
88 :
89 : private:
90 : const Type Kind;
91 : };
92 :
93 : using RewriteDescriptorList = std::list<std::unique_ptr<RewriteDescriptor>>;
94 :
95 : class RewriteMapParser {
96 : public:
97 : bool parse(const std::string &MapFile, RewriteDescriptorList *Descriptors);
98 :
99 : private:
100 : bool parse(std::unique_ptr<MemoryBuffer> &MapFile, RewriteDescriptorList *DL);
101 : bool parseEntry(yaml::Stream &Stream, yaml::KeyValueNode &Entry,
102 : RewriteDescriptorList *DL);
103 : bool parseRewriteFunctionDescriptor(yaml::Stream &Stream,
104 : yaml::ScalarNode *Key,
105 : yaml::MappingNode *Value,
106 : RewriteDescriptorList *DL);
107 : bool parseRewriteGlobalVariableDescriptor(yaml::Stream &Stream,
108 : yaml::ScalarNode *Key,
109 : yaml::MappingNode *Value,
110 : RewriteDescriptorList *DL);
111 : bool parseRewriteGlobalAliasDescriptor(yaml::Stream &YS, yaml::ScalarNode *K,
112 : yaml::MappingNode *V,
113 : RewriteDescriptorList *DL);
114 : };
115 :
116 : } // end namespace SymbolRewriter
117 :
118 : ModulePass *createRewriteSymbolsPass();
119 : ModulePass *createRewriteSymbolsPass(SymbolRewriter::RewriteDescriptorList &);
120 :
121 : class RewriteSymbolPass : public PassInfoMixin<RewriteSymbolPass> {
122 : public:
123 27455 : RewriteSymbolPass() { loadAndParseMapFiles(); }
124 :
125 0 : RewriteSymbolPass(SymbolRewriter::RewriteDescriptorList &DL) {
126 : Descriptors.splice(Descriptors.begin(), DL);
127 0 : }
128 :
129 : PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
130 :
131 : // Glue for old PM
132 : bool runImpl(Module &M);
133 :
134 : private:
135 : void loadAndParseMapFiles();
136 :
137 : SymbolRewriter::RewriteDescriptorList Descriptors;
138 : };
139 :
140 : } // end namespace llvm
141 :
142 : #endif //LLVM_TRANSFORMS_UTILS_SYMBOLREWRITER_H
|