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
15 #include "llvm/Transforms/Utils/MetaRenamer.h"
16 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/ADT/SmallString.h"
18 #include "llvm/ADT/SmallVector.h"
19 #include "llvm/ADT/StringRef.h"
20 #include "llvm/ADT/Twine.h"
21 #include "llvm/Analysis/TargetLibraryInfo.h"
22 #include "llvm/IR/Argument.h"
23 #include "llvm/IR/BasicBlock.h"
24 #include "llvm/IR/DerivedTypes.h"
25 #include "llvm/IR/Function.h"
26 #include "llvm/IR/GlobalAlias.h"
27 #include "llvm/IR/GlobalVariable.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"
33 #include "llvm/InitializePasses.h"
34 #include "llvm/Pass.h"
35 #include "llvm/Support/CommandLine.h"
36 #include "llvm/Transforms/Utils.h"
37
38 using namespace llvm;
39
40 static cl::opt<std::string> RenameExcludeFunctionPrefixes(
41 "rename-exclude-function-prefixes",
42 cl::desc("Prefixes for functions that don't need to be renamed, separated "
43 "by a comma"),
44 cl::Hidden);
45
46 static cl::opt<std::string> RenameExcludeAliasPrefixes(
47 "rename-exclude-alias-prefixes",
48 cl::desc("Prefixes for aliases that don't need to be renamed, separated "
49 "by a comma"),
50 cl::Hidden);
51
52 static cl::opt<std::string> RenameExcludeGlobalPrefixes(
53 "rename-exclude-global-prefixes",
54 cl::desc(
55 "Prefixes for global values that don't need to be renamed, separated "
56 "by a comma"),
57 cl::Hidden);
58
59 static cl::opt<std::string> RenameExcludeStructPrefixes(
60 "rename-exclude-struct-prefixes",
61 cl::desc("Prefixes for structs that don't need to be renamed, separated "
62 "by a comma"),
63 cl::Hidden);
64
65 static const char *const metaNames[] = {
66 // See http://en.wikipedia.org/wiki/Metasyntactic_variable
67 "foo", "bar", "baz", "quux", "barney", "snork", "zot", "blam", "hoge",
68 "wibble", "wobble", "widget", "wombat", "ham", "eggs", "pluto", "spam"
69 };
70
71 namespace {
72 // This PRNG is from the ISO C spec. It is intentionally simple and
73 // unsuitable for cryptographic use. We're just looking for enough
74 // variety to surprise and delight users.
75 struct PRNG {
76 unsigned long next;
77
srand__anon4d72f7160111::PRNG78 void srand(unsigned int seed) { next = seed; }
79
rand__anon4d72f7160111::PRNG80 int rand() {
81 next = next * 1103515245 + 12345;
82 return (unsigned int)(next / 65536) % 32768;
83 }
84 };
85
86 struct Renamer {
Renamer__anon4d72f7160111::Renamer87 Renamer(unsigned int seed) { prng.srand(seed); }
88
newName__anon4d72f7160111::Renamer89 const char *newName() {
90 return metaNames[prng.rand() % std::size(metaNames)];
91 }
92
93 PRNG prng;
94 };
95
96 static void
parseExcludedPrefixes(StringRef PrefixesStr,SmallVectorImpl<StringRef> & ExcludedPrefixes)97 parseExcludedPrefixes(StringRef PrefixesStr,
98 SmallVectorImpl<StringRef> &ExcludedPrefixes) {
99 for (;;) {
100 auto PrefixesSplit = PrefixesStr.split(',');
101 if (PrefixesSplit.first.empty())
102 break;
103 ExcludedPrefixes.push_back(PrefixesSplit.first);
104 PrefixesStr = PrefixesSplit.second;
105 }
106 }
107
MetaRename(Function & F)108 void MetaRename(Function &F) {
109 for (Argument &Arg : F.args())
110 if (!Arg.getType()->isVoidTy())
111 Arg.setName("arg");
112
113 for (auto &BB : F) {
114 BB.setName("bb");
115
116 for (auto &I : BB)
117 if (!I.getType()->isVoidTy())
118 I.setName("tmp");
119 }
120 }
121
MetaRename(Module & M,function_ref<TargetLibraryInfo & (Function &)> GetTLI)122 void MetaRename(Module &M,
123 function_ref<TargetLibraryInfo &(Function &)> GetTLI) {
124 // Seed our PRNG with simple additive sum of ModuleID. We're looking to
125 // simply avoid always having the same function names, and we need to
126 // remain deterministic.
127 unsigned int randSeed = 0;
128 for (auto C : M.getModuleIdentifier())
129 randSeed += C;
130
131 Renamer renamer(randSeed);
132
133 SmallVector<StringRef, 8> ExcludedAliasesPrefixes;
134 SmallVector<StringRef, 8> ExcludedGlobalsPrefixes;
135 SmallVector<StringRef, 8> ExcludedStructsPrefixes;
136 SmallVector<StringRef, 8> ExcludedFuncPrefixes;
137 parseExcludedPrefixes(RenameExcludeAliasPrefixes, ExcludedAliasesPrefixes);
138 parseExcludedPrefixes(RenameExcludeGlobalPrefixes, ExcludedGlobalsPrefixes);
139 parseExcludedPrefixes(RenameExcludeStructPrefixes, ExcludedStructsPrefixes);
140 parseExcludedPrefixes(RenameExcludeFunctionPrefixes, ExcludedFuncPrefixes);
141
142 auto IsNameExcluded = [](StringRef &Name,
143 SmallVectorImpl<StringRef> &ExcludedPrefixes) {
144 return any_of(ExcludedPrefixes,
145 [&Name](auto &Prefix) { return Name.startswith(Prefix); });
146 };
147
148 // Rename all aliases
149 for (GlobalAlias &GA : M.aliases()) {
150 StringRef Name = GA.getName();
151 if (Name.startswith("llvm.") || (!Name.empty() && Name[0] == 1) ||
152 IsNameExcluded(Name, ExcludedAliasesPrefixes))
153 continue;
154
155 GA.setName("alias");
156 }
157
158 // Rename all global variables
159 for (GlobalVariable &GV : M.globals()) {
160 StringRef Name = GV.getName();
161 if (Name.startswith("llvm.") || (!Name.empty() && Name[0] == 1) ||
162 IsNameExcluded(Name, ExcludedGlobalsPrefixes))
163 continue;
164
165 GV.setName("global");
166 }
167
168 // Rename all struct types
169 TypeFinder StructTypes;
170 StructTypes.run(M, true);
171 for (StructType *STy : StructTypes) {
172 StringRef Name = STy->getName();
173 if (STy->isLiteral() || Name.empty() ||
174 IsNameExcluded(Name, ExcludedStructsPrefixes))
175 continue;
176
177 SmallString<128> NameStorage;
178 STy->setName(
179 (Twine("struct.") + renamer.newName()).toStringRef(NameStorage));
180 }
181
182 // Rename all functions
183 for (auto &F : M) {
184 StringRef Name = F.getName();
185 LibFunc Tmp;
186 // Leave library functions alone because their presence or absence could
187 // affect the behavior of other passes.
188 if (Name.startswith("llvm.") || (!Name.empty() && Name[0] == 1) ||
189 GetTLI(F).getLibFunc(F, Tmp) ||
190 IsNameExcluded(Name, ExcludedFuncPrefixes))
191 continue;
192
193 // Leave @main alone. The output of -metarenamer might be passed to
194 // lli for execution and the latter needs a main entry point.
195 if (Name != "main")
196 F.setName(renamer.newName());
197
198 MetaRename(F);
199 }
200 }
201
202 struct MetaRenamer : public ModulePass {
203 // Pass identification, replacement for typeid
204 static char ID;
205
MetaRenamer__anon4d72f7160111::MetaRenamer206 MetaRenamer() : ModulePass(ID) {
207 initializeMetaRenamerPass(*PassRegistry::getPassRegistry());
208 }
209
getAnalysisUsage__anon4d72f7160111::MetaRenamer210 void getAnalysisUsage(AnalysisUsage &AU) const override {
211 AU.addRequired<TargetLibraryInfoWrapperPass>();
212 AU.setPreservesAll();
213 }
214
runOnModule__anon4d72f7160111::MetaRenamer215 bool runOnModule(Module &M) override {
216 auto GetTLI = [this](Function &F) -> TargetLibraryInfo & {
217 return this->getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F);
218 };
219 MetaRename(M, GetTLI);
220 return true;
221 }
222 };
223
224 } // end anonymous namespace
225
226 char MetaRenamer::ID = 0;
227
228 INITIALIZE_PASS_BEGIN(MetaRenamer, "metarenamer",
229 "Assign new names to everything", false, false)
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)230 INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
231 INITIALIZE_PASS_END(MetaRenamer, "metarenamer",
232 "Assign new names to everything", false, false)
233
234 //===----------------------------------------------------------------------===//
235 //
236 // MetaRenamer - Rename everything with metasyntactic names.
237 //
238 ModulePass *llvm::createMetaRenamerPass() {
239 return new MetaRenamer();
240 }
241
run(Module & M,ModuleAnalysisManager & AM)242 PreservedAnalyses MetaRenamerPass::run(Module &M, ModuleAnalysisManager &AM) {
243 FunctionAnalysisManager &FAM =
244 AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
245 auto GetTLI = [&FAM](Function &F) -> TargetLibraryInfo & {
246 return FAM.getResult<TargetLibraryAnalysis>(F);
247 };
248 MetaRename(M, GetTLI);
249
250 return PreservedAnalyses::all();
251 }
252