9

I am trying to use the pretty printing facilities of GDB to show a custom C++ matrix class.

The class is quite standard you can find anywhere. It is a template parameterized by the type, and can be accessed with C-type notation like mat[i][j]. This first implicitly returns another template "Slice" class representing a row or a column, which can again accessed by the [] operator to extract the data. The class itself is using a plain C array for storage, but it is implementing some tricks on it, like an option of pre-allocating a larger matrix, enabling non-zero starts, using stride etc. The class does not have a native printing interface, and I cannot modify it, or link with my own code easily.

The custom features make it painful to reproduce the direct data access code in Python. But is that necessary? In general: why should pretty printing reproduce the logic of accessing the data? Cannot I just use C++ calls and use the [] operators to print the i,j-th element? The fact that the Slice class is a temporary in GDB during such a request further complicates this.

I am also quite a beginner with python and GDB scripting. I have tried to hack the examples to replace data access with gdb.execute calls, but I have no idea how to access the object name from the to_string function, so I can use something like gdb.execute(??? + '[]+str(i)+']', False, True).

I wonder what is the most effective way of doing this.

user202729
  • 3,358
  • 3
  • 25
  • 36
takbal
  • 183
  • 1
  • 6
  • Side note, you can also choose to write **only** a pretty printer in Python, then call it from C++ side to pretty print it: [How can I make a C++ function that can pretty print every object, using gdb? - Stack Overflow](https://stackoverflow.com/questions/60343020/how-can-i-make-a-c-function-that-can-pretty-print-every-object-using-gdb/71418512#71418512) – user202729 Mar 10 '22 at 04:32
  • Yes **it's possible**. Just use [gdb python api: is it possible to make a call to a class/struct method - Stack Overflow](https://stackoverflow.com/questions/22774067/gdb-python-api-is-it-possible-to-make-a-call-to-a-class-struct-method) (the method name should be something like `operator[]`) – user202729 Mar 10 '22 at 07:06

3 Answers3

7

Cannot I just use C++ calls and use the [] operators to print the i,j-th element?

You can call from the pretty-printer into the inferior (being debugged) process using gdb.parse_and_eval (docs), but this has several disadvantages:

  • you need a "live" process to do this (in other words, your pretty printer will not work when you are debugging a core dump)
  • if the inferior is corrupt in some way, calling functions in it will likely corrupt it even more
  • if the inferior is multi-threaded, and the pretty printer calls into a function that may require a lock (e.g. malloc), then you are very likely to cause the pretty printer to deadlock, and there would not be any way to recover from such deadlock.
Employed Russian
  • 199,314
  • 34
  • 295
  • 362
1

I don't know of a way to get the name of the variable in the to_string function, but you can get the address of the value (if it is addressable) and you can get it's type. (See the docs for more information.)

With this, you can take the address and cast it to pointer to the given type and access it. For example, I used the following to call toStyledString().c_str() on the argument:

eval_string = f"(({self.val.type.name}*)self.val.address})->toStyledString().c_str()"
return gdb.parse_and_eval(eval_string).string()

In your case, you probably want something like the following:

eval_string = f"(*(({self.val.type.name}*)self.val.address}))[{i}]"
sirain
  • 918
  • 10
  • 19
1

This is not python scripting, but simple command sequences for GDB extension. I am defining a new command called print_matrix.

(gdb) define print_matrix
Type commands for definition of "print_matrix".
End with a line saying just "end".
>set $s_arr = $arg0
>set $i=0
>while($i < $arg1)
 >p (int [][$arg2]) *($s_arr + $i)
 >set $i = $i + 1
 >end
>end
(gdb) print_matrix arr 10 10
$90 = {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}}
$91 = {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}
$92 = {{2, 3, 4, 5, 6, 7, 8, 9, 10, 11}}
$93 = {{3, 4, 5, 6, 7, 8, 9, 10, 11, 12}}
$94 = {{4, 5, 6, 7, 8, 9, 10, 11, 12, 13}}
$95 = {{5, 6, 7, 8, 9, 10, 11, 12, 13, 14}}
$96 = {{6, 7, 8, 9, 10, 11, 12, 13, 14, 15}}
$97 = {{7, 8, 9, 10, 11, 12, 13, 14, 15, 16}}
$98 = {{8, 9, 10, 11, 12, 13, 14, 15, 16, 17}}
$99 = {{9, 10, 11, 12, 13, 14, 15, 16, 17, 18}}
(gdb)

You could also save these commands as a script and use -x option

gdb -x <commands file name> binary.out
Kamath
  • 4,461
  • 5
  • 33
  • 60
  • Thanks, but I need to use the pretty printing facility because its integration with Eclipse. – takbal Jan 10 '12 at 10:15