I have written a pass-plugin for obfuscation and I would like to load this plugin using clang
instead of opt
in Windows. However, when I use the command .\bin\clang++.exe -O1 -Xclang -fpass-plugin='./BronyaObfus.dll' -passes=bogus-control-flow .\test.cpp -o .\a.exe
, clang throws an error:
clang++: error: unknown argument: '-passes=bogus-control-flow'
Then I use .\bin\clang++.exe -O1 -Xclang -fpass-plugin='./BronyaObfus.dll' -mllvm --bogus-control-flow .\test.cpp -o .\a.exe
It didn't load the corresponding pass(bogus-control-flow) as expected, instead, it loaded all passes.
This is my registry code:
llvm::PassPluginLibraryInfo getBronyaObfusPluginInfo() {
return {LLVM_PLUGIN_API_VERSION, "BronyaObfus", "v0.1", [](PassBuilder &PB) {
PB.registerPipelineParsingCallback(
[](StringRef PassName, FunctionPassManager &FPM, ...) {
if (PassName == "bogus-control-flow") {
FPM.addPass(BogusControlFlowPass());
return true;
}
if (PassName == "flattening") {
FPM.addPass(FlatteningPass());
return true;
}
if (PassName == "mba-obfuscation") {
FPM.addPass(MBAObfuscationPass());
return true;
}
return false;
});
PB.registerPipelineParsingCallback(
[](StringRef PassName, ModulePassManager &MPM, ...) {
if (PassName == "string-obfuscation") {
MPM.addPass(StringObfuscationPass());
return true;
}
return false;
});
PB.registerPipelineStartEPCallback([](ModulePassManager &MPM,
OptimizationLevel Level) {
MPM.addPass(StringObfuscationPass());
FunctionPassManager FPM;
FPM.addPass(BogusControlFlowPass());
FPM.addPass(FlatteningPass());
FPM.addPass(MBAObfuscationPass());
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
});
}};
}
extern "C" LLVM_ATTRIBUTE_WEAK ::llvm::PassPluginLibraryInfo
llvmGetPassPluginInfo() {
return getBronyaObfusPluginInfo();
}
If I just want to load bogus-control-flow
pass, how should I pass arguments to clang?
I also tried this, but it seems that it's not possible. It is only possible to add passes from a plugin to the optimization pass pipeline(Based on OptimizationLevel
-O0
, -O1
, etc) . In your case you have all of your passes because, this is called:
PB.registerPipelineStartEPCallback([](ModulePassManager &MPM,
OptimizationLevel Level) {
MPM.addPass(StringObfuscationPass());
FunctionPassManager FPM;
FPM.addPass(BogusControlFlowPass());
FPM.addPass(FlatteningPass());
FPM.addPass(MBAObfuscationPass());
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
});
What you can do is refactor your current plugin into smaller ones.
For example bogus-control-flow.dll
to only add BogusControlFlowPass
pass:
PB.registerPipelineStartEPCallback([](ModulePassManager &MPM,
OptimizationLevel Level) {
FunctionPassManager FPM;
FPM.addPass(BogusControlFlowPass());
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
});
and then you can invoke it using:
.\bin\clang++.exe -O1 -Xclang -fpass-plugin='bogus-control-flow.dll' .\test.cpp -o .\a.exe
Let's say that you created plugins: foo.dll
, bar.dll
and tar.dll
if you want to enable pass from foo.dll
and bar.dll
you would do that by providing:
-Xclang -fpass-plugin=foo.dll -Xclang -fpass-plugin=bar.dll