For crash reduction, I don't think it does anything that llvm-reduce can't. Pass pipeline reduction also has a separate reduction script. The main thing there isn't a replacement tool is the miscompilation reducer, but I'm not sure that's actually functioned for years. There are still some references to bugpoint in various comments and pieces of documentation that don't all necessarily make sense to replace or remove. In particular there are a few passes documented as "only for bugpoint", but I've left those alone in case they are useful for manual reductions.
237 lines
7.2 KiB
C++
237 lines
7.2 KiB
C++
//===- MetaRenamer.cpp - Rename everything with metasyntatic names --------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This pass renames everything with metasyntatic names. The intent is to use
|
|
// this pass after llvm-reduce reduction to conceal the nature of the original
|
|
// program.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/Transforms/Utils/MetaRenamer.h"
|
|
#include "llvm/ADT/STLExtras.h"
|
|
#include "llvm/ADT/SmallString.h"
|
|
#include "llvm/ADT/SmallVector.h"
|
|
#include "llvm/ADT/StringRef.h"
|
|
#include "llvm/ADT/Twine.h"
|
|
#include "llvm/Analysis/TargetLibraryInfo.h"
|
|
#include "llvm/IR/Argument.h"
|
|
#include "llvm/IR/BasicBlock.h"
|
|
#include "llvm/IR/DerivedTypes.h"
|
|
#include "llvm/IR/Function.h"
|
|
#include "llvm/IR/GlobalAlias.h"
|
|
#include "llvm/IR/GlobalVariable.h"
|
|
#include "llvm/IR/Instruction.h"
|
|
#include "llvm/IR/InstIterator.h"
|
|
#include "llvm/IR/Module.h"
|
|
#include "llvm/IR/PassManager.h"
|
|
#include "llvm/IR/Type.h"
|
|
#include "llvm/IR/TypeFinder.h"
|
|
#include "llvm/Support/CommandLine.h"
|
|
|
|
using namespace llvm;
|
|
|
|
static cl::opt<std::string> RenameExcludeFunctionPrefixes(
|
|
"rename-exclude-function-prefixes",
|
|
cl::desc("Prefixes for functions that don't need to be renamed, separated "
|
|
"by a comma"),
|
|
cl::Hidden);
|
|
|
|
static cl::opt<std::string> RenameExcludeAliasPrefixes(
|
|
"rename-exclude-alias-prefixes",
|
|
cl::desc("Prefixes for aliases that don't need to be renamed, separated "
|
|
"by a comma"),
|
|
cl::Hidden);
|
|
|
|
static cl::opt<std::string> RenameExcludeGlobalPrefixes(
|
|
"rename-exclude-global-prefixes",
|
|
cl::desc(
|
|
"Prefixes for global values that don't need to be renamed, separated "
|
|
"by a comma"),
|
|
cl::Hidden);
|
|
|
|
static cl::opt<std::string> RenameExcludeStructPrefixes(
|
|
"rename-exclude-struct-prefixes",
|
|
cl::desc("Prefixes for structs that don't need to be renamed, separated "
|
|
"by a comma"),
|
|
cl::Hidden);
|
|
|
|
static cl::opt<bool>
|
|
RenameOnlyInst("rename-only-inst", cl::init(false),
|
|
cl::desc("only rename the instructions in the function"),
|
|
cl::Hidden);
|
|
|
|
static const char *const metaNames[] = {
|
|
// See http://en.wikipedia.org/wiki/Metasyntactic_variable
|
|
"foo", "bar", "baz", "quux", "barney", "snork", "zot", "blam", "hoge",
|
|
"wibble", "wobble", "widget", "wombat", "ham", "eggs", "pluto", "spam"
|
|
};
|
|
|
|
namespace {
|
|
// This PRNG is from the ISO C spec. It is intentionally simple and
|
|
// unsuitable for cryptographic use. We're just looking for enough
|
|
// variety to surprise and delight users.
|
|
struct PRNG {
|
|
unsigned long next;
|
|
|
|
void srand(unsigned int seed) { next = seed; }
|
|
|
|
int rand() {
|
|
next = next * 1103515245 + 12345;
|
|
return (unsigned int)(next / 65536) % 32768;
|
|
}
|
|
};
|
|
|
|
struct Renamer {
|
|
Renamer(unsigned int seed) { prng.srand(seed); }
|
|
|
|
const char *newName() {
|
|
return metaNames[prng.rand() % std::size(metaNames)];
|
|
}
|
|
|
|
PRNG prng;
|
|
};
|
|
|
|
static void
|
|
parseExcludedPrefixes(StringRef PrefixesStr,
|
|
SmallVectorImpl<StringRef> &ExcludedPrefixes) {
|
|
for (;;) {
|
|
auto PrefixesSplit = PrefixesStr.split(',');
|
|
if (PrefixesSplit.first.empty())
|
|
break;
|
|
ExcludedPrefixes.push_back(PrefixesSplit.first);
|
|
PrefixesStr = PrefixesSplit.second;
|
|
}
|
|
}
|
|
|
|
void MetaRenameOnlyInstructions(Function &F) {
|
|
for (auto &I : instructions(F))
|
|
if (!I.getType()->isVoidTy() && I.getName().empty())
|
|
I.setName(I.getOpcodeName());
|
|
}
|
|
|
|
void MetaRename(Function &F) {
|
|
for (Argument &Arg : F.args())
|
|
if (!Arg.getType()->isVoidTy())
|
|
Arg.setName("arg");
|
|
|
|
for (auto &BB : F) {
|
|
BB.setName("bb");
|
|
|
|
for (auto &I : BB)
|
|
if (!I.getType()->isVoidTy())
|
|
I.setName(I.getOpcodeName());
|
|
}
|
|
}
|
|
|
|
void MetaRename(Module &M,
|
|
function_ref<TargetLibraryInfo &(Function &)> GetTLI) {
|
|
// Seed our PRNG with simple additive sum of ModuleID. We're looking to
|
|
// simply avoid always having the same function names, and we need to
|
|
// remain deterministic.
|
|
unsigned int randSeed = 0;
|
|
for (auto C : M.getModuleIdentifier())
|
|
randSeed += C;
|
|
|
|
Renamer renamer(randSeed);
|
|
|
|
SmallVector<StringRef, 8> ExcludedAliasesPrefixes;
|
|
SmallVector<StringRef, 8> ExcludedGlobalsPrefixes;
|
|
SmallVector<StringRef, 8> ExcludedStructsPrefixes;
|
|
SmallVector<StringRef, 8> ExcludedFuncPrefixes;
|
|
parseExcludedPrefixes(RenameExcludeAliasPrefixes, ExcludedAliasesPrefixes);
|
|
parseExcludedPrefixes(RenameExcludeGlobalPrefixes, ExcludedGlobalsPrefixes);
|
|
parseExcludedPrefixes(RenameExcludeStructPrefixes, ExcludedStructsPrefixes);
|
|
parseExcludedPrefixes(RenameExcludeFunctionPrefixes, ExcludedFuncPrefixes);
|
|
|
|
auto IsNameExcluded = [](StringRef &Name,
|
|
SmallVectorImpl<StringRef> &ExcludedPrefixes) {
|
|
return any_of(ExcludedPrefixes,
|
|
[&Name](auto &Prefix) { return Name.starts_with(Prefix); });
|
|
};
|
|
|
|
// Leave library functions alone because their presence or absence could
|
|
// affect the behavior of other passes.
|
|
auto ExcludeLibFuncs = [&](Function &F) {
|
|
LibFunc Tmp;
|
|
StringRef Name = F.getName();
|
|
return F.isIntrinsic() || (!Name.empty() && Name[0] == 1) ||
|
|
GetTLI(F).getLibFunc(F, Tmp) ||
|
|
IsNameExcluded(Name, ExcludedFuncPrefixes);
|
|
};
|
|
|
|
if (RenameOnlyInst) {
|
|
// Rename all functions
|
|
for (auto &F : M) {
|
|
if (ExcludeLibFuncs(F))
|
|
continue;
|
|
MetaRenameOnlyInstructions(F);
|
|
}
|
|
return;
|
|
}
|
|
|
|
// Rename all aliases
|
|
for (GlobalAlias &GA : M.aliases()) {
|
|
StringRef Name = GA.getName();
|
|
if (Name.starts_with("llvm.") || (!Name.empty() && Name[0] == 1) ||
|
|
IsNameExcluded(Name, ExcludedAliasesPrefixes))
|
|
continue;
|
|
|
|
GA.setName("alias");
|
|
}
|
|
|
|
// Rename all global variables
|
|
for (GlobalVariable &GV : M.globals()) {
|
|
StringRef Name = GV.getName();
|
|
if (Name.starts_with("llvm.") || (!Name.empty() && Name[0] == 1) ||
|
|
IsNameExcluded(Name, ExcludedGlobalsPrefixes))
|
|
continue;
|
|
|
|
GV.setName("global");
|
|
}
|
|
|
|
// Rename all struct types
|
|
TypeFinder StructTypes;
|
|
StructTypes.run(M, true);
|
|
for (StructType *STy : StructTypes) {
|
|
StringRef Name = STy->getName();
|
|
if (STy->isLiteral() || Name.empty() ||
|
|
IsNameExcluded(Name, ExcludedStructsPrefixes))
|
|
continue;
|
|
|
|
SmallString<128> NameStorage;
|
|
STy->setName(
|
|
(Twine("struct.") + renamer.newName()).toStringRef(NameStorage));
|
|
}
|
|
|
|
// Rename all functions
|
|
for (auto &F : M) {
|
|
if (ExcludeLibFuncs(F))
|
|
continue;
|
|
|
|
// Leave @main alone. The output of -metarenamer might be passed to
|
|
// lli for execution and the latter needs a main entry point.
|
|
if (F.getName() != "main")
|
|
F.setName(renamer.newName());
|
|
|
|
MetaRename(F);
|
|
}
|
|
}
|
|
|
|
} // end anonymous namespace
|
|
|
|
PreservedAnalyses MetaRenamerPass::run(Module &M, ModuleAnalysisManager &AM) {
|
|
FunctionAnalysisManager &FAM =
|
|
AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
|
|
auto GetTLI = [&FAM](Function &F) -> TargetLibraryInfo & {
|
|
return FAM.getResult<TargetLibraryAnalysis>(F);
|
|
};
|
|
MetaRename(M, GetTLI);
|
|
|
|
return PreservedAnalyses::all();
|
|
}
|