1

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!

K.Mulier
  • 8,069
  • 15
  • 79
  • 141

3 Answers3

4

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\""
Mark Plotnick
  • 9,598
  • 1
  • 24
  • 40
1

GDB manual clearly documents that .gdbinit is evaluated before any -ex commands.

You could write a trivial shell wrapper that creates a temporary /tmp/.gdbinit.$unique_suffix with appropriate substitutions, invokes gdb -x /tmp/.gdbinit...., and removes the temporary file once GDB exits.

Employed Russian
  • 199,314
  • 34
  • 295
  • 362
  • Hi @EmployedRussian, thanks for your reply. Unfortunately that doesn't work. Even if I don't use a `.gdbinit` file at all, and just type the commands manually in gdb, the `$com` variable doesn't expand (see paragraph 3 in my question). – K.Mulier Jul 05 '20 at 18:03
  • Hi @EmployedRussian, thanks for your help. Your suggestion would certainly work. However, the solution I'm looking for should fit elegantly in our new IDE for microcontrollers (I'm in the startup "Embeetle", building a new IDE for microcontrollers). The solution must therefore be immediately obvious to users who want to edit the `.gdbinit` file themselves (we strive for an IDE that doesn't hide anything behind the scenes, but uses only industry-standard config files, see https://embeetle.com/#comics/cfg_as_code). – K.Mulier Jul 06 '20 at 08:21
1

The format for selecting a COM port on Windows is "//./COM9", so your test in GDB should have used:

$com = COM9
target extended-remote //.$com

I have not tested this, however I would expect it to work.

Sid
  • 563
  • 6
  • 23