OLLVM代码肴杂移植与使用(再续)

源码 2024-9-21 01:47:30 61 0 来自 中国
关键修改

Legacy PM模式不收效

现在由于默认是NEW PM以是常常有人邮件我移植很完善编译也乐成,就是没效果,这里做一下解答。告急两种方式办理,一种是在cmake的时间加一下-DLLVM_ENABLE_NEW_PASS_MANAGER =OFF来禁用掉NEW PM,这样在编译完成后使用的时间就可以了,尚有一种就是走默认开启这,然后用ollvm编译自己项目时加上-flegacy-pass-manager的cflag,再加-mllvm原来哪些就可以正常使用了
14.0以后的修改

告急是StringObfuscation.cpp内里的两个地方,第一个是宏的修改编译机遇,第二个就是CreateGEP,CreateLoad等多个方法必要通报指针范例了,原来不传会设置为null到了13.0里就开始内部通过对象获取范例,就像修改的这样,到了14.0干脆就是逼迫你必须传范例了。
1.jpg 改为New Pass Manager

这个欠好说修改了是好是坏,毕竟假如不修改,现在正常开启NEWPM编译完,使用-flegacy-pass-manager标识才气肴杂,官方也说了在积极去撤除全部legacy pass manager,以是还是该预备一下。
这里只那两个Pass举例,由于改法都差不多,之以是是两个是由于一个是Function一个是Module,实在尚有其他的很多多少种,只不外网上封装的肴杂Pass也就用了这两种,想具体相识的,文档我反正没找到,但可以从源码中读逻辑。
FunctionAnalysisManager

起首以BogusControlFlow为例在.h里添加#include "llvm/IR/PassManager.h"的头文件,然后创建如下的Pass类
    class BogusControlFlowPass : public PassInfoMixin<BogusControlFlowPass>{         public:            PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);            static bool isRequired() { return true; }    };在.m文件里先把之前初始化的方法包一层,为了在另一个Pass类里方便调用


把下面的代码加完补上之前界说的类的方法就完成了
PreservedAnalyses BogusControlFlowPass::run(Function& F, FunctionAnalysisManager& AM) {  BogusControlFlow bcf;  if (bcf.runOnCustomFunction(F))    return PreservedAnalyses::none();  return PreservedAnalyses::all();}ModuleAnalysisManager

然后以StringObfuscation为例在.h里添加#include "llvm/IR/PassManager.h"的头文件,然后创建如下的Pass类
      class StringObfuscationPass : public PassInfoMixin<StringObfuscationPass>{         public:            PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);            static bool isRequired() { return true; }      };在.m文件里比之前谁人改动要多点,告急之前类就带了Pass后缀,如下直接去掉

3.png

再把之前初始化方法包一层,还是为了在另一个Pass类里方便调用


把下面的代码加完补上之前界说的类的方法就完成了
PreservedAnalyses StringObfuscationPass::run(Module &M, ModuleAnalysisManager& AM) {  StringObfuscation sop;  if (sop.runCustomModule(M))        return PreservedAnalyses::none();  return PreservedAnalyses::all();}注册 添加 Pass

把Pass类做完支持后就该添加和注册了,起首把头文件加到PassBuilder.cpp下,由于PassRegistry.def里注册Pass是从这边调用的。

6.png
然后找符合的机遇插入Pass,与之前PassManagerBuilder.cpp对应的是PassBuilderPipelines.cpp,而方法则是populateModulePassManager对应buildModuleOptimizationPipeline,如下加到和之前类似的调用位置即可。
这里是头文件,和之前的一些处置处罚,但基本没有效过

8.png
下面是按之前位置挑了开头和末了位置添加
9.png Swift支持

