#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/TypeFinder.h"
#include "llvm/Transforms/Utils/Obfuscation.h"
using namespace llvm;
using namespace obfuscate;
void Rot13Obfuscator::anchor() {}
void IncrementObfuscator::anchor() {}
namespace {
class MDSRecursiveModify {
SmallVector<MDNode *, 16> Worklist;
DenseSet<const MDNode *> Visited;
LLVMContext &Ctx;
std::function<StringRef(StringRef)> F;
public:
MDSRecursiveModify(LLVMContext &Context,
std::function<StringRef(StringRef)> NewStr)
: Ctx(Context), F(NewStr) {}
void addEntryPoint(MDNode *N) {
if (!N || !Visited.count(N))
Worklist.push_back(N);
}
void addEntryPoint(NamedMDNode *NMD) {
for (auto I : NMD->operands())
addEntryPoint(I);
}
void addEntryPoint(DbgInfoIntrinsic *DII) {
if (auto DDI = dyn_cast<DbgDeclareInst>(DII))
addEntryPoint(DDI->getVariable());
else if (auto DVI = dyn_cast<DbgValueInst>(DII))
addEntryPoint(DVI->getVariable());
else
llvm_unreachable("invalid debug info intrinsic");
}
inline void run();
};
}
void MDSRecursiveModify::run() {
while (!Worklist.empty()) {
auto N = Worklist.pop_back_val();
if (!N || Visited.count(N))
continue;
Visited.insert(N);
for (unsigned i = 0; i < N->getNumOperands(); ++i) {
Metadata *MD = N->getOperand(i);
if (!MD)
continue;
if (auto MDS = dyn_cast<MDString>(MD)) {
assert(N->isResolved() && "Unexpected forward reference");
N->replaceOperandWith(i, MDString::get(Ctx, F(MDS->getString())));
} else if (auto NN = dyn_cast<MDNode>(MD))
Worklist.push_back(NN);
}
}
}
void Obfuscator::obfuscateModule(Module &M,
std::function<bool(Value &)> preserve) {
{
SmallVector<GlobalValue *, 64> Worklist;
auto hasName = [](const Value &V) { return V.getName() != ""; };
for (auto &F : M) {
if (hasName(F) && !preserve(F))
Worklist.push_back(&F);
for (auto &Arg : F.args())
Arg.setName("");
}
for (auto &I : M.globals())
if (hasName(I) && !preserve(I))
Worklist.push_back(&I);
for (auto &I : M.aliases())
if (hasName(I) && !preserve(I))
Worklist.push_back(&I);
for (auto I : Worklist)
I->setName(obfuscate(I->getName()));
}
TypeFinder TF;
TF.run(M, true);
for (auto I : TF)
I->setName(obfuscateTypeName(I->getName()));
MDSRecursiveModify Modify(M.getContext(),
[this](StringRef S) { return obfuscate(S); });
if (auto DBG = M.getNamedMetadata("llvm.dbg.cu"))
Modify.addEntryPoint(DBG);
Modify.run();
auto addDbgIntrinsicCalls = [&](StringRef Name) {
auto F = M.getFunction(Name);
if (!F)
return;
for (auto Usr : F->users())
Modify.addEntryPoint(cast<DbgInfoIntrinsic>(Usr));
};
addDbgIntrinsicCalls("llvm.dbg.declare");
addDbgIntrinsicCalls("llvm.dbg.value");
Modify.run();
for (auto &F : M.functions())
for (auto &BB : F)
for (auto &I : BB) {
I.setName("");
Modify.addEntryPoint(I.getDebugLoc().getAsMDNode());
}
Modify.run();
}
void IncrementObfuscator::writeReverseMap(raw_ostream &OS) {
std::vector<StringRef> Strs;
Strs.resize(reverseMap().size());
OS << "BCSymbolMap Version: 1.0\n";
for (auto &STE : reverseMap())
Strs[findIndex(STE.getKey())] = STE.getValue();
for (auto S : Strs) {
assert(S != "" && "failed to initialize a member");
OS << S << "\n";
}
}