If you don't have gdb, you can't do much.
magic_get
works in some limited cases.
For the rest you mostly have to manually specify the field names, possibly through a macro to make it more convenient, but still manual.
visual c++ - Printing values of all fields in a C++ structure - Stack Overflow
If you have gdb (as in, you can guarantee the program will be run in gdb) however, (as specified in the question),
use a technique in
c - Sending commands to gdb from the debugged program - Stack Overflow
we have (you need the Python code copied from that post run in gdb)
void gdb_run([[maybe_unused]] char const* str) {}
template<class T> void gdb_pretty_print([[maybe_unused]] T const& arg){
gdb_run("up\nprint arg");
}
struct Example{
int a;
char b;
};
int main(){
gdb_pretty_print(Example{1, '0'});
}
If you want to get the result to pass to C++ you can do something like
template<class T> void gdb_pretty_print([[maybe_unused]] T const& arg){
char const* volatile result=nullptr;
gdb_run("up\n"
"python gdb.set_convenience_variable('result', gdb.execute('print arg', to_string=True))\n"
"set result=$result");
__builtin_printf("result = %s\n", result);
}
Actually I'm not sure if volatile
will do it, alternatively compile the particular with -O0
.
Alternatively you may try to set break point within gdb_pretty_print
itself, but I tried it's pretty hard.
class GdbPrettyPrint(gdb.Breakpoint):
def __init__(self, function_name):
super().__init__(function_name, internal=1)
self.silent = True
def stop(self):
gdb.execute("print arg")
return False
def set_breaks():
for b in gdb.rbreak("^gdb_pretty_print<"):
GdbPrettyPrint(b.location.split(":")[-1])
b.delete()
You have to run the set_breaks()
function unfortunately. For some reason rbreak
alone doesn't work for me.
Example program
template<class T> void gdb_pretty_print(T const& arg){
(void) arg;
}
struct Example{
int a;
char b;
};
int main(){
gdb_pretty_print(Example{1, '0'});
}