想支持swift的肴杂直接用我之前的swift分支是不现实的,由于苹果大量的修改想直接编译llvm就支持基本不大概,但假如直接选择编译swift的工具链来实现就简朴的多,这个时间只必要下载Swift的源码,它在编译Toolchain时下载的llvm上把我之前的修改移植过来,然后编译出来就可以直接支持swift的肴杂了。(厥后认真编译了频频,效果都是不报错肴杂无效果,但团体思绪应该没错下面写的没爱好可以略过了。。。)
根据Xcode Wiki上的对应去切换git上的branch对应版本,有一点要留意通常你当前Xcode版本编译不了你当前Xcode用的,只能用上个版本编译你当前Xcode对应的,不外你也可以不管对应直接就用master的版本编译最新的。
官方给的编译教程在这里,有爱好的可以自己研磨,下面是我总结的。
这里我发起用ssh的方式,https的偶然会出现连不上的情况,不加反面的-with-ssh走的就是https的。
git clone git@github.com:apple/swift.gitcd swiftutils/update-checkout --clone-with-ssh 10.png 指令结束后swift同级目次会多出一堆当前master对应的依靠库,以是第一步git clone的时间肯定要找个干净的目次。
然后切换到自己想要编译的版本,编译之前肯定要看看自己Xcode版本
utils/update-checkout --scheme mybranchname# ORutils/update-checkout --tag mytagname末了实行build_toolchain或build_script,此中build_toolchain最简朴,傻瓜式编译,全自动,先看看有没有错,不报错就可以做ollvm移植了。
# 反面必须要跟个唯一标识utils/build_toolchain com.xxxx编译乐成会如下图,多出两个文件夹两个tar.gz文件,内里都是.toolchain放/Library/Developer/Toolchains里Xcode就可以用了
移植的话在swift同级目次有个llvm-project,这就是尺度的llvm,之前怎么移植现在就怎么移植即可。比力简朴的方式可以选择git patch文件大概找我swift-llvm-clang的分支用git cherry pick拉已往,这里的llvm都是指向的swift-llvm的。
下面提供了git的patch具体下令
cd ../llvm-project# 下载patch文件wget https://heroims.github.io/obfuscator/LegacyPass/ollvm14.patch# 使用patchgit apply ollvm14.patch假如失败,辩说了则用另一条下令如下,会天生辩说文件的对应.rej,直接看一下辩说的地方按提示修改即可。(大部门情况都会有辩说。。。)
git apply --reject --ignore-whitespace ollvm14.patch把llvm移植完再用build_toolchain把工具链编译出来,这里再简朴说一下build_toolchain实在内部就是在调用build_script。
./utils/build-script ${DRY_RUN} ${DISTCC_FLAG} ${PRESET_FILE_FLAGS} \        ${SCCACHE_FLAG} \        --preset="${PRESET_PREFIX}${SWIFT_PACKAGE}${NO_TEST}${USE_OS_RUNTIME}" \        install_destdir="${SWIFT_INSTALL_DIR}" \        installable_package="${SWIFT_INSTALLABLE_PACKAGE}" \        install_toolchain_dir="${SWIFT_TOOLCHAIN_DIR}" \        install_symroot="${SWIFT_INSTALL_SYMROOT}" \        symbols_package="${SYMBOLS_PACKAGE}" \        darwin_toolchain_bundle_identifier="${BUNDLE_IDENTIFIER}" \        darwin_toolchain_display_name="${DISPLAY_NAME}" \        darwin_toolchain_display_name_short="${DISPLAY_NAME_SHORT}" \        darwin_toolchain_xctoolchain_name="${TOOLCHAIN_NAME}" \        darwin_toolchain_version="${TOOLCHAIN_VERSION}" \        darwin_toolchain_alias="Local" \        darwin_toolchain_require_use_os_runtime="${REQUIRE_USE_OS_RUNTIME}"假如想用build_toolchain做一些特别设置也可以用--preset-file指定文件设置默认使用的是build-presets.ini,内里用[preset: xxxx,xxx]来指定模块,而且还可以调用已有的,内里最底子的是[preset: mixin_osx_package_base],仿照这可以写一个针对自己的llvm设置挑些自己必要的,我第一次直接用的master然后全量编译愣是直接编译了12个小时以上。。。。
Android 轻量编译

之前我都是直接看一眼当前用的版本对应google llvm的版本就去下载切到对应commit位置,直接移植ollvm团体编译,厥后看网上有个套路居然能使用ndk编译个Pass的.so文件直接搞定,以是记载一下。
对方也有些文章具体报告这里和这里都有。
通用的轻量级编译

根据上面的套路,实在核心是Legacy Pass提供了自动注册功能,然后编译一个独立的动态加载的Pass,这样不必要对llvm自己举行修改,只是扩展一个模块,由此有了下边的代码分别对应Legacy Pass和New Pass两种模式的自动注册。
Legacy Pass Manager

#include "Transforms/Obfuscation/BogusControlFlow.h"#include "Transforms/Obfuscation/Flattening.h"#include "Transforms/Obfuscation/Split.h"#include "Transforms/Obfuscation/Substitution.h"#include "Transforms/Obfuscation/StringObfuscation.h"#include "llvm/IR/LegacyPassManager.h"#include "llvm/Transforms/IPO/PassManagerBuilder.h"using namespace llvm;static void registerOllvmPass(const PassManagerBuilder &,                              legacy:assManagerBase &M) {    PM.add(createBogus(true));#if LLVM_VERSION_MAJOR >= 9    PM.add(createLowerSwitchPass());#endif    PM.add(createFlattening(true));    PM.add(createSplitBasicBlock(true));    PM.add(createSubstitution(true));}static void registerOllvmModulePass(const PassManagerBuilder &,                              legacy:assManagerBase &M) {    PM.add(createStringObfuscation(true));}static RegisterStandardPasses        RegisterMyPass1(PassManagerBuilder::EP_EnabledOnOptLevel0,                       registerOllvmModulePass);static RegisterStandardPasses        RegisterMyPass2(PassManagerBuilder::EP_OptimizerLast,                        registerOllvmModulePass);static RegisterStandardPasses        RegisterMyPass3(PassManagerBuilder::EP_EarlyAsPossible,                       registerOllvmFunctionPass);New Pass Manager

#include "Transforms/Obfuscation/BogusControlFlow.h"#include "Transforms/Obfuscation/Flattening.h"#include "Transforms/Obfuscation/Split.h"#include "Transforms/Obfuscation/Substitution.h"#include "Transforms/Obfuscation/StringObfuscation.h"#include "llvm/Passes/PassBuilder.h"#include "llvm/Passes/PassPlugin.h"llvm:assPluginLibraryInfo getOllvmPluginInfo() {  return {    LLVM_PLUGIN_API_VERSION, "OpcodeCounter", LLVM_VERSION_STRING,        [](PassBuilder &B) {            // #1 注册标志 "opt -passes=obf-bcf"            PB.registerPipelineParsingCallback(              [&](StringRef Name, FunctionPassManager &FPM,                  ArrayRef<assBuilder:ipelineElement>) {                if (Name == "obf-bcf") {                  FPM.addPass(BogusControlFlowPass());                  return true;                }                if(Name == "obf-fla"){                  FPM.addPass(FlatteningPass());                  return true;                }                if(Name == "obf-sub"){                  FPM.addPass(SubstitutionPass());                  return true;                }                if(Name == "obf-split"){                  FPM.addPass(SplitBasicBlockPass());                  return true;                }                return false;              });            PB.registerPipelineParsingCallback(              [&](StringRef Name, ModulePassManager &MPM,                  ArrayRef<assBuilder:ipelineElement>) {                if (Name == "obf-str") {                  MPM.addPass(StringObfuscationPass());                  return true;                }                return false;              });            // #2 找到具体机遇插入pass            //registerVectorizerStartEPCallback这个方法插入必要加-O1的flag否则大概不收效会被跳过            PB.registerVectorizerStartEPCallback(              [](llvm::FunctionPassManager &M,                 llvm:assBuilder::OptimizationLevel Level) {                PM.addPass(SplitBasicBlockPass());                PM.addPass(BogusControlFlowPass());                #if LLVM_VERSION_MAJOR >= 9                    PM.addPass(LowerSwitchPass());                #endif                PM.addPass(FlatteningPass());                PM.addPass(SubstitutionPass());                              });            PB.registerPipelineStartEPCallback(              [](llvm::ModulePassManager &M,                 llvm:assBuilder::OptimizationLevel Level) {                PM.addPass(StringObfuscationPass());              });                  };}extern "C" LLVM_ATTRIBUTE_WEAK ::llvm:assPluginLibraryInfollvmGetPassPluginInfo() {  return getOllvmPluginInfo();}创建个PMRegistration.cpp,放到Obfuscation里再改一下CMakeLists.txt,实行完cmake构建好项目可以单独编译这个Obfuscation模块,实在用这个方法也就不必要再修改llvm自己了,移植起来方便多了只必要添加文件即可。用patch也就基本见不到辩说了。
末了跟一个注册方法的表
回调函数回调时提供的对象对应 ExtensionPointTyregisterPeepholeEPCallbackFunctionPassManager对应EP_PeepholeregisterLateLoopOptimizationsEPCallbackLoopPassManager对应EP_LoopOptimizerEndregisterLoopOptimizerEndEPCallbackLoopPassManager对应EP_LateLoopOptimizationsregisterScalarOptimizerLateEPCallbackFunctionPassManager对应 EP_ScalarOptimizerLateregisterCGSCCOptimizerLateEPCallbackCGSCCPassManager对应EP_CGSCCOptimizerLateregisterVectorizerStartEPCallbackFunctionPassManager对应EP_VectorizerStartregisterPipelineStartEPCallbackModulePassManager对应EP_EarlyAsPossibleregisterPipelineEarlySimplificationEPCallbackModulePassManager对应 EP_ModuleOptimizerEarlyregisterOptimizerLastEPCallbackModulePassManager对应EP_OptimizerLast
您需要登录后才可以回帖 登录 | 立即注册

Powered by CangBaoKu v1.0 小黑屋藏宝库It社区( 冀ICP备14008649号 )

GMT+8, 2024-10-18 20:31, Processed in 0.189120 second(s), 35 queries.© 2003-2025 cbk Team.

快速回复 返回顶部 返回列表