LLVM 调试环境配置

Posted by Qfrost on 2021-10-14
Estimated Reading Time 7 Minutes
Words 1.3k In Total
Viewed Times

感谢@Richar,教我配出了超级方便的LLVM Pass源码级调试环境 Orzzzz

准备工作

  1. 按照前一篇博客 LLVM编译与FirstPass 配置好LLVM环境和环境变量,LLVM必须用Debug模式编译
  2. 安装好vscode 如果用的是虚拟机则配好vscode remote ssh,WSL的话配好vscode remote WSL

调试环境配置

本来我是想直接将调试环境配置到LLVM源码根目录。但是尝试之后发现用Remote的方式打开源码根目录,vscode要加载的东西太多,代码联想等功能都非常慢,体验很差。因为我们要调试的基本是自己写的Pass,后面发现可以直接配到自己Pass的目录下(这个目录可以在任意位置),然后把包含目录配置到vscode配置文件中就可以了。

现在,假定自己要开发的Pass目录名为MyPass,其中有Pass源代码文件 MyPass.cpp,目标源文件 target.cpp。在MyPass目录下,创建一个.vscode文件夹,在.vscode文件夹中建立三个文件

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
// c_cpp_properties.json  用来配置要包含的头文件和宏
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**",
"/mnt/c/Users/Qfrost/Desktop/code/LLVM/ollvm-12.x-main/llvm/include", // 这里设置为LLVM源码目录的include目录
"/mnt/c/Users/Qfrost/Desktop/code/LLVM/build/include" // 这里设置为LLVM_HOME的include目录
],
"defines": [
"_GNU_SOURCE",
"__STDC_CONSTANT_MACROS",
"__STDC_FORMAT_MACROS",
"__STDC_LIMIT_MACROS"
],
"compilerPath": "/mnt/c/Users/Qfrost/Desktop/code/LLVM/build/bin/clang", // 这里设置为clang的绝对路径(vscode不加载环境变量,必须要用绝对路径)
"cStandard": "c17",
"cppStandard": "c++14",
"intelliSenseMode": "linux-clang-x64",
"compilerArgs": [
"-fno-exceptions",
"-fno-rtti"
]
}
],
"version": 4
}
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
// launch.json   配置调试设置
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug Pass",
"type": "cppdbg",
"request": "launch",
"program": "/mnt/c/Users/Qfrost/Desktop/code/LLVM/build/bin/opt", // 这里设置为opt的绝对路径
"args": [
"-load",
"${fileDirname}/build/${fileBasenameNoExtension}.so",
"-${fileBasenameNoExtension}",
"${fileDirname}/build/1-target_before.bc",
"-o",
"${fileDirname}/build/2-target_after.bc",
],
"stopAtEntry": false,
"cwd": "${fileDirname}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"sourceFileMap":{
// "./": ""
},
"preLaunchTask": "build",
}
]
}
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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
// tasks.json
{
"version": "2.0.0",
"tasks": [
{
"label": "build", // 设置build任务 即 make build -j2
"type": "shell",
"command": "make",
"args": [
"build",
"-j2",
],
"options": {
"cwd": "${workspaceFolder}",
"env": {
"FILE": "${relativeFile}",
"FILE_DIR_NAME": "${fileDirname}",
"FILE_EXT_NAME": "${fileExtname}",
"FILE_BASENAME_NO_EXTENSION": "${fileBasenameNoExtension}"
}
},
"isBackground": false,
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "dedicated",
"showReuseMessage": true,
"clear": true
},
"problemMatcher": {
"owner": "cpp",
"fileLocation": [
"absolute"
],
"pattern": {
"regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)$",
"file": 1,
"line": 2,
"column": 3,
"severity": 4,
"message": 5
}
}
},
{
"label": "run", // 设置run任务
"type": "shell",
"command": "make",
"group": {
"kind": "build",
"isDefault": true
},
"args": [
"run",
"-j2"
],
"options": {
"cwd": "${workspaceFolder}",
"env": {
"FILE": "${relativeFile}",
"FILE_DIR_NAME": "${fileDirname}",
"FILE_EXT_NAME": "${fileExtname}",
"FILE_BASENAME_NO_EXTENSION": "${fileBasenameNoExtension}"
}
},
"isBackground": false,
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "dedicated",
"showReuseMessage": true,
"clear": true
},
"problemMatcher": []
},
{
"label": "clean", // 设置clean任务
"type": "shell",
"command": "make",
"args": [
"clean"
],
"options": {
"cwd": "${workspaceFolder}",
"env": {
"FILE": "${relativeFile}",
"FILE_DIR_NAME": "${fileDirname}",
"FILE_EXT_NAME": "${fileExtname}",
"FILE_BASENAME": "${fileBasename}"
}
},
"isBackground": true,
"presentation": {
"reveal": "never",
},
"problemMatcher": []
}
]
}

以上是.vscode目录下所有配置的内容。然后回到MyPass目录,需要再配置一个makefile

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
TARGRT_FILE=./target.cpp		# 指定目标源文件名

cxxflags=`llvm-config --cxxflags`
ldflags=`llvm-config --ldflags`

build-pass:
@bash -c "if [[ ! -d $(FILE_DIR_NAME)/build ]];then mkdir $(FILE_DIR_NAME)/build;fi"
@g++ $(cxxflags) -ggdb -shared $(ldflags) -fPIC $(FILE) -o $(FILE_DIR_NAME)/build/$(FILE_BASENAME_NO_EXTENSION).so
@echo "\033[32mBuild $(FILE) Successfully.\033[0m"

build-target:
@bash -c "if [[ ! -d $(FILE_DIR_NAME)/build ]];then mkdir $(FILE_DIR_NAME)/build;fi"
@clang -emit-llvm -c $(TARGRT_FILE) -o $(FILE_DIR_NAME)/build/1-target_before.bc
@llvm-dis $(FILE_DIR_NAME)/build/1-target_before.bc
@echo "\033[32mBuild target.cpp successfully.\033[0m"

clean:
rm -rf ./build/*.{o,so,bc}

build: build-pass build-target

run: build
@clear
@opt -load $(FILE_DIR_NAME)/build/$(FILE_BASENAME_NO_EXTENSION).so -$(FILE_BASENAME_NO_EXTENSION) $(FILE_DIR_NAME)/build/1-target_before.bc -o $(FILE_DIR_NAME)/build/2-target_after.bc
@llvm-dis $(FILE_DIR_NAME)/build/2-target_after.bc

大概就是配置这些文件。然后要使用的话,切记要用Remote模式的vscode。比如是WSL的,则要在WSL Shell中敲 “code .”来启动vscode,虚拟机的话则用vscode Remote SSH并打开对应文件夹。然后就可以按快捷键愉快build和调试自己的Pass了

  1. F5调试
  2. Ctrl+Shift+B Run
  3. 终端->运行任务 里面可以看到并运行配置的所有任务

LLVMPassDebug