This page looks best with JavaScript enabled

LLVM 调试环境配置

 ·  ☕ 3 min read · 👀... views

感谢@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
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

Share on

Qfrost
WRITTEN BY
Qfrost
CTFer, Anti-Cheater, LLVM Committer