硬汉嵌入式论坛

 找回密码
 立即注册
查看: 554|回复: 4
收起左侧

[VS Code] cortex-debug工作原理

[复制链接]

1

主题

7

回帖

10

积分

新手上路

积分
10
发表于 2025-10-16 14:20:40 | 显示全部楼层 |阅读模式
本帖最后由 老叶子 于 2025-10-16 14:36 编辑

请原谅我用这个标题吸引大家进来,其实本文是一篇外文翻译,内容取自cortex-debug github-wiki(Cortex Debug Under the hood)(标题翻译的也没错吧)

翻译的初衷是因为在学习cortex-debug的过程中,发现多数文章仅仅只是给一个配置好的launch.json模板,没有对于cortex-debug更详细的介绍。这篇文章正好可以补足这一点,而且中文互联网上还没有此文的翻译,那么我就结合自己的理解,对文章做一下解读,如有错误,还请指出
Debug file(s)
巧妇难为无米之炊,既然debug,首先要有调试文件。调试文件由程序和调试信息组成,程序烧录到芯片内,调试信息供GDB使用。当两者在一个文件内时,可以使用launch.json中executable属性,当两者不在一起时,loadFiles属性指定待烧录的程序,symboFiles属性指定调试信息。下面两种表达方式是等价的
[C] 纯文本查看 复制代码
{
  "executable": "./aaa.elf",
}

{
  "loadFiles": [
    "./aaa.elf",
  ],
  "symbolFiles": [
    "./aaa.elf",
  ],
}
虽然原文指出“loadFiles可以是 E
LF、二进制或 intel 十六进制格式文件“,但作者经过测试,只支持elf、hex格式,bin文件由于不含有地址信息,无法烧录。
举例几个使用loadFiles、symboFiles的场景:
同时调试flash上的多个程序,比如bootload、app,launch.json如下配置
[C] 纯文本查看 复制代码
{
  "loadFiles": [
    "./bootload.elf",
    "./app.elf",
  ],
  "symbolFiles": [
    "./bootload.elf",
    "./app.elf",
  ],
}
当在boot工程中开启调试时,若转到app工程,vscode会自动打开app工程中对应的源文件。
还有一种情景,bootload是外购的程序,不包含调试信息(已经被strip了),app存放于外置norFlash中,这种情景下不需要向flash中烧录app,只烧录bootload。无法调试bootliad,只能调试app
[C] 纯文本查看 复制代码
{
  "loadFiles": [
    "./bootload—_strip.elf",
  ],
  "symbolFiles": [
    "./app.elf",
  ],
}
launch.json没有executable属性会出现警告,为消除警告,可以将executable的值留空。loadFiles、symbolFiles属性的优先级大于executable属性
[C] 纯文本查看 复制代码
{
  "executable": "",
  "loadFiles": [
    "./bootload.elf",
    "./app.elf",
  ],
  "symbolFiles": [
    "./bootload.elf",
    "./app.elf",
  ],
}
编译时务必使用-g选项,使文件携带调试信息。
调试文件必须是固定地址(没使用-fPIC选项),才能使用executable、loadFiles、symbolFiles属性。对于动态加载程序,可以在postLaunchCommands属性中执行add-symbol-file命令进行调试,具体请参考以下链接
Body part
调试时共有五部分参与,他们之间是线性关系

data-flow.jpg
vscode只是个文本编辑器,并不是IDE,所以并没有调试功能。但vscode为各种语言的调试适配器(Debug Adapter)预留了接口,从而在vscode上实现调试功能。launch.json就是调试适配器的配置文件,cortex-debug就是嵌入式C语言的调试适配器。关于vscode调试功能(如按钮功能、断点、数据检查)如何使用,请参考以下链接
对于C语言程序,launch.json内的属性可分为三部分
vscode通用属性,如type、name、preLaunchTask。此部分属性说明请参考以下连接
调试C/C++的属性,此处的C程序指在Windows、Linux上运行的C程序。此部分属性由C/C++插件提供,说明请参考以下连接
调试嵌入式C/C++的属性。此部分属性由cortex-debug插件提供,说明请参考以下连接
调试嵌入式代码时,launch.json中可以使用vscode的通用属性,但能不能使用C/C++插件的属性,作者没有做过实验,望了解的朋友解答一下。
vscode与调试适配器之间有专用的通讯协议(原文中有链接)。在通讯时,vscode为客户端,调试适配器为服务端,两者间通讯的过程在“调试控制台”用蓝色字体表示。“From client xxx”即为调试适配器从vscode接收到的内容。“To client xxx”即为cortex-debug发向vscode的内容。
在下图中,用户在“调试控制台”输入GDB命令“print retry_count = 123”。通过GDB将变量在内存中的值改变,并将结果反映在调试UI

