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/InstIterator.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" 34 #include "llvm/Support/CommandLine.h" 35 36 using namespace llvm; 37 38 static cl::opt<std::string> RenameExcludeFunctionPrefixes( 39 "rename-exclude-function-prefixes", 40 cl::desc("Prefixes for functions that don't need to be renamed, separated " 41 "by a comma"), 42 cl::Hidden); 43 44 static cl::opt<std::string> RenameExcludeAliasPrefixes( 45 "rename-exclude-alias-prefixes", 46 cl::desc("Prefixes for aliases that don't need to be renamed, separated " 47 "by a comma"), 48 cl::Hidden); 49 50 static cl::opt<std::string> RenameExcludeGlobalPrefixes( 51 "rename-exclude-global-prefixes", 52 cl::desc( 53 "Prefixes for global values that don't need to be renamed, separated " 54 "by a comma"), 55 cl::Hidden); 56 57 static cl::opt<std::string> RenameExcludeStructPrefixes( 58 "rename-exclude-struct-prefixes", 59 cl::desc("Prefixes for structs that don't need to be renamed, separated " 60 "by a comma"), 61 cl::Hidden); 62 63 static cl::opt<bool> 64 RenameOnlyInst("rename-only-inst", cl::init(false), 65 cl::desc("only rename the instructions in the function"), 66 cl::Hidden); 67 68 static 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 74 namespace { 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. 78 struct 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 89 struct 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 99 static void 100 parseExcludedPrefixes(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 111 void MetaRenameOnlyInstructions(Function &F) { 112 for (auto &I : instructions(F)) 113 if (!I.getType()->isVoidTy() && I.getName().empty()) 114 I.setName(I.getOpcodeName()); 115 } 116 117 void 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 131 void MetaRename(Module &M, 132 function_ref<TargetLibraryInfo &(Function &)> GetTLI) { 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 227 PreservedAnalyses MetaRenamerPass::run(Module &M, ModuleAnalysisManager &AM) { 228 FunctionAnalysisManager &FAM = 229 AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager(); 230 auto GetTLI = [&FAM](Function &F) -> TargetLibraryInfo & { 231 return FAM.getResult<TargetLibraryAnalysis>(F); 232 }; 233 MetaRename(M, GetTLI); 234 235 return PreservedAnalyses::all(); 236 } 237