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/Support/CommandLine.h" 34 35 using namespace llvm; 36 37 static cl::opt<std::string> RenameExcludeFunctionPrefixes( 38 "rename-exclude-function-prefixes", 39 cl::desc("Prefixes for functions that don't need to be renamed, separated " 40 "by a comma"), 41 cl::Hidden); 42 43 static cl::opt<std::string> RenameExcludeAliasPrefixes( 44 "rename-exclude-alias-prefixes", 45 cl::desc("Prefixes for aliases that don't need to be renamed, separated " 46 "by a comma"), 47 cl::Hidden); 48 49 static cl::opt<std::string> RenameExcludeGlobalPrefixes( 50 "rename-exclude-global-prefixes", 51 cl::desc( 52 "Prefixes for global values that don't need to be renamed, separated " 53 "by a comma"), 54 cl::Hidden); 55 56 static cl::opt<std::string> RenameExcludeStructPrefixes( 57 "rename-exclude-struct-prefixes", 58 cl::desc("Prefixes for structs that don't need to be renamed, separated " 59 "by a comma"), 60 cl::Hidden); 61 62 static 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 68 namespace { 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. 72 struct 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 83 struct 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 93 static void 94 parseExcludedPrefixes(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 105 void 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 119 void MetaRename(Module &M, 120 function_ref<TargetLibraryInfo &(Function &)> GetTLI) { 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 201 PreservedAnalyses MetaRenamerPass::run(Module &M, ModuleAnalysisManager &AM) { 202 FunctionAnalysisManager &FAM = 203 AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager(); 204 auto GetTLI = [&FAM](Function &F) -> TargetLibraryInfo & { 205 return FAM.getResult<TargetLibraryAnalysis>(F); 206 }; 207 MetaRename(M, GetTLI); 208 209 return PreservedAnalyses::all(); 210 } 211