ardnew
ardnew

Reputation: 2086

Create user-defined gdb command to print all arguments' values to log file

Before combining both of these objectives, I first tried to define a command that will print all arguments to the gdb console:

define printall
  set $n = 0
  while $n < $argc
    eval "print $arg%d", $n
    set $n = $n + 1
  end
end

But even this is not behaving as expected, printing the following when called with 3 variables (C99) of different type (1 float primitive, 2 structs):

(gdb) printall abs_tol point_a interval
$1 = void
$2 = void
$3 = void
(gdb)

Once this is functioning, I would like to define another user-defined command that will evaluate a gdb command and print its output to a log file, similar to:

define logcmd
  if $argc >= 2
    set logging on
    set logging file $arg0 # <-- does this guy need to be quoted?
    set logging overwrite on
    set logging redirect on
    set $n = 1
    while $n < $argc
      eval "$arg%d", $n
      set $n = $n + 1
    end
    set logging off
  end
end

With these two functions defined, I anticipate being able to write an expression:

logcmd values.log "printall abs_tol point_a interval"

But I seem to be missing something fundamental here (with eval maybe?), what gives?

Upvotes: 2

Views: 2812

Answers (1)

Mark Plotnick
Mark Plotnick

Reputation: 10271

Gdb expands arguments in user-defined CLI commands by simple textual substitution. Each occurrence of $arg0, ..., $arg9, and $argc is replaced in each line, before the line is executed1.

Substitution occurs even within double quoted strings, so eval "x/$arg1xg $arg0" does what the user expects2, and printf "$argc is %d\n", $argc will display something like 3 is 3.

Gdb won't recognize $arg%d as something to substitute, though.

But it works better in gdb 8.0 (or gdb 7.12.50 on Ubuntu). Although gdb still won't substitute any args in eval "print $arg%d", $n during its pass through the user-defined command, it adds an additional substitution pass for all eval commands, after the internal printf has been done, before the generated command is executed.

So, the short answer is, your code will work in gdb 8.0.

Your other question was:

set logging file $arg0 # <-- does this guy need to be quoted?

The string after set logging file , through the end of the line, will be used as the filename. You can even have embedded spaces. Do not add quotes! That will give you filenames with quotes in them.

[1]Gdb 8.0 allows an arbitrary number of args, not just 10. This is also the case with the gdb 7.12.50 snapshot that's included with Ubuntu 17.04.

[2]It's probably better to write this as eval "x/%dxg $arg0", $arg1

Upvotes: 3

Related Questions