brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.2 KiB · f3bce31 Raw
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