237 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9// This pass renames everything with metasyntatic names. The intent is to use10// this pass after bugpoint reduction to conceal the nature of the original11// 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 36using namespace llvm;37 38static 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 44static 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 50static 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 57static 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 63static 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 68static const char *const metaNames[] = {69 // See http://en.wikipedia.org/wiki/Metasyntactic_variable70 "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 and76// unsuitable for cryptographic use. We're just looking for enough77// 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 void100parseExcludedPrefixes(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,132 function_ref<TargetLibraryInfo &(Function &)> GetTLI) {133 // Seed our PRNG with simple additive sum of ModuleID. We're looking to134 // simply avoid always having the same function names, and we need to135 // 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 could158 // affect the behavior of other passes.159 auto ExcludeLibFuncs = [&](Function &F) {160 LibFunc Tmp;161 StringRef Name = F.getName();162 return F.isIntrinsic() || (!Name.empty() && Name[0] == 1) ||163 GetTLI(F).getLibFunc(F, Tmp) ||164 IsNameExcluded(Name, ExcludedFuncPrefixes);165 };166 167 if (RenameOnlyInst) {168 // Rename all functions169 for (auto &F : M) {170 if (ExcludeLibFuncs(F))171 continue;172 MetaRenameOnlyInstructions(F);173 }174 return;175 }176 177 // Rename all aliases178 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 variables188 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 types198 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 functions212 for (auto &F : M) {213 if (ExcludeLibFuncs(F))214 continue;215 216 // Leave @main alone. The output of -metarenamer might be passed to217 // 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 namespace226 227PreservedAnalyses 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