0%

GDB 实用方法

GDB 的一些实用方法。

线程调试

Reference 4.10 Debugging Programs with Multiple Threads

显示当前所有的线程:

1
info threads

切换到指定线程:

1
thread thread-id

向指定线程执行指令:

1
thread apply [thread-id-list] [all] args

Backtrace

Reference 8.2 Backtraces

显示当前线程的 backtrace:

1
bt

显示指定线程的 backtrace:

1
thread apply thread-id backtrace

显示所有线程的 backtrace:

1
thread apply all backtrace

启动流程

2.1.3 What gdb Does During Startup

Here’s the description of what gdb does during session startup:

  1. Sets up the command interpreter as specified by the command line (see Section 2.1.2 [Mode Options], page 13).

  2. Reads the system-wide init file (if ‘–with-system-gdbinit’ was used when building gdb; see Section C.6 [System-wide configuration and settings], page 612) and executes all the commands in that file.

  3. Reads the init file (if any) in your home directory 1 and executes all the commands in that file.

  4. Executes commands and command files specified by the ‘-iex’ and ‘-ix’ options in their specified order. Usually you should use the ‘-ex’ and ‘-x’ options instead, but this way you can apply settings before gdb init files get executed and before inferior gets loaded.

  5. Processes command line options and operands.

  6. Reads and executes the commands from init file (if any) in the current working directory as long as ‘set auto-load local-gdbinit’ is set to ‘on’ (see Section 22.7.1 [Init File in the Current Directory], page 314). This is only done if the current directory is different from your home directory. Thus, you can have more than one init file, one generic in your home directory, and another, specific to the program you are debugging, in the directory where you invoke gdb.

  7. If the command line specified a program to debug, or a process to attach to, or a core file, gdb loads any auto-loaded scripts provided for the program or for its loaded shared libraries. See Section 22.7 [Auto-loading], page 312. If you wish to disable the auto-loading during startup, you must do something like the following:

    1
    $ gdb -iex "set auto-load python-scripts off" myprogram

    Option ‘-ex’ does not work because the auto-loading is then turned off too late.

  8. Executes commands and command files specified by the ‘-ex’ and ‘-x’ options in their specified order. See Section 23.1.3 [Command Files], page 328, for more details about gdb command files.

  9. Reads the command history recorded in the history file. See Section 22.3 [Command History], page 308, for more details about the command history and the files where gdb records it.

gdb 启动时会默认执行 home 目录下的 .gdbinit,然后执行当前目录下的 .gdbinit

执行命令

启动 gdb 时执行命令

  1. 单个命令

    1
    2
    3
    4
    -eval-command command 
    -ex command
    Execute a single gdb command. This option may be used multiple times to call multiple commands. It may also be interleaved with ‘-command’ as required.
    gdb -ex 'target sim' -ex 'load' -x setbreakpoints -ex 'run' a.out
  2. 命令脚本

    1
    2
    3
    -command file
    -x file
    Execute commands from file file. The contents of this file is evaluated exactly as the source command would. See Section 23.1.3 [Command files], page 328.

启动 gdb 后执行脚本

1
2
source [-s] [-v] filename 
Execute the command file filename.

执行 shell 命令

上面说的方法都只能执行 gdb 内建的命令,若要执行 shell 命令,需要用 gdb shell 命令

1
2
shell command-string !command-string 
Invoke a standard shell to execute command-string. Note that no space is needed between ! and command-string. If it exists, the environment variable SHELL determines which shell to run. Otherwise gdb uses the default shell (‘/bin/sh’ on Unix systems, ‘COMMAND.COM’ on MS-DOS, etc.).

在 windows 上,shell 的命令要放到后台执行,则需使用start /B

实例

有时候需要在命令行启动 gdb 同时执行一些指令,这样就不用每次重复敲一遍了,特别是在脚本内很有用。

比如要在启动 gdb 时启动 openocd 并连接 openocd server,然后让程序在 main 函数停下来:

1
arm-none-eabi-gdb -x .gdbinit -ex 'target remote localhost:3333' -ex 'break main' -ex 'continue' test.elf --tui

在 windows 上 .gdbinit 为:

1
2
3
shell start /B ./mico-os/makefiles/OpenOCD/binary/Win32/openocd_mico 
-f ./mico-os/makefiles/OpenOCD/interface/jlink_swd.cfg
-f ./mico-os/makefiles/OpenOCD/MX1290/MX1290.cfg

在 unix/like 上:

1
2
3
shell ./mico-os/makefiles/OpenOCD/binary/OSX/openocd_mico 
-f ./mico-os/makefiles/OpenOCD/interface/jlink_swd.cfg
-f ./mico-os/makefiles/OpenOCD/MX1290/MX1290.cfg &

其他

  1. 寄存器的读取要使用小写,如 p $basepri

  2. 使用 display /x $basepri,可以在每次操作,如单步后自动显示此寄存器值。

  3. 开启 watch 断点会让速度变慢,不晓得为啥,可能是因为每步都要对比吧。

  4. remote timeout,在调试 MX1101 时遇到了一个问题,先启动 OpenOCD server,再起 gdb 去连接,再等待了一会之后显示失败:

    1
    2
    3
    Ignoring packet error, continuing...
    warning: unrecognized item "timeout" in "qSupported" response
    Remote replied unexpectedly to 'vMustReplyEmpty': PacketSize=3fff;qXfer:memory-map:read-;qXfer:features:read+;QStartNoAckMode+

    OpenOCD 端显示:

    1
    2
    3
    4
    5
    6
    Warn : negative reply, retrying
    Warn : negative reply, retrying
    Warn : negative reply, retrying
    Error: GDB missing ack(2) - assumed good
    Error: GDB missing ack(2) - assumed good
    Error: GDB missing ack(2) - assumed good

    只要在 gdb 命令里加上 set remotetimeout 20 就好了。

    那么为什么连接时间这么久呢,原来是因为我设置的 jtag 速度太慢了 100KHz,所以连接的很慢。并且读写 RAM 的速度也很慢。

  5. watch *address 可以监视某个地址是否被写。

  6. bkpt

坚持原创技术分享,您的支持将鼓励我继续创作!