LLVM 20.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"
30#include "llvm/IR/Module.h"
31#include "llvm/IR/PassManager.h"
32#include "llvm/IR/Type.h"
33#include "llvm/IR/TypeFinder.h"
35
36using namespace llvm;
37
39 "rename-exclude-function-prefixes",
40 cl::desc("Prefixes for functions that don't need to be renamed, separated "
41 "by a comma"),
43
45 "rename-exclude-alias-prefixes",
46 cl::desc("Prefixes for aliases that don't need to be renamed, separated "
47 "by a comma"),
49
51 "rename-exclude-global-prefixes",
53 "Prefixes for global values that don't need to be renamed, separated "
54 "by a comma"),
56
58 "rename-exclude-struct-prefixes",
59 cl::desc("Prefixes for structs that don't need to be renamed, separated "
60 "by a comma"),
62
63static cl::opt<bool>
64 RenameOnlyInst("rename-only-inst", cl::init(false),
65 cl::desc("only rename the instructions in the function"),
67
68static const char *const metaNames[] = {
69 // See http://en.wikipedia.org/wiki/Metasyntactic_variable
70 "foo", "bar", "baz", "quux", "barney", "snork", "zot", "blam", "hoge",
71 "wibble", "wobble", "widget", "wombat", "ham", "eggs", "pluto", "spam"
72};
73
74namespace {
75// This PRNG is from the ISO C spec. It is intentionally simple and
76// unsuitable for cryptographic use. We're just looking for enough
77// variety to surprise and delight users.
78struct PRNG {
79 unsigned long next;
80
81 void srand(unsigned int seed) { next = seed; }
82
83 int rand() {
84 next = next * 1103515245 + 12345;
85 return (unsigned int)(next / 65536) % 32768;
86 }
87};
88
89struct Renamer {
90 Renamer(unsigned int seed) { prng.srand(seed); }
91
92 const char *newName() {
93 return metaNames[prng.rand() % std::size(metaNames)];
94 }
95
96 PRNG prng;
97};
98
99static void
100parseExcludedPrefixes(StringRef PrefixesStr,
101 SmallVectorImpl<StringRef> &ExcludedPrefixes) {
102 for (;;) {
103 auto PrefixesSplit = PrefixesStr.split(',');
104 if (PrefixesSplit.first.empty())
105 break;
106 ExcludedPrefixes.push_back(PrefixesSplit.first);
107 PrefixesStr = PrefixesSplit.second;
108 }
109}
110
111void MetaRenameOnlyInstructions(Function &F) {
112 for (auto &I : instructions(F))
113 if (!I.getType()->isVoidTy() && I.getName().empty())
114 I.setName(I.getOpcodeName());
115}
116
117void MetaRename(Function &F) {
118 for (Argument &Arg : F.args())
119 if (!Arg.getType()->isVoidTy())
120 Arg.setName("arg");
121
122 for (auto &BB : F) {
123 BB.setName("bb");
124
125 for (auto &I : BB)
126 if (!I.getType()->isVoidTy())
127 I.setName(I.getOpcodeName());
128 }
129}
130
131void MetaRename(Module &M,
133 // Seed our PRNG with simple additive sum of ModuleID. We're looking to
134 // simply avoid always having the same function names, and we need to
135 // remain deterministic.
136 unsigned int randSeed = 0;
137 for (auto C : M.getModuleIdentifier())
138 randSeed += C;
139
140 Renamer renamer(randSeed);
141
142 SmallVector<StringRef, 8> ExcludedAliasesPrefixes;
143 SmallVector<StringRef, 8> ExcludedGlobalsPrefixes;
144 SmallVector<StringRef, 8> ExcludedStructsPrefixes;
145 SmallVector<StringRef, 8> ExcludedFuncPrefixes;
146 parseExcludedPrefixes(RenameExcludeAliasPrefixes, ExcludedAliasesPrefixes);
147 parseExcludedPrefixes(RenameExcludeGlobalPrefixes, ExcludedGlobalsPrefixes);
148 parseExcludedPrefixes(RenameExcludeStructPrefixes, ExcludedStructsPrefixes);
149 parseExcludedPrefixes(RenameExcludeFunctionPrefixes, ExcludedFuncPrefixes);
150
151 auto IsNameExcluded = [](StringRef &Name,
152 SmallVectorImpl<StringRef> &ExcludedPrefixes) {
153 return any_of(ExcludedPrefixes,
154 [&Name](auto &Prefix) { return Name.starts_with(Prefix); });
155 };
156
157 // Leave library functions alone because their presence or absence could
158 // affect the behavior of other passes.
159 auto ExcludeLibFuncs = [&](Function &F) {
160 LibFunc Tmp;
161 StringRef Name = F.getName();
162 return Name.starts_with("llvm.") || (!Name.empty() && Name[0] == 1) ||
163 GetTLI(F).getLibFunc(F, Tmp) ||
164 IsNameExcluded(Name, ExcludedFuncPrefixes);
165 };
166
167 if (RenameOnlyInst) {
168 // Rename all functions
169 for (auto &F : M) {
170 if (ExcludeLibFuncs(F))
171 continue;
172 MetaRenameOnlyInstructions(F);
173 }
174 return;
175 }
176
177 // Rename all aliases
178 for (GlobalAlias &GA : M.aliases()) {
179 StringRef Name = GA.getName();
180 if (Name.starts_with("llvm.") || (!Name.empty() && Name[0] == 1) ||
181 IsNameExcluded(Name, ExcludedAliasesPrefixes))
182 continue;
183
184 GA.setName("alias");
185 }
186
187 // Rename all global variables
188 for (GlobalVariable &GV : M.globals()) {
189 StringRef Name = GV.getName();
190 if (Name.starts_with("llvm.") || (!Name.empty() && Name[0] == 1) ||
191 IsNameExcluded(Name, ExcludedGlobalsPrefixes))
192 continue;
193
194 GV.setName("global");
195 }
196
197 // Rename all struct types
198 TypeFinder StructTypes;
199 StructTypes.run(M, true);
200 for (StructType *STy : StructTypes) {
201 StringRef Name = STy->getName();
202 if (STy->isLiteral() || Name.empty() ||
203 IsNameExcluded(Name, ExcludedStructsPrefixes))
204 continue;
205
206 SmallString<128> NameStorage;
207 STy->setName(
208 (Twine("struct.") + renamer.newName()).toStringRef(NameStorage));
209 }
210
211 // Rename all functions
212 for (auto &F : M) {
213 if (ExcludeLibFuncs(F))
214 continue;
215
216 // Leave @main alone. The output of -metarenamer might be passed to
217 // lli for execution and the latter needs a main entry point.
218 if (F.getName() != "main")
219 F.setName(renamer.newName());
220
221 MetaRename(F);
222 }
223}
224
225} // end anonymous namespace
226
230 auto GetTLI = [&FAM](Function &F) -> TargetLibraryInfo & {
232 };
233 MetaRename(M, GetTLI);
234
235 return PreservedAnalyses::all();
236}
Expand Atomic instructions
std::string Name
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
#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< bool > RenameOnlyInst("rename-only-inst", cl::init(false), cl::desc("only rename the instructions in the function"), 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:68
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)
FunctionAnalysisManager FAM
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:253
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Definition: PassManager.h:410
This class represents an incoming formal argument to a Function.
Definition: Argument.h:31
An analysis over an "outer" IR unit that provides access to an analysis manager over an "inner" IR un...
Definition: PassManager.h:567
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: Analysis.h:111
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: Analysis.h:117
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:573
void push_back(const T &Elt)
Definition: SmallVector.h:413
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1196
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
Definition: StringRef.h:700
Class to represent struct types.
Definition: DerivedTypes.h:218
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
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:443
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:1746
PreservedAnalyses run(Module &, ModuleAnalysisManager &)