简体   繁体   English

条件数据观察点在 ARM GDB 中不起作用

[英]Conditional data watchpoint doesn't work in ARM GDB

My intent is to be able to catch when a global variable has some exact value.我的意图是能够捕捉到全局变量何时具有某个确切值。 GDB has data watchpoints according to which this can be implemented. GDB 有数据观察点,据此可以实现。

Consider this simple program written for x86 Linux:考虑为 x86 Linux 编写的这个简单程序:

int myVar = 0;

void debug_watchpoints() {
    for(int i=0; i < 2000; i++) {
        myVar++;
    }
}

int main() {
    debug_watchpoints();
    return 0;
}

Compiling the program with编译程序

gcc -o main -ggdb3 -Og main.c

And starting debugging with GDB:并使用 GDB 开始调试:

max@PC-LT-23:~/stackoverflow$ gdb ./main
GNU gdb (Ubuntu 8.3-0ubuntu1) 8.3
Copyright (C) 2019 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./main...
(gdb) b main 
Breakpoint 1 at 0x1146: file main.c, line 9.
(gdb) start
Temporary breakpoint 2 at 0x1146: file main.c, line 9.
Starting program: /home/max/stackoverflow/main 

Breakpoint 1, main () at main.c:9
9   int main() {
(gdb) watch myVar if myVar==1337
Hardware watchpoint 3: myVar
(gdb) continue
Continuing.

Hardware watchpoint 3: myVar

Old value = 1336
New value = 1337
debug_watchpoints () at main.c:4
4       for(int i=0; i < 2000; i++) {
(gdb) 

As you can see it halted the program at exactly the point in time when the variable was set to 1337.如您所见,它恰好在变量设置为 1337 的时间点停止了程序。

Consider the exact same program , compiled with arm-none-eabi-gcc for a STM32L476RG microcontroller which has a Cortex-M4F core.考虑完全相同的程序,使用arm-none-eabi-gcc为具有 Cortex-M4F 内核的 STM32L476RG 微控制器编译。 The used IDE here is System Workbench for STM32 (aka Eclipse) with a project generated by STM32CubeMX.这里使用的 IDE 是 STM32(又名 Eclipse)的 System Workbench,项目由 STM32CubeMX 生成。

Now launching openocd gives现在启动openocd

Open On-Chip Debugger 0.10.0+dev-00021-g524e8c8 (2019-04-12-08:33)
Licensed under GNU GPL v2
For bug reports, read
    http://openocd.org/doc/doxygen/bugs.html
srst_only separate srst_nogate srst_open_drain connect_assert_srst
Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
padded zone erase set to 1
adapter speed: 8000 kHz
adapter_nsrst_delay: 100
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : clock speed 8000 kHz
Info : STLINK v2.1 JTAG v34 API v2 M25 VID 0x0483 PID 0x374B
Info : using stlink api v2
Info : Target voltage: 0.011074
Error: target voltage may be too low for reliable debugging
Info : Unable to match requested speed 8000 kHz, using 4000 kHz
Info : Stlink adapter speed set to 4000 kHz
Info : STM32L476RGTx.cpu: hardware has 6 breakpoints, 4 watchpoints
Info : Listening on port 3333 for gdb connections
Info : accepting 'gdb' connection on tcp/3333
target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x08001340 msp: 0x20018000

A breakpoint is set in the main function and then the watchpoint is setup exactly like before.main function 中设置断点,然后像以前一样设置观察点。 Also, a breakpoint is is set after the execution of the debug_watchpoints() function.此外,在执行debug_watchpoints() function 后设置断点。

GNU gdb (GNU Tools for Arm Embedded Processors 9-2019-q4-major) 8.3.0.20190709-git
Copyright (C) 2019 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "--host=x86_64-linux-gnu --target=arm-none-eabi".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word".
(gdb) Reset_Handler () at ../startup/startup_stm32l476xx.s:63
63        ldr   sp, =_estack    /* Set stack pointer */

Temporary breakpoint 3, main () at ../Src/main.c:65
65      {

(gdb) watch myVar if myVar==1337
Hardware watchpoint 4: myVar
(gdb) info breakpoints
Num     Type           Disp Enb Address    What
2       breakpoint     keep y   0x08000f46 in main at ../Src/main.c:70
4       hw watchpoint  keep y              myVar
        stop only if myVar==1337
(gdb) 

When continuing the program, it now stops at every modification of the variable with a SIGTRAP , regardless of whether the condition was met or not.继续程序时,它现在会在每次使用SIGTRAP修改变量时停止,无论是否满足条件。

Program received signal SIGTRAP, Trace/breakpoint trap.
0x08000ec2 in debug_watchpoints () at ../Src/main.c:54
54              for(int i=0; i < 2000; i++) {
(gdb) continue
Continuing.

Program received signal SIGTRAP, Trace/breakpoint trap.
0x08000ec2 in debug_watchpoints () at ../Src/main.c:54
54              for(int i=0; i < 2000; i++) {
(gdb) continue
Continuing.

Program received signal SIGTRAP, Trace/breakpoint trap.
0x08000ec2 in debug_watchpoints () at ../Src/main.c:54
54              for(int i=0; i < 2000; i++) {
(gdb) info breakpoint
Num     Type           Disp Enb Address    What
2       breakpoint     keep y   0x08000f46 in main at ../Src/main.c:70
4       hw watchpoint  keep y              myVar
        stop only if myVar==1337
(gdb) print myVar
$2 = 3

I can continue for as many times as I want, it just breaks each and every time the variable is changed.我可以根据需要继续多次,每次更改变量时它都会中断。

In my scenario of "debugging a memory corruption on the stack", I really need GDB to evaluate the condition correctly, otherwise the program stops a thousand times or more (every time a variable which happens to be at this memory location is changed) and not at only the specific time a specific value is written into it to catch a bug.在我的“调试堆栈上的 memory 损坏”的场景中,我真的需要 GDB 来正确评估条件,否则程序会停止一千次或更多次(每次恰好位于此 ZCD69B4957F06CD818D7BF3D618 位置的变量发生变化)不仅在特定时间将特定值写入其中以捕获错误。

Why does arm-none-eabi-gdb differ here in its behavior from normal gdb ?为什么arm-none-eabi-gdb的行为与正常的gdb Could the error lie in the Cortex-M4 hardware debugging capabilities, arm-none-eabi-gdb , or openocd as the GDB server?错误是否在于 Cortex-M4 硬件调试功能arm-none-eabi-gdbopenocd作为 GDB 服务器?

None of the software I know does it out of the box.我所知道的软件都没有开箱即用。 When |I use the DWT usually I set it in my software. |当我使用 DWT 时,我通常在我的软件中设置它。 I have not found any way to program it via any variant of gdb (except manual setting the registers - but it is too annoying)我还没有找到任何方法通过 gdb 的任何变体对其进行编程(手动设置寄存器除外 - 但它太烦人了)

As said, there's no working implementation in openocd, the debugger bridge you are using.如前所述,openocd(您正在使用的调试器桥接器)中没有有效的实现。

You can set by sw.您可以通过 sw 设置。 Here a small snippet.这里有一个小片段。 COMP2, FUNCTION2, COMP1 and FUNCTION1 are DWT registers. COMP2、FUNCTION2、COMP1 和 FUNCTION1 是 DWT 寄存器。 Please note that you need to use two comparators linked together.请注意,您需要使用两个链接在一起的比较器。 Not all Cortex-m implementations support these features and not all comparators are linkable, it depends on your silicon.并非所有 Cortex-m 实现都支持这些功能,也不是所有比较器都是可链接的,这取决于您的芯片。 Also it seems that the capture is asynchonous.此外,捕获似乎是异步的。 Generally my PC stops a few istruction after the trigger.一般来说,我的电脑在触发后会停止一些指令。

DWT->COMP2 = <address to compare>;
DWT->FUNCTION2 = 0;
DWT->COMP1 = <word to compare>;
DWT->FUNCTION1 = 0x20B06;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM