首页
社区
课程
招聘
[原创]macOS安装调试llvm入门
发表于: 2020-12-26 14:02 9283

[原创]macOS安装调试llvm入门

2020-12-26 14:02
9283

题目出自3W班9月第一题:编译llvm,动态调试Pass报告。老师的课件不是基于macos的,所以这篇文章算是自己踩坑之后的一个学习记录。

打开clion新建一个项目,先写一个demo:

尝试用你编译出来的clang来编译这个demo

编译报错:

重新编译

Pass

Cmakelists

编译

使用opt打印

Cmakelists

编译

使用

逆向

以编写ObfString为例

编译通过。

在代码中编写一个错误代码

编译

编写一个测试main.cpp尝试调试

打开shell尝试编译

可以看出clang++的编译实际上是使用了clang-9做的编译,那么修改clion编译配置,尝试调试:

就可以调试了

# 查看你的Android ndk版本
$ ./clang -v
Android (6454773 based on r365631c2) clang version 9.0.8 (https://android.googlesource.com/toolchain/llvm-project 98c855489587874b2a325e7a516b99d838599c6f) (based on LLVM 9.0.8svn)
Target: x86_64-apple-darwin19.6.0
Thread model: posix
InstalledDir: /Volumes/Work/SDK/AndroidSDK/ndk/21.3.6528147/toolchains/llvm/prebuilt/darwin-x86_64/bin/.
# 下载依赖
$ brew install cmake zlib ninja
# 可以看到版本是clang version 9.0.8,所以我们去github寻找差不多的版本下载,这里我们找到了9.0.1,下载它
# 从这个地址下载源码:
$ https://github.com/llvm/llvm-project/releases
# 下载好后用clion打开项目,然后找到llvm文件夹中的CMakelist.txt双击打开,按照clion提示,点击同步
# clion-preferences-build,execution,deployment-cmake对debug与release设置cmake options
-G Ninja -DLLVM_ENABLE_PROJECTS="clang"
# 等待同步完成后,跳转到cmake-build-debug文件夹
$ ninja -j8
# 查看你的Android ndk版本
$ ./clang -v
Android (6454773 based on r365631c2) clang version 9.0.8 (https://android.googlesource.com/toolchain/llvm-project 98c855489587874b2a325e7a516b99d838599c6f) (based on LLVM 9.0.8svn)
Target: x86_64-apple-darwin19.6.0
Thread model: posix
InstalledDir: /Volumes/Work/SDK/AndroidSDK/ndk/21.3.6528147/toolchains/llvm/prebuilt/darwin-x86_64/bin/.
# 下载依赖
$ brew install cmake zlib ninja
# 可以看到版本是clang version 9.0.8,所以我们去github寻找差不多的版本下载,这里我们找到了9.0.1,下载它
# 从这个地址下载源码:
$ https://github.com/llvm/llvm-project/releases
# 下载好后用clion打开项目,然后找到llvm文件夹中的CMakelist.txt双击打开,按照clion提示,点击同步
# clion-preferences-build,execution,deployment-cmake对debug与release设置cmake options
-G Ninja -DLLVM_ENABLE_PROJECTS="clang"
# 等待同步完成后,跳转到cmake-build-debug文件夹
$ ninja -j8
# main.c
#include <stdio.h>
 
void test(){
    printf("this is Test!\n");
}
 
void test01(){
    printf("test01\n");
}
int main() {
    test();
    test01();
    return 0;
}
# main.c
#include <stdio.h>
 
void test(){
    printf("this is Test!\n");
}
 
void test01(){
    printf("test01\n");
}
int main() {
    test();
    test01();
    return 0;
}
# 配置clang地址
$ export PATH=/Volumes/Work/CLion/Projects/llvm-project-llvmorg-9.0.1/llvm/cmake-build-debug/bin/:$PATH
# 尝试编译
$ clang main.cpp -o main_clang
# 配置clang地址
$ export PATH=/Volumes/Work/CLion/Projects/llvm-project-llvmorg-9.0.1/llvm/cmake-build-debug/bin/:$PATH
# 尝试编译
$ clang main.cpp -o main_clang
$ clang main.cpp -o main_clang 
clang-9: error: no such file or directory: 'main.cpp'
clang-9: error: no input files
# 解决
$ export SDKROOT=$(xcrun --sdk macosx --show-sdk-path)
$ clang main.cpp -o main_clang 
clang-9: error: no such file or directory: 'main.cpp'
clang-9: error: no input files
# 解决
$ export SDKROOT=$(xcrun --sdk macosx --show-sdk-path)
$ clang main.c -o main_clang
$ ./main_clang
this is Test!
test01
# 生成ll文件
$ clang -emit-llvm main.c -S -o main.ll
# 生成bc文件
$ llvm-as main.ll -o main.bc
$ clang main.c -o main_clang
$ ./main_clang
this is Test!
test01
# 生成ll文件
$ clang -emit-llvm main.c -S -o main.ll
# 生成bc文件
$ llvm-as main.ll -o main.bc
# 这是介绍https://llvm.org/docs/WritingAnLLVMPass.html#writing-an-llvm-pass-basiccode
# 这是介绍https://llvm.org/docs/WritingAnLLVMPass.html#writing-an-llvm-pass-basiccode
// /Volumes/Work/CLion/Projects/llvm-project-llvmorg-9.0.1/llvm/lib/Transforms/EncodeFunctionName/EncodeFunctionName.cpp
#include "llvm/IR/Function.h"
#include "llvm/Pass.h"
#include "llvm/Support/raw_ostream.h"
 
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
 
using namespace llvm;
 
namespace llvm {
    struct EncodeFunctionName : public FunctionPass {
        static char ID; // Pass identification, replacement for typeid
        EncodeFunctionName() : FunctionPass(ID) {};
 
        bool runOnFunction(Function &F) override {
            errs() << "EncodeFunctionName";
            errs().write_escaped(F.getName()) << '\n';
            return false;
        }
    };
}
 
char EncodeFunctionName::ID = 0;
static RegisterPass<EncodeFunctionName> X("encode", "Hello EncodeFunctionName Pass");
 
static llvm::RegisterStandardPasses Y(
        llvm::PassManagerBuilder::EP_EarlyAsPossible,
        [](const llvm::PassManagerBuilder &Builder,
           llvm::legacy::PassManagerBase &PM) { PM.add(new EncodeFunctionName()); });
// /Volumes/Work/CLion/Projects/llvm-project-llvmorg-9.0.1/llvm/lib/Transforms/EncodeFunctionName/EncodeFunctionName.cpp
#include "llvm/IR/Function.h"
#include "llvm/Pass.h"
#include "llvm/Support/raw_ostream.h"
 
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
 
using namespace llvm;
 
namespace llvm {
    struct EncodeFunctionName : public FunctionPass {
        static char ID; // Pass identification, replacement for typeid
        EncodeFunctionName() : FunctionPass(ID) {};
 
        bool runOnFunction(Function &F) override {
            errs() << "EncodeFunctionName";
            errs().write_escaped(F.getName()) << '\n';
            return false;
        }
    };
}
 
char EncodeFunctionName::ID = 0;
static RegisterPass<EncodeFunctionName> X("encode", "Hello EncodeFunctionName Pass");
 
static llvm::RegisterStandardPasses Y(
        llvm::PassManagerBuilder::EP_EarlyAsPossible,
        [](const llvm::PassManagerBuilder &Builder,
           llvm::legacy::PassManagerBase &PM) { PM.add(new EncodeFunctionName()); });
# /Volumes/Work/CLion/Projects/llvm-project-llvmorg-9.0.1/llvm/lib/Transforms/EncodeFunctionName/CMakeLists.txt
add_llvm_library( LLVMEncodeFunctionName MODULE BUILDTREE_ONLY
  EncodeFunctionName.cpp
 
  DEPENDS
  intrinsics_gen
  PLUGIN_TOOL
  opt
  )
# /Volumes/Work/CLion/Projects/llvm-project-llvmorg-9.0.1/llvm/lib/Transforms/EncodeFunctionName/CMakeLists.txt
add_llvm_library( LLVMEncodeFunctionName MODULE BUILDTREE_ONLY
  EncodeFunctionName.cpp
 
  DEPENDS
  intrinsics_gen
  PLUGIN_TOOL
  opt
  )
$ cd /Volumes/Work/CLion/Projects/llvm-project-llvmorg-9.0.1/llvm/cmake-build-debug
$ ninja LLVMEncodeFunctionName
$ cd /Volumes/Work/CLion/Projects/llvm-project-llvmorg-9.0.1/llvm/cmake-build-debug
$ ninja LLVMEncodeFunctionName
# opt -load passpath -encode llfile -o bcfile
$ opt -load /Volumes/Work/CLion/Projects/llvm-project-llvmorg-9.0.1/llvm/cmake-build-debug/lib/LLVMEncodeFunctionName.dylib -encode main.ll -o main.bc
# opt -load passpath -encode llfile -o bcfile
$ opt -load /Volumes/Work/CLion/Projects/llvm-project-llvmorg-9.0.1/llvm/cmake-build-debug/lib/LLVMEncodeFunctionName.dylib -encode main.ll -o main.bc
// /Volumes/Work/CLion/Projects/llvm-project-llvmorg-9.0.1/llvm/lib/Transforms/EncodeFunctionName/EncodeFunctionName.cpp
#include "llvm/IR/Function.h"
#include "llvm/Pass.h"
#include "llvm/Support/raw_ostream.h"
 
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
 
using namespace llvm;
 
namespace llvm {
    struct EncodeFunctionName : public FunctionPass {
        static char ID; // Pass identification, replacement for typeid
        EncodeFunctionName() : FunctionPass(ID) {};
 
        bool runOnFunction(Function &F) override {
            errs() << "EncodeFunctionName: " << F.getName() << " -> ";
 
            if(F.getName().compare("main") !=0){ # 过滤方法名,main方法名不能改,其他方法可以
                llvm::MD5 Hasher; # 使用md5算法修改方法名称
                llvm::MD5::MD5Result Hash; # 使用md5算法修改方法名称
                Hasher.update(F.getName()); # 使用md5算法修改方法名称
                Hasher.update("NewFunctionName"); # 使用md5算法修改方法名称
                Hasher.final(Hash); # 使用md5算法修改方法名称
 
                SmallString<32> HexString; # 使用md5算法修改方法名称
                llvm::MD5::stringifyResult(Hash, HexString);# 使用md5算法修改方法名称
                F.setName(HexString); # 修改方法名称
            }
            errs().write_escaped(F.getName()) << '\n';
            return false;
        }
    };
}
 
char EncodeFunctionName::ID = 0;
static RegisterPass<EncodeFunctionName> X("encode", "Hello EncodeFunctionName Pass");
 
static llvm::RegisterStandardPasses Y(
        llvm::PassManagerBuilder::EP_EarlyAsPossible,
        [](const llvm::PassManagerBuilder &Builder,
           llvm::legacy::PassManagerBase &PM) { PM.add(new EncodeFunctionName()); });
// /Volumes/Work/CLion/Projects/llvm-project-llvmorg-9.0.1/llvm/lib/Transforms/EncodeFunctionName/EncodeFunctionName.cpp
#include "llvm/IR/Function.h"
#include "llvm/Pass.h"
#include "llvm/Support/raw_ostream.h"
 
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
 
using namespace llvm;
 
namespace llvm {
    struct EncodeFunctionName : public FunctionPass {
        static char ID; // Pass identification, replacement for typeid
        EncodeFunctionName() : FunctionPass(ID) {};
 
        bool runOnFunction(Function &F) override {
            errs() << "EncodeFunctionName: " << F.getName() << " -> ";
 
            if(F.getName().compare("main") !=0){ # 过滤方法名,main方法名不能改,其他方法可以
                llvm::MD5 Hasher; # 使用md5算法修改方法名称
                llvm::MD5::MD5Result Hash; # 使用md5算法修改方法名称
                Hasher.update(F.getName()); # 使用md5算法修改方法名称
                Hasher.update("NewFunctionName"); # 使用md5算法修改方法名称
                Hasher.final(Hash); # 使用md5算法修改方法名称
 
                SmallString<32> HexString; # 使用md5算法修改方法名称
                llvm::MD5::stringifyResult(Hash, HexString);# 使用md5算法修改方法名称
                F.setName(HexString); # 修改方法名称
            }
            errs().write_escaped(F.getName()) << '\n';
            return false;
        }
    };
}
 
char EncodeFunctionName::ID = 0;
static RegisterPass<EncodeFunctionName> X("encode", "Hello EncodeFunctionName Pass");
 
static llvm::RegisterStandardPasses Y(
        llvm::PassManagerBuilder::EP_EarlyAsPossible,
        [](const llvm::PassManagerBuilder &Builder,
           llvm::legacy::PassManagerBase &PM) { PM.add(new EncodeFunctionName()); });
add_llvm_library( LLVMEncodeFunctionName MODULE BUILDTREE_ONLY
  EncodeFunctionName.cpp
 
  DEPENDS
  intrinsics_gen
  PLUGIN_TOOL
  opt
  )
add_llvm_library( LLVMEncodeFunctionName MODULE BUILDTREE_ONLY
  EncodeFunctionName.cpp
 
  DEPENDS
  intrinsics_gen
  PLUGIN_TOOL
  opt
  )
$ cd /Volumes/Work/CLion/Projects/llvm-project-llvmorg-9.0.1/llvm/cmake-build-debug
$ ninja LLVMEncodeFunctionName
[2/2] Linking CXX shared module lib/LLVMEncodeFunctionName.dylib
$ cd /Volumes/Work/CLion/Projects/llvm-project-llvmorg-9.0.1/llvm/cmake-build-debug
$ ninja LLVMEncodeFunctionName
[2/2] Linking CXX shared module lib/LLVMEncodeFunctionName.dylib
# 配置临时环境变量
$ export PATH=/Volumes/Work/CLion/Projects/llvm-project-llvmorg-9.0.1/llvm/cmake-build-debug/bin/:$PATH
# 查看版本信息
$ clang --version
clang version 9.0.1
Target: x86_64-apple-darwin19.6.0
Thread model: posix
InstalledDir: /Volumes/Work/CLion/Projects/llvm-project-llvmorg-9.0.1/llvm/cmake-build-debug/bin
# 编译ll文件
$ clang -emit-llvm main.c -S -o main.ll
# 产生bc文件
$ opt -load /Volumes/Work/CLion/Projects/llvm-project-llvmorg-9.0.1/llvm/cmake-build-debug/lib/LLVMEncodeFunctionName.dylib -encode main.ll -o main.bc
EncodeFunctionName: test -> 5087472e3f661e2a53ecdb4d8dc398a7
EncodeFunctionName: test01 -> e63ae3cc6d7f9892993496b04573c87c
EncodeFunctionName: main -> main
# bc文件转可执行文件
$ clang main.bc -o main_clang
# 配置临时环境变量
$ export PATH=/Volumes/Work/CLion/Projects/llvm-project-llvmorg-9.0.1/llvm/cmake-build-debug/bin/:$PATH
# 查看版本信息
$ clang --version
clang version 9.0.1
Target: x86_64-apple-darwin19.6.0

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 4
支持
分享
最新回复 (9)
雪    币: 8911
活跃值: (5136)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
jgs
2
收藏,mark,不定哪天会用上。
2020-12-26 17:35
0
雪    币: 5482
活跃值: (3272)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
3
mark
2020-12-26 17:54
0
雪    币: 6573
活跃值: (3893)
能力值: (RANK:200 )
在线值:
发帖
回帖
粉丝
4
mark
2020-12-28 10:21
0
雪    币: 3738
活跃值: (3872)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
5
感谢分享!
2020-12-28 10:38
0
雪    币: 2231
活跃值: (1078)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
收藏,mark,不定哪天会用上
2020-12-28 11:52
0
雪    币: 2719
活跃值: (1595)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
7
Ubuntu 不香么
2020-12-29 10:53
0
雪    币: 35
活跃值: (14)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
2020-12-31 08:11
0
雪    币: 355
活跃值: (435)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9

分享快乐
2020-12-31 08:19
0
雪    币: 120
活跃值: (1597)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
收藏,mark,不定哪天会用上。
2022-4-8 20:17
0
游客
登录 | 注册 方可回帖
返回
//