本文介绍如何在 CLion 里调试 llvm-readelf,总体思路是建立合适的 cmake 项目,使用合适的IDE 进行调试即可。
一、背景 环境:MacOS,CLion,自行编译完成的LLVM环境(参考 LLVM 第一篇)。
本来是想看看 readelf 源码来学习 ELF 文件格式,但由于肉眼实在是看不懂,就准备下断点调试。llvm-readelf 是软连接到 llvm-readobj 的,源码位于 llvm-project-10.0.0/llvm/tools/llvm-readobj ,而且刚好是一个叶子节点的 Cmake 项目,就尝试将其放到 CLion 里,独立出来,借助LLVM_HOME 目录下的静态链接库和头文件运行。
二、操作步骤 1、编写cmake 文件,使用 llvm 提供的cmake 环境 把原先的 cmake 文件删掉,写成下面的格式(照抄 llvm pass 的编写即可)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 cmake_minimum_required(VERSION 3.4) project(llvm-readobj) # we need LLVM_HOME in order not automatically set LLVM_DIR if (NOT DEFINED ENV{LLVM_HOME}) message(FATAL_ERROR "$LLVM_HOME is not defined") else () set(ENV{LLVM_DIR} $ENV{LLVM_HOME}/lib/cmake/llvm) endif () find_package(LLVM REQUIRED CONFIG) add_definitions(${LLVM_DEFINITIONS}) include_directories(${LLVM_INCLUDE_DIRS}) link_directories(${LLVM_LIBRARY_DIRS}) if (${LLVM_VERSION_MAJOR} VERSION_GREATER_EQUAL 10) set(CMAKE_CXX_STANDARD 14) endif () set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk") add_executable(llvm-readelf ARMWinEHPrinter.cpp COFFDumper.cpp COFFImportDumper.cpp ELFDumper.cpp Error.cpp llvm-readobj.cpp MachODumper.cpp ObjDumper.cpp WasmDumper.cpp Win64EHDumper.cpp WindowsResourceDumper.cpp XCOFFDumper.cpp ) set_target_properties(llvm-readelf PROPERTIES COMPILE_FLAGS "-fno-rtti" ) target_link_libraries(llvm-readelf // TODO: import static library )
这时候就能使用CLion 打开它,有高亮补全,点击编译,会提醒缺失一大堆符号,这是我们预期之内的。
在 LLVM_HOME/lib/cmake/llvm 的 LLVMExports.cmake 文件里,存放了一系列可以被连接的静态库,为了验证方案可行性,先把 target_link_libraries 的内容写全了,每个文件都写进去(太长我就不贴了)。
这时候,llvm-readelf 可以正常运行了。
2、二分法移除不必要的依赖 target_link_libraries 里不是每一项都会被用到,为了优雅,就需要移除不必要的依赖,可以参考 LLVMBuild.txt 的内容。
1 2 3 4 5 [component_0] type = Tool name = llvm-readobj parent = Tools required_libraries = all-targets BitReader Object BinaryFormat DebugInfoCodeView DebugInfoPDB DebugInfoMSF
经过测试,最后得到最小的集合是:
1 2 3 target_link_libraries(llvm-readelf LLVMDebugInfoDWARF )
于是准备工作就完成了
3、直接进行调试 使用 CLion 运行,修改命令行参数,下断点,即可正常调试。
三、效果 非常优雅!
四、总结 虽然 LLVM 非常庞大,使用 cmake 做模块管理,模块化做的还是很好的,舒服了。