image.jpg
更常见的情况,并不需要用户输入命令,cortex-debug会直接控制GDB,比如调试配置阶段,调试UI操作

image2.jpg
cortex-debug与gdb交互过程在“调试控制台”用红色字体表示,两者间使用的不是常见的GDB/CLI(Command-Line Interface)命令,而是方便解析的GDB/MI(Machine Interface)命令,两者功能相同,格式不同
关于GDB/MI更多内容,请参考以下链接
cortex-debug发向gdb的格式为:数字序号+“-”+命令,如42-interpreter-exec console "print retry_count = 123"
gdb返回的格式为:->+具体内容,如-> =memory-changed,thread-group="i1",addr="0x20004f0c",len="0x4"
->+数字序号+^done,表示此命令执行完毕,如-> 2^done
Startup process
1.启动GDB
2.通过objdump读取反汇编内容,通过nm读取符号表
3.启动GDBserver
image3.jpg
步骤4-8是原文“Collect gdb+gdb-server commands for start”的内容。在此处,特意说明了在launch.json中request的值不论是launch还是attach,对cortex-debug的影响并不大,原文如下:
image4.jpg
从此链接cortex-debug/debug_attributes.md at master · Marus/cortex-debug也可以看出,多数属性在launch、attach下均可使用
4.一些杂七杂八的命令,作者也看不懂
image5.jpg
5.连接GDBserver与GDB
image6.jpg
6.执行launch.json中preLaunchCommands属性的命令,作者在这使用echo打印了一句话
image7.jpg
7.执行内置启动命令,内置启动命令可以用overrideLaunchCommands属性覆盖。内置命令如下
monitor reset halt
load
monitor reset halt
wiki也解释了这三句命令的含义,大意为:重置停止设备-->烧录程序-->重置停止设备。monitor开头的命令为gdb传递给gdbserver,由gdbserver执行的命令。
调试包含了烧录,所以在preLaunchTask属性指定的任务中,仅编译即可
image8.jpg
8.执行launch.json中postLaunchCommands属性的命令,作者在这使用echo打印了一句话
image9.jpg
9.(可选)调试起始选项。由launch.json中的属性决定其行为
runToEntryPoint:程序一直运行,直到运行到指定函数处暂停
breakAfterReset:在程序第一句处暂停
postStartSessionCommands:用户给定的命令。如果此命令与断点无关,则在程序第一句处暂停
以上属性均没有:程序一直运行,直到第一个断点
Restart or Reset
重启(restart)与重置(reset)在调试中是两个概念。
重启是vscode控制的东西,指的是关闭本次调试,并开启下一次调试,受preLaunchTask属性影响
image10.jpg
重置是cortex-debug控制的东西,指的是芯片的重启
image11.jpg



重置的具体步骤为:
1.执行launch.json中preRestartCommands属性的命令
2.执行内置启动命令,内置启动命令可以用overrideRestartCommands属性覆盖。内置命令如下
monitor reset halt
3.执行launch.json中postRestartCommands属性的命令
注意!!
  • 重置并不会断开GDB、GDBserver之间的链接,所以Startup process步骤中的命令不会被再次执行
  • Startup process步骤中也有monitor reset halt命令,但是并不会触发preRestartCommands、postRestartCommands属性

(完)















评分

参与人数 3金币 +130 收起 理由
桐阴转午 + 20
GGv587 + 10 很给力!
eric2013 + 100 很给力!

查看全部评分

回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
119429
QQ
发表于 2025-10-17 08:51:51 | 显示全部楼层
谢谢楼主分享。
回复

使用道具 举报

59

主题

277

回帖

459

积分

高级会员

积分
459
发表于 2025-10-17 14:07:56 | 显示全部楼层
mark
回复

使用道具 举报

2

主题

20

回帖

26

积分

新手上路

积分
26
发表于 2025-10-18 09:57:18 | 显示全部楼层
较为全面的解析了
回复

使用道具 举报

0

主题

33

回帖

33

积分

新手上路

积分
33
发表于 2025-10-18 23:27:27 | 显示全部楼层
感謝您分享資訊。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-11-21 21:03 , Processed in 0.042700 second(s), 29 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表