搭建一个windows 下应用层能够快捷使用的 llvm 工具链,文中将会解释为什么要这么做,以及阐述其他方式可能会遇到的坑点,同时这个文章只是一个实践文,并不涉及具体原理,只为了提供一个windows 下搭建llvm的最佳实践方案。
为什么不用 VS2019 自带的llvm,而要很复杂的一系列编译替换来捣鼓它?
答:不从头编译llvm项目的话,就无法编译生成Pass,你只是能用clang去编译生成exe,比起VS2019 自带的cl并没有明显优势。作为一个小白,我并不清楚为什么微软回出一个支持llvm工具编译的原因(也许是对于大型c++项目的编译速度考虑?),但对于我们来说,Pass相当于一个插件,起到中间层实际执行混淆的作用,是我们混淆功能的核心,所以必须要用它,而用它,你就需要对llvm进行从头到尾的编译。
为什么一定要用12.0.0版本的llvm?而且llvm 官方文档中支持VS2019直接进行工具链的编译,为什么不用 VS2019 进行项目编译,而要使用mingw来编译llvm项目?
经过对12.0.1 / 12.0.0 / 15.0.6 几个版本的实践,会遇到各种问题,其中最主要的问题是,如果不使用12.0.0 ,你编译出来的llvm 集成到VS 2019中使用时,会出现各种意想不到的错误。另外用MSVC(VS 2019) 编译llvm时,不支持开启BUILD_SHARED_LIBS 选项,但可以使用LLVM_EXPORT_SYMBOLS_FOR_PLUGINS
选项或LLVM_ENABLE_PLUGINS
选项,但这样会出现一个问题,编译后的pass仅能使用new Pass语法,而且必须使用opt 进行加载插件使用,实际只有registerPipelineParsingCallback
回调函数可以正常使用
既然我们需要的只是Pass,也就是一个dll文件,那么我们是否能生成12.0.0 版本的llvm pass,然后就直接用VS 2019 自带的llvm来编译集成呢?
不是自己编译出来的llvm pass 和 自己编译出来的 llvm clang-cl 在使用时会报0x7E(无法加载模块)的错误,因为不想在windows下试图调试llvm 源码找出报错原因,所以只能将就了。
基础环境
windows 10
51cK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6D9L8s2k6E0i4K6u0r3L8r3I4$3L8g2)9J5k6s2m8J5L8$3A6W2j5%4c8Q4x3V1k6J5k6h3I4W2j5i4y4W2M7#2)9J5c8Y4c8S2k6#2)9J5c8X3I4D9N6X3#2G2M7X3N6Q4x3X3b7I4x3W2)9J5k6e0m8Q4x3X3f1H3
CMake (8ceK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6U0L8h3q4C8k6g2)9J5k6h3!0J5k6#2)9J5c8X3c8G2N6$3&6D9L8$3q4V1i4K6u0r3i4K6t1&6
VS 2019 16.11.10
MSYS2
Python
Git
安装MSYS2
PS:llvm 是支持 VS 2019直接去生成llvm的,不用安装这些东西,官方有相关文章(bc6K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6D9L8s2k6E0i4K6u0W2L8%4u0Y4i4K6u0r3k6r3!0U0M7#2)9J5c8V1N6W2N6s2c8A6L8X3N6e0N6r3q4J5N6r3g2V1g2W2y4Q4x3X3g2Z5N6r3#2D9i4K6t1&6i4@1g2r3i4@1u0o6i4K6S2o6i4@1f1%4i4@1u0o6i4K6V1$3i4@1f1^5i4@1q4r3i4K6V1I4i4@1f1#2i4@1u0q4i4K6R3^5i4@1f1#2i4@1u0r3i4@1q4n7i4@1g2r3i4@1u0o6i4K6S2o6i4@1f1@1i4@1u0p5i4K6R3$3i4@1f1%4i4@1u0o6i4K6V1$3i4@1f1#2i4K6R3%4i4@1u0m8i4@1f1$3i4K6W2p5i4@1p5#2i4@1f1@1i4@1t1^5i4K6S2p5i4@1f1@1i4@1u0o6i4K6W2m8i4@1f1#2i4K6R3$3i4K6V1&6i4@1f1%4i4K6W2n7i4@1t1^5i4@1f1#2i4K6R3#2i4@1t1K6f1r3q4K6M7#2!0q4y4g2!0n7z5g2!0n7y4W2!0q4y4g2)9^5z5q4!0m8z5g2!0q4y4#2)9&6y4q4!0m8z5q4!0q4c8W2!0n7b7#2)9^5b7#2!0q4z5q4!0n7c8W2)9&6z5g2!0q4z5g2)9^5y4#2)9^5b7#2!0q4y4#2)9&6y4q4!0m8z5r3N6U0j5H3`.`. + vs2019 构造工具链,欢迎踩完坑后分享~
官网:8fcK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2E0M7%4W2K6x3W2)9J5k6h3!0J5k6#2)9J5c8R3`.`.
详细安装步骤:https://bbs.kanxue.com/thread-272346.htm#msg_header_h3_1
安装后安装gcc工具链
在VS 2019 中安装clang cmake 等工具
将源码解压,文件树如下:
PS:其中build* 文件夹是我运行bat文件后产生的目录,lld 可以不用下载,是之前踩坑的产物
编译源码:
x64_gcc_build.bat 文件内容
x86_gcc_build.bat 文件内容
运行 bat 文件即可编译对应的 llvm
编译安装完成之后可以在下面两个目录中找到编译好的clang 文件
3 . bat文件的内容如下(x86 就是将前面的环境设置为x86的即可):
4 . TestProgram.cpp的内容,是一道简单的re逆向题:
5 . 配置好之后,直接运行bat文件就能编译测试:
我使用的是vs 2019,在之前下载了llvm 12.0 ,并且我们编译替换成自己的,做好准备工作之后,只需要在命令行选项中加入调用语句即可。
使用前还需要将平台工具集先改了
pacman
-
S
-
-
needed base
-
devel mingw
-
w64
-
x86_64
-
toolchain mingw
-
w64
-
i686
-
toolchain cmake
pacman
-
S
-
-
needed base
-
devel mingw
-
w64
-
x86_64
-
toolchain mingw
-
w64
-
i686
-
toolchain cmake
cd C:\Users\admin\Documents\llvmProject12
set
PATH
=
%
PATH
%
;C:\msys64\mingw64\
bin
gcc
-
-
version
cmake
-
G
"MinGW Makefiles"
-
S .
/
llvm
-
B .
/
build_dyn_x64 ^
-
DCMAKE_BUILD_TYPE
=
Release
-
DLLVM_ENABLE_PROJECTS
=
"clang;"
^
-
DLLVM_TARGETS_TO_BUILD
=
"X86"
-
DBUILD_SHARED_LIBS
=
ON ^
-
DLLVM_INCLUDE_TESTS
=
OFF
-
DLLVM_BUILD_TESTS
=
OFF ^
-
DLLVM_INCLUDE_BENCHMARKS
=
OFF
-
DLLVM_BUILD_BENCHMARKS
=
OFF
-
DLLVM_ENABLE_DUMP
=
ON
cmake
-
-
build .
/
build_dyn_x64
-
j
4
cmake
-
DCMAKE_INSTALL_PREFIX
=
"C:\Program Files\LLVM\llvm12\llvm12_dyn_x64"
-
P .\build_dyn_x64\cmake_install.cmake
cd C:\Users\admin\Documents\llvmProject12
set
PATH
=
%
PATH
%
;C:\msys64\mingw64\
bin
gcc
-
-
version
cmake
-
G
"MinGW Makefiles"
-
S .
/
llvm
-
B .
/
build_dyn_x64 ^
-
DCMAKE_BUILD_TYPE
=
Release
-
DLLVM_ENABLE_PROJECTS
=
"clang;"
^
-
DLLVM_TARGETS_TO_BUILD
=
"X86"
-
DBUILD_SHARED_LIBS
=
ON ^
-
DLLVM_INCLUDE_TESTS
=
OFF
-
DLLVM_BUILD_TESTS
=
OFF ^
-
DLLVM_INCLUDE_BENCHMARKS
=
OFF
-
DLLVM_BUILD_BENCHMARKS
=
OFF
-
DLLVM_ENABLE_DUMP
=
ON
cmake
-
-
build .
/
build_dyn_x64
-
j
4
cmake
-
DCMAKE_INSTALL_PREFIX
=
"C:\Program Files\LLVM\llvm12\llvm12_dyn_x64"
-
P .\build_dyn_x64\cmake_install.cmake
cd C:\Users\admin\Documents\llvmProject12
set
PATH
=
%
PATH
%
;C:\msys64\mingw32\
bin
gcc
-
-
version
cmake
-
G
"MinGW Makefiles"
-
S .
/
llvm
-
B .
/
build_dyn_x32 ^
-
DCMAKE_BUILD_TYPE
=
Release
-
DLLVM_ENABLE_PROJECTS
=
"clang;"
^
-
DLLVM_TARGETS_TO_BUILD
=
"X86"
-
DBUILD_SHARED_LIBS
=
ON ^
-
DLLVM_INCLUDE_TESTS
=
OFF
-
DLLVM_BUILD_TESTS
=
OFF ^
-
DLLVM_INCLUDE_BENCHMARKS
=
OFF
-
DLLVM_BUILD_BENCHMARKS
=
OFF
-
DLLVM_ENABLE_DUMP
=
ON
cmake
-
-
build .
/
build_dyn_x32
-
j
4
cmake
-
DCMAKE_INSTALL_PREFIX
=
"C:\Program Files\LLVM\llvm12\llvm12_dyn_x32"
-
P .\build_dyn_x32\cmake_install.cmake
cd C:\Users\admin\Documents\llvmProject12
set
PATH
=
%
PATH
%
;C:\msys64\mingw32\
bin
gcc
-
-
version
cmake
-
G
"MinGW Makefiles"
-
S .
/
llvm
-
B .
/
build_dyn_x32 ^
-
DCMAKE_BUILD_TYPE
=
Release
-
DLLVM_ENABLE_PROJECTS
=
"clang;"
^
-
DLLVM_TARGETS_TO_BUILD
=
"X86"
-
DBUILD_SHARED_LIBS
=
ON ^
-
DLLVM_INCLUDE_TESTS
=
OFF
-
DLLVM_BUILD_TESTS
=
OFF ^
-
DLLVM_INCLUDE_BENCHMARKS
=
OFF
-
DLLVM_BUILD_BENCHMARKS
=
OFF
-
DLLVM_ENABLE_DUMP
=
ON
cmake
-
-
build .
/
build_dyn_x32
-
j
4
cmake
-
DCMAKE_INSTALL_PREFIX
=
"C:\Program Files\LLVM\llvm12\llvm12_dyn_x32"
-
P .\build_dyn_x32\cmake_install.cmake
C:\Program Files\LLVM\llvm12\llvm12_dyn_x64
C:\Program Files\LLVM\llvm12\llvm12_dyn_x32
C:\Program Files\LLVM\llvm12\llvm12_dyn_x64
C:\Program Files\LLVM\llvm12\llvm12_dyn_x32
libstdc
+
+
-
6.dll
libgcc_s_seh
-
1.dll
libwinpthread
-
1.dll
zlib1.dll
libstdc
+
+
-
6.dll
libgcc_s_seh
-
1.dll
libwinpthread
-
1.dll
zlib1.dll
libstdc
+
+
-
6.dll
libgcc_s_dw2
-
1.dll
(这个库名称不一样)
libwinpthread
-
1.dll
zlib1.dll
libstdc
+
+
-
6.dll
libgcc_s_dw2
-
1.dll
(这个库名称不一样)
libwinpthread
-
1.dll
zlib1.dll
project(mydemo)
cmake_minimum_required(VERSION
3.10
)
if
(NOT DEFINED ENV{LLVM_HOME})
message(FATAL_ERROR
"Environment variable $LLVM_HOME is not defined, user should define it before running cmake!"
)
endif()
message(STATUS
"LLVM_HOME = [$ENV{LLVM_HOME}]"
)
if
(NOT DEFINED ENV{LLVM_DIR})
set
(ENV{LLVM_DIR} $ENV{LLVM_HOME}
/
lib
/
cmake
/
llvm)
endif()
if
(NOT EXISTS $ENV{LLVM_DIR})
message(STATUS
"Path ($ENV{LLVM_DIR}) not found!"
)
set
(ENV{LLVM_DIR} $ENV{LLVM_HOME}
/
lib64
/
cmake
/
llvm)
if
(NOT EXISTS $ENV{LLVM_DIR})
message(FATAL_ERROR
"Path ($ENV{LLVM_DIR}) not found!"
)
else
()
message(STATUS
"Path ($ENV{LLVM_DIR}) found!"
)
endif()
else
()
message(STATUS
"Path ($ENV{LLVM_DIR}) found!"
)
endif()
find_package(LLVM REQUIRED CONFIG)
add_definitions(${LLVM_DEFINITIONS})
include_directories(${LLVM_INCLUDE_DIRS})
link_directories(${LLVM_LIBRARY_DIRS})
message(STATUS
"LLVM_DEFINITIONS : ${LLVM_DEFINITIONS}"
)
message(STATUS
"LLVM_INCLUDE_DIRS : ${LLVM_INCLUDE_DIRS}"
)
message(STATUS
"LLVM_LIBRARY_DIRS : ${LLVM_LIBRARY_DIRS}"
)
add_library(mydemo SHARED
.
/
src
/
mydemo.cpp
)
target_compile_features(mydemo PRIVATE cxx_range_for cxx_auto_type)
include_directories(.
/
include)
set_target_properties(mydemo PROPERTIES COMPILE_FLAGS
"-fno-rtti"
)
if
(APPLE)
set_target_properties(mydemo PROPERTIES LINK_FLAGS
"-undefined dynamic_lookup"
)
endif(APPLE)
target_link_libraries(mydemo
libLLVMCore.dll.a
libLLVMSupport.dll.a
libLLVMipo.dll.a
libLLVMDemangle.dll.a
libLLVMTransformUtils.dll.a
libLLVMAnalysis.dll.a
libpthread.a
)
project(mydemo)
cmake_minimum_required(VERSION
3.10
)
if
(NOT DEFINED ENV{LLVM_HOME})
message(FATAL_ERROR
"Environment variable $LLVM_HOME is not defined, user should define it before running cmake!"
)
endif()
message(STATUS
"LLVM_HOME = [$ENV{LLVM_HOME}]"
)
if
(NOT DEFINED ENV{LLVM_DIR})
set
(ENV{LLVM_DIR} $ENV{LLVM_HOME}
/
lib
/
cmake
/
llvm)
endif()
if
(NOT EXISTS $ENV{LLVM_DIR})
message(STATUS
"Path ($ENV{LLVM_DIR}) not found!"
)
set
(ENV{LLVM_DIR} $ENV{LLVM_HOME}
/
lib64
/
cmake
/
llvm)
if
(NOT EXISTS $ENV{LLVM_DIR})
message(FATAL_ERROR
"Path ($ENV{LLVM_DIR}) not found!"
)
else
()
message(STATUS
"Path ($ENV{LLVM_DIR}) found!"
)
endif()
else
()
message(STATUS
"Path ($ENV{LLVM_DIR}) found!"
)
endif()
find_package(LLVM REQUIRED CONFIG)
add_definitions(${LLVM_DEFINITIONS})
include_directories(${LLVM_INCLUDE_DIRS})
link_directories(${LLVM_LIBRARY_DIRS})
message(STATUS
"LLVM_DEFINITIONS : ${LLVM_DEFINITIONS}"
)
message(STATUS
"LLVM_INCLUDE_DIRS : ${LLVM_INCLUDE_DIRS}"
)
message(STATUS
"LLVM_LIBRARY_DIRS : ${LLVM_LIBRARY_DIRS}"
)
add_library(mydemo SHARED
.
/
src
/
mydemo.cpp
)
target_compile_features(mydemo PRIVATE cxx_range_for cxx_auto_type)
include_directories(.
/
include)
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
最后于 2023-6-6 14:55
被Rixo_叶默编辑
,原因: 看到自个文章描述有些不清楚,改了一下描述,让人更容易看懂