109467b48Spatrick //===- MetaRenamer.cpp - Rename everything with metasyntatic names --------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick // This pass renames everything with metasyntatic names. The intent is to use
1009467b48Spatrick // this pass after bugpoint reduction to conceal the nature of the original
1109467b48Spatrick // program.
1209467b48Spatrick //
1309467b48Spatrick //===----------------------------------------------------------------------===//
1409467b48Spatrick
1573471bf0Spatrick #include "llvm/Transforms/Utils/MetaRenamer.h"
1609467b48Spatrick #include "llvm/ADT/STLExtras.h"
1709467b48Spatrick #include "llvm/ADT/SmallString.h"
18*d415bd75Srobert #include "llvm/ADT/SmallVector.h"
1909467b48Spatrick #include "llvm/ADT/StringRef.h"
2009467b48Spatrick #include "llvm/ADT/Twine.h"
2109467b48Spatrick #include "llvm/Analysis/TargetLibraryInfo.h"
2209467b48Spatrick #include "llvm/IR/Argument.h"
2309467b48Spatrick #include "llvm/IR/BasicBlock.h"
2409467b48Spatrick #include "llvm/IR/DerivedTypes.h"
2509467b48Spatrick #include "llvm/IR/Function.h"
2609467b48Spatrick #include "llvm/IR/GlobalAlias.h"
2709467b48Spatrick #include "llvm/IR/GlobalVariable.h"
2809467b48Spatrick #include "llvm/IR/Instruction.h"
2909467b48Spatrick #include "llvm/IR/Module.h"
3073471bf0Spatrick #include "llvm/IR/PassManager.h"
3109467b48Spatrick #include "llvm/IR/Type.h"
3209467b48Spatrick #include "llvm/IR/TypeFinder.h"
3309467b48Spatrick #include "llvm/InitializePasses.h"
3409467b48Spatrick #include "llvm/Pass.h"
35*d415bd75Srobert #include "llvm/Support/CommandLine.h"
3609467b48Spatrick #include "llvm/Transforms/Utils.h"
3709467b48Spatrick
3809467b48Spatrick using namespace llvm;
3909467b48Spatrick
40*d415bd75Srobert static cl::opt<std::string> RenameExcludeFunctionPrefixes(
41*d415bd75Srobert "rename-exclude-function-prefixes",
42*d415bd75Srobert cl::desc("Prefixes for functions that don't need to be renamed, separated "
43*d415bd75Srobert "by a comma"),
44*d415bd75Srobert cl::Hidden);
45*d415bd75Srobert
46*d415bd75Srobert static cl::opt<std::string> RenameExcludeAliasPrefixes(
47*d415bd75Srobert "rename-exclude-alias-prefixes",
48*d415bd75Srobert cl::desc("Prefixes for aliases that don't need to be renamed, separated "
49*d415bd75Srobert "by a comma"),
50*d415bd75Srobert cl::Hidden);
51*d415bd75Srobert
52*d415bd75Srobert static cl::opt<std::string> RenameExcludeGlobalPrefixes(
53*d415bd75Srobert "rename-exclude-global-prefixes",
54*d415bd75Srobert cl::desc(
55*d415bd75Srobert "Prefixes for global values that don't need to be renamed, separated "
56*d415bd75Srobert "by a comma"),
57*d415bd75Srobert cl::Hidden);
58*d415bd75Srobert
59*d415bd75Srobert static cl::opt<std::string> RenameExcludeStructPrefixes(
60*d415bd75Srobert "rename-exclude-struct-prefixes",
61*d415bd75Srobert cl::desc("Prefixes for structs that don't need to be renamed, separated "
62*d415bd75Srobert "by a comma"),
63*d415bd75Srobert cl::Hidden);
64*d415bd75Srobert
6509467b48Spatrick static const char *const metaNames[] = {
6609467b48Spatrick // See http://en.wikipedia.org/wiki/Metasyntactic_variable
6709467b48Spatrick "foo", "bar", "baz", "quux", "barney", "snork", "zot", "blam", "hoge",
6809467b48Spatrick "wibble", "wobble", "widget", "wombat", "ham", "eggs", "pluto", "spam"
6909467b48Spatrick };
7009467b48Spatrick
7109467b48Spatrick namespace {
7209467b48Spatrick // This PRNG is from the ISO C spec. It is intentionally simple and
7309467b48Spatrick // unsuitable for cryptographic use. We're just looking for enough
7409467b48Spatrick // variety to surprise and delight users.
7509467b48Spatrick struct PRNG {
7609467b48Spatrick unsigned long next;
7709467b48Spatrick
srand__anon4d72f7160111::PRNG7873471bf0Spatrick void srand(unsigned int seed) { next = seed; }
7909467b48Spatrick
rand__anon4d72f7160111::PRNG8009467b48Spatrick int rand() {
8109467b48Spatrick next = next * 1103515245 + 12345;
8209467b48Spatrick return (unsigned int)(next / 65536) % 32768;
8309467b48Spatrick }
8409467b48Spatrick };
8509467b48Spatrick
8609467b48Spatrick struct Renamer {
Renamer__anon4d72f7160111::Renamer8773471bf0Spatrick Renamer(unsigned int seed) { prng.srand(seed); }
8809467b48Spatrick
newName__anon4d72f7160111::Renamer8909467b48Spatrick const char *newName() {
90*d415bd75Srobert return metaNames[prng.rand() % std::size(metaNames)];
9109467b48Spatrick }
9209467b48Spatrick
9309467b48Spatrick PRNG prng;
9409467b48Spatrick };
9509467b48Spatrick
96*d415bd75Srobert static void
parseExcludedPrefixes(StringRef PrefixesStr,SmallVectorImpl<StringRef> & ExcludedPrefixes)97*d415bd75Srobert parseExcludedPrefixes(StringRef PrefixesStr,
98*d415bd75Srobert SmallVectorImpl<StringRef> &ExcludedPrefixes) {
99*d415bd75Srobert for (;;) {
100*d415bd75Srobert auto PrefixesSplit = PrefixesStr.split(',');
101*d415bd75Srobert if (PrefixesSplit.first.empty())
102*d415bd75Srobert break;
103*d415bd75Srobert ExcludedPrefixes.push_back(PrefixesSplit.first);
104*d415bd75Srobert PrefixesStr = PrefixesSplit.second;
105*d415bd75Srobert }
106*d415bd75Srobert }
107*d415bd75Srobert
MetaRename(Function & F)10873471bf0Spatrick void MetaRename(Function &F) {
10973471bf0Spatrick for (Argument &Arg : F.args())
11073471bf0Spatrick if (!Arg.getType()->isVoidTy())
11173471bf0Spatrick Arg.setName("arg");
11209467b48Spatrick
11373471bf0Spatrick for (auto &BB : F) {
11473471bf0Spatrick BB.setName("bb");
11573471bf0Spatrick
11673471bf0Spatrick for (auto &I : BB)
11773471bf0Spatrick if (!I.getType()->isVoidTy())
11873471bf0Spatrick I.setName("tmp");
11973471bf0Spatrick }
12009467b48Spatrick }
12109467b48Spatrick
MetaRename(Module & M,function_ref<TargetLibraryInfo & (Function &)> GetTLI)12273471bf0Spatrick void MetaRename(Module &M,
12373471bf0Spatrick function_ref<TargetLibraryInfo &(Function &)> GetTLI) {
12409467b48Spatrick // Seed our PRNG with simple additive sum of ModuleID. We're looking to
12509467b48Spatrick // simply avoid always having the same function names, and we need to
12609467b48Spatrick // remain deterministic.
12709467b48Spatrick unsigned int randSeed = 0;
12809467b48Spatrick for (auto C : M.getModuleIdentifier())
12909467b48Spatrick randSeed += C;
13009467b48Spatrick
13109467b48Spatrick Renamer renamer(randSeed);
13209467b48Spatrick
133*d415bd75Srobert SmallVector<StringRef, 8> ExcludedAliasesPrefixes;
134*d415bd75Srobert SmallVector<StringRef, 8> ExcludedGlobalsPrefixes;
135*d415bd75Srobert SmallVector<StringRef, 8> ExcludedStructsPrefixes;
136*d415bd75Srobert SmallVector<StringRef, 8> ExcludedFuncPrefixes;
137*d415bd75Srobert parseExcludedPrefixes(RenameExcludeAliasPrefixes, ExcludedAliasesPrefixes);
138*d415bd75Srobert parseExcludedPrefixes(RenameExcludeGlobalPrefixes, ExcludedGlobalsPrefixes);
139*d415bd75Srobert parseExcludedPrefixes(RenameExcludeStructPrefixes, ExcludedStructsPrefixes);
140*d415bd75Srobert parseExcludedPrefixes(RenameExcludeFunctionPrefixes, ExcludedFuncPrefixes);
141*d415bd75Srobert
142*d415bd75Srobert auto IsNameExcluded = [](StringRef &Name,
143*d415bd75Srobert SmallVectorImpl<StringRef> &ExcludedPrefixes) {
144*d415bd75Srobert return any_of(ExcludedPrefixes,
145*d415bd75Srobert [&Name](auto &Prefix) { return Name.startswith(Prefix); });
146*d415bd75Srobert };
147*d415bd75Srobert
14809467b48Spatrick // Rename all aliases
149*d415bd75Srobert for (GlobalAlias &GA : M.aliases()) {
150*d415bd75Srobert StringRef Name = GA.getName();
151*d415bd75Srobert if (Name.startswith("llvm.") || (!Name.empty() && Name[0] == 1) ||
152*d415bd75Srobert IsNameExcluded(Name, ExcludedAliasesPrefixes))
15309467b48Spatrick continue;
15409467b48Spatrick
155*d415bd75Srobert GA.setName("alias");
15609467b48Spatrick }
15709467b48Spatrick
15809467b48Spatrick // Rename all global variables
15973471bf0Spatrick for (GlobalVariable &GV : M.globals()) {
16073471bf0Spatrick StringRef Name = GV.getName();
161*d415bd75Srobert if (Name.startswith("llvm.") || (!Name.empty() && Name[0] == 1) ||
162*d415bd75Srobert IsNameExcluded(Name, ExcludedGlobalsPrefixes))
16309467b48Spatrick continue;
16409467b48Spatrick
16573471bf0Spatrick GV.setName("global");
16609467b48Spatrick }
16709467b48Spatrick
16809467b48Spatrick // Rename all struct types
16909467b48Spatrick TypeFinder StructTypes;
17009467b48Spatrick StructTypes.run(M, true);
17109467b48Spatrick for (StructType *STy : StructTypes) {
172*d415bd75Srobert StringRef Name = STy->getName();
173*d415bd75Srobert if (STy->isLiteral() || Name.empty() ||
174*d415bd75Srobert IsNameExcluded(Name, ExcludedStructsPrefixes))
17573471bf0Spatrick continue;
17609467b48Spatrick
17709467b48Spatrick SmallString<128> NameStorage;
17873471bf0Spatrick STy->setName(
17973471bf0Spatrick (Twine("struct.") + renamer.newName()).toStringRef(NameStorage));
18009467b48Spatrick }
18109467b48Spatrick
18209467b48Spatrick // Rename all functions
18309467b48Spatrick for (auto &F : M) {
18409467b48Spatrick StringRef Name = F.getName();
18509467b48Spatrick LibFunc Tmp;
18609467b48Spatrick // Leave library functions alone because their presence or absence could
18709467b48Spatrick // affect the behavior of other passes.
18809467b48Spatrick if (Name.startswith("llvm.") || (!Name.empty() && Name[0] == 1) ||
189*d415bd75Srobert GetTLI(F).getLibFunc(F, Tmp) ||
190*d415bd75Srobert IsNameExcluded(Name, ExcludedFuncPrefixes))
19109467b48Spatrick continue;
19209467b48Spatrick
19309467b48Spatrick // Leave @main alone. The output of -metarenamer might be passed to
19409467b48Spatrick // lli for execution and the latter needs a main entry point.
19509467b48Spatrick if (Name != "main")
19609467b48Spatrick F.setName(renamer.newName());
19709467b48Spatrick
19873471bf0Spatrick MetaRename(F);
19909467b48Spatrick }
20009467b48Spatrick }
20109467b48Spatrick
20273471bf0Spatrick struct MetaRenamer : public ModulePass {
20373471bf0Spatrick // Pass identification, replacement for typeid
20473471bf0Spatrick static char ID;
20509467b48Spatrick
MetaRenamer__anon4d72f7160111::MetaRenamer20673471bf0Spatrick MetaRenamer() : ModulePass(ID) {
20773471bf0Spatrick initializeMetaRenamerPass(*PassRegistry::getPassRegistry());
20809467b48Spatrick }
20973471bf0Spatrick
getAnalysisUsage__anon4d72f7160111::MetaRenamer21073471bf0Spatrick void getAnalysisUsage(AnalysisUsage &AU) const override {
21173471bf0Spatrick AU.addRequired<TargetLibraryInfoWrapperPass>();
21273471bf0Spatrick AU.setPreservesAll();
21373471bf0Spatrick }
21473471bf0Spatrick
runOnModule__anon4d72f7160111::MetaRenamer21573471bf0Spatrick bool runOnModule(Module &M) override {
21673471bf0Spatrick auto GetTLI = [this](Function &F) -> TargetLibraryInfo & {
21773471bf0Spatrick return this->getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F);
21873471bf0Spatrick };
21973471bf0Spatrick MetaRename(M, GetTLI);
22009467b48Spatrick return true;
22109467b48Spatrick }
22209467b48Spatrick };
22309467b48Spatrick
22409467b48Spatrick } // end anonymous namespace
22509467b48Spatrick
22609467b48Spatrick char MetaRenamer::ID = 0;
22709467b48Spatrick
22809467b48Spatrick INITIALIZE_PASS_BEGIN(MetaRenamer, "metarenamer",
22909467b48Spatrick "Assign new names to everything", false, false)
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)23009467b48Spatrick INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
23109467b48Spatrick INITIALIZE_PASS_END(MetaRenamer, "metarenamer",
23209467b48Spatrick "Assign new names to everything", false, false)
23309467b48Spatrick
23409467b48Spatrick //===----------------------------------------------------------------------===//
23509467b48Spatrick //
23609467b48Spatrick // MetaRenamer - Rename everything with metasyntactic names.
23709467b48Spatrick //
23809467b48Spatrick ModulePass *llvm::createMetaRenamerPass() {
23909467b48Spatrick return new MetaRenamer();
24009467b48Spatrick }
24173471bf0Spatrick
run(Module & M,ModuleAnalysisManager & AM)24273471bf0Spatrick PreservedAnalyses MetaRenamerPass::run(Module &M, ModuleAnalysisManager &AM) {
24373471bf0Spatrick FunctionAnalysisManager &FAM =
24473471bf0Spatrick AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
24573471bf0Spatrick auto GetTLI = [&FAM](Function &F) -> TargetLibraryInfo & {
24673471bf0Spatrick return FAM.getResult<TargetLibraryAnalysis>(F);
24773471bf0Spatrick };
24873471bf0Spatrick MetaRename(M, GetTLI);
24973471bf0Spatrick
25073471bf0Spatrick return PreservedAnalyses::all();
25173471bf0Spatrick }
252