debugginggdbarm-none-eabi-gcc

GDB convenience variable doesn't expand in .gdbinit


I run gdb with a .gdbinit file, which has some convenience variables that just won't expand.

1. My setup

I wrote the following .gdbinit file to flash an executable to a microcontroller through a blackmagic probe (see https://github.com/blacksphere/blackmagic/wiki):

# .gdbinit file:
# ------------------------------------------- #
#              GDB commands                   #
#              FOR STM32F767ZI                #
# ------------------------------------------- #
target extended-remote $com
monitor version
monitor swdp_scan
attach 1
file mcu_application.elf
load
start
detach
quit

The blackmagic probe attaches itself to a COM-port, which can be different on one computer vs another. Therefore, I don't want to hardcode that in the .gdbinit file. A GDB convenience variable looked like the most elegant solution:

https://ftp.gnu.org/old-gnu/Manuals/gdb/html_node/gdb_59.html

So I use the convenience variable $com in the .gdbinit file and I define it on the commandline when I invoke GDB:

arm-none-eabi-gdb -x .gdbinit -ex "set $com = \"COM9\""

2. The error

GDB starts but throws an error message:

.gdbinit:6: Error in sourced command file:
$com: No such file or directory.

It looks like GDB doesn't recognize the $com convenience variable. So I check if GDB actually stored the variable:

(gdb) show convenience
$com = "COM9"
$trace_file = void
$trace_func = void
$trace_line = -1
$tracepoint = -1
$trace_frame = -1
$_inferior = 1
...

This proves that GDB correctly stored it as "COM9". The problem is therefore a failure to expand it.

3. Some more trials

As I observed the failure to expand $com while executing .gdbinit, I thought it might work to issue the commands directly in GDB:

(gdb) set $com = "COM9"

(gdb) show convenience
$com = "COM9"
$trace_file = void
$trace_func = void
...

(gdb) target extended-remote $com
$com: No such file or directory.

But the error persists.

4. Questions

Do you know a way to make the convenience variables in GDB work? Or do you know of another mechanism to reach the same goal?


5. The solution

Thank you @Mark Plotnick for your answer! As you suggested, I gave my .gdbinit file the following content:

define flash-remote
  target extended-remote $arg0
  monitor version
  monitor swdp_scan
  attach 1
  file mcu_application.elf
  load
  start
  detach
  quit
end

However, I had to remove the quotes around the argument COM9 when invoking GDB. So instead of:

arm-none-eabi-gdb -x .gdbinit -ex "flash-remote \"COM9\""

I invoke GDB this way:

arm-none-eabi-gdb -x .gdbinit -ex "flash-remote COM9"

Now it works! You saved my day!


Solution

  • Convenience variables are only expanded in certain contexts - mostly expressions - such as the arguments to print, x, eval, set, and if.

    You could use eval to do what you want:

    eval "target extended-remote %s", $com
    

    But - and this is a big but - until recently, when evaluating expressions, gdb would store string values in the address space of the target, which requires a running process. So on older gdbs, you may get the error message evaluation of this expression requires the target program to be active.

    Gdb does have a more general macro facility: user-defined commands.

    One possibility is to put this in .gdbinit:

    define flash-remote
      target extended-remote $arg0
      monitor version
      monitor swdp_scan
      attach 1
      file mcu_application.elf
      load
      start
      detach
      quit
    end
    

    And invoke gdb like this:

    arm-none-eabi-gdb -ex "flash-remote \"COM9\""