LLVM 17.0.0git
MetaRenamer.cpp
Go to the documentation of this file.
1//===- MetaRenamer.cpp - Rename everything with metasyntatic names --------===//
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-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This pass renames everything with metasyntatic names. The intent is to use
10// this pass after bugpoint reduction to conceal the nature of the original
11// program.
12//
13//===----------------------------------------------------------------------===//
14
16#include "llvm/ADT/STLExtras.h"
19#include "llvm/ADT/StringRef.h"
20#include "llvm/ADT/Twine.h"
22#include "llvm/IR/Argument.h"
23#include "llvm/IR/BasicBlock.h"
25#include "llvm/IR/Function.h"
26#include "llvm/IR/GlobalAlias.h"
28#include "llvm/IR/Instruction.h"
29#include "llvm/IR/Module.h"
30#include "llvm/IR/PassManager.h"
31#include "llvm/IR/Type.h"
32#include "llvm/IR/TypeFinder.h"
34
35using namespace llvm;
36
38 "rename-exclude-function-prefixes",
39 cl::desc("Prefixes for functions that don't need to be renamed, separated "
40 "by a comma"),
42
44 "rename-exclude-alias-prefixes",
45 cl::desc("Prefixes for aliases that don't need to be renamed, separated "
46 "by a comma"),
48
50 "rename-exclude-global-prefixes",
52 "Prefixes for global values that don't need to be renamed, separated "
53 "by a comma"),
55
57 "rename-exclude-struct-prefixes",
58 cl::desc("Prefixes for structs that don't need to be renamed, separated "
59 "by a comma"),
61
62static const char *const metaNames[] = {
63 // See http://en.wikipedia.org/wiki/Metasyntactic_variable
64 "foo", "bar", "baz", "quux", "barney", "snork", "zot", "blam", "hoge",
65 "wibble", "wobble", "widget", "wombat", "ham", "eggs", "pluto", "spam"
66};
67
68namespace {
69// This PRNG is from the ISO C spec. It is intentionally simple and
70// unsuitable for cryptographic use. We're just looking for enough
71// variety to surprise and delight users.
72struct PRNG {
73 unsigned long next;
74
75 void srand(unsigned int seed) { next = seed; }
76
77 int rand() {
78 next = next * 1103515245 + 12345;
79 return (unsigned int)(next / 65536) % 32768;
80 }
81};
82
83struct Renamer {
84 Renamer(unsigned int seed) { prng.srand(seed); }
85
86 const char *newName() {
87 return metaNames[prng.rand() % std::size(metaNames)];
88 }
89
90 PRNG prng;
91};
92
93static void
94parseExcludedPrefixes(StringRef PrefixesStr,
95 SmallVectorImpl<StringRef> &ExcludedPrefixes) {
96 for (;;) {
97 auto PrefixesSplit = PrefixesStr.split(',');
98 if (PrefixesSplit.first.empty())
99 break;
100 ExcludedPrefixes.push_back(PrefixesSplit.first);
101 PrefixesStr = PrefixesSplit.second;
102 }
103}
104
105void MetaRename(Function &F) {
106 for (Argument &Arg : F.args())
107 if (!Arg.getType()->isVoidTy())
108 Arg.setName("arg");
109
110 for (auto &BB : F) {
111 BB.setName("bb");
112
113 for (auto &I : BB)
114 if (!I.getType()->isVoidTy())
115 I.setName(I.getOpcodeName());
116 }
117}
118
119void MetaRename(Module &M,
121 // Seed our PRNG with simple additive sum of ModuleID. We're looking to
122 // simply avoid always having the same function names, and we need to
123 // remain deterministic.
124 unsigned int randSeed = 0;
125 for (auto C : M.getModuleIdentifier())
126 randSeed += C;
127
128 Renamer renamer(randSeed);
129
130 SmallVector<StringRef, 8> ExcludedAliasesPrefixes;
131 SmallVector<StringRef, 8> ExcludedGlobalsPrefixes;
132 SmallVector<StringRef, 8> ExcludedStructsPrefixes;
133 SmallVector<StringRef, 8> ExcludedFuncPrefixes;
134 parseExcludedPrefixes(RenameExcludeAliasPrefixes, ExcludedAliasesPrefixes);
135 parseExcludedPrefixes(RenameExcludeGlobalPrefixes, ExcludedGlobalsPrefixes);
136 parseExcludedPrefixes(RenameExcludeStructPrefixes, ExcludedStructsPrefixes);
137 parseExcludedPrefixes(RenameExcludeFunctionPrefixes, ExcludedFuncPrefixes);
138
139 auto IsNameExcluded = [](StringRef &Name,
140 SmallVectorImpl<StringRef> &ExcludedPrefixes) {
141 return any_of(ExcludedPrefixes,
142 [&Name](auto &Prefix) { return Name.startswith(Prefix); });
143 };
144
145 // Rename all aliases
146 for (GlobalAlias &GA : M.aliases()) {
147 StringRef Name = GA.getName();
148 if (Name.startswith("llvm.") || (!Name.empty() && Name[0] == 1) ||
149 IsNameExcluded(Name, ExcludedAliasesPrefixes))
150 continue;
151
152 GA.setName("alias");
153 }
154
155 // Rename all global variables
156 for (GlobalVariable &GV : M.globals()) {
157 StringRef Name = GV.getName();
158 if (Name.startswith("llvm.") || (!Name.empty() && Name[0] == 1) ||
159 IsNameExcluded(Name, ExcludedGlobalsPrefixes))
160 continue;
161
162 GV.setName("global");
163 }
164
165 // Rename all struct types
166 TypeFinder StructTypes;
167 StructTypes.run(M, true);
168 for (StructType *STy : StructTypes) {
169 StringRef Name = STy->getName();
170 if (STy->isLiteral() || Name.empty() ||
171 IsNameExcluded(Name, ExcludedStructsPrefixes))
172 continue;
173
174 SmallString<128> NameStorage;
175 STy->setName(
176 (Twine("struct.") + renamer.newName()).toStringRef(NameStorage));
177 }
178
179 // Rename all functions
180 for (auto &F : M) {
181 StringRef Name = F.getName();
182 LibFunc Tmp;
183 // Leave library functions alone because their presence or absence could
184 // affect the behavior of other passes.
185 if (Name.startswith("llvm.") || (!Name.empty() && Name[0] == 1) ||
186 GetTLI(F).getLibFunc(F, Tmp) ||
187 IsNameExcluded(Name, ExcludedFuncPrefixes))
188 continue;
189
190 // Leave @main alone. The output of -metarenamer might be passed to
191 // lli for execution and the latter needs a main entry point.
192 if (Name != "main")
193 F.setName(renamer.newName());
194
195 MetaRename(F);
196 }
197}
198
199} // end anonymous namespace
200
204 auto GetTLI = [&FAM](Function &F) -> TargetLibraryInfo & {
206 };
207 MetaRename(M, GetTLI);
208
209 return PreservedAnalyses::all();
210}
amdgpu Simplify well known AMD library false FunctionCallee Value * Arg
std::string Name
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
static cl::opt< std::string > RenameExcludeFunctionPrefixes("rename-exclude-function-prefixes", cl::desc("Prefixes for functions that don't need to be renamed, separated " "by a comma"), cl::Hidden)
static cl::opt< std::string > RenameExcludeStructPrefixes("rename-exclude-struct-prefixes", cl::desc("Prefixes for structs that don't need to be renamed, separated " "by a comma"), cl::Hidden)
static cl::opt< std::string > RenameExcludeGlobalPrefixes("rename-exclude-global-prefixes", cl::desc("Prefixes for global values that don't need to be renamed, separated " "by a comma"), cl::Hidden)
static const char *const metaNames[]
Definition: MetaRenamer.cpp:62
static cl::opt< std::string > RenameExcludeAliasPrefixes("rename-exclude-alias-prefixes", cl::desc("Prefixes for aliases that don't need to be renamed, separated " "by a comma"), cl::Hidden)
Module.h This file contains the declarations for the Module class.
FunctionAnalysisManager FAM
This header defines various interfaces for pass management in LLVM.
This file contains some templates that are useful if you are working with the STL at all.
This file defines the SmallString class.
This file defines the SmallVector class.
A container for analyses that lazily runs them and caches their results.
Definition: PassManager.h:620
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Definition: PassManager.h:774
This class represents an incoming formal argument to a Function.
Definition: Argument.h:28
An analysis over an "outer" IR unit that provides access to an analysis manager over an "inner" IR un...
Definition: PassManager.h:933
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
A set of analyses that are preserved following a run of a transformation pass.
Definition: PassManager.h:152
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: PassManager.h:158
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition: SmallString.h:26
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:577
void push_back(const T &Elt)
Definition: SmallVector.h:416
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1200
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
Definition: StringRef.h:698
Class to represent struct types.
Definition: DerivedTypes.h:213
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
TypeFinder - Walk over a module, identifying all of the types that are used by the module.
Definition: TypeFinder.h:31
void run(const Module &M, bool onlyNamed)
Definition: TypeFinder.cpp:34
An efficient, type-erasing, non-owning reference to a callable.
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1826
PreservedAnalyses run(Module &, ModuleAnalysisManager &)