0

In linux, with gdb debugger I can print every object if the program is compiled with -g option. Is it possible to write a function like

template<typename T> ostream& to_stream(ostream& out, const T& obj);

that serialize my object with the name and type?

Naturally with help of gdb call or system call or other.

user202729
  • 3,358
  • 3
  • 25
  • 36

2 Answers2

0

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'});
}
user202729
  • 3,358
  • 3
  • 25
  • 36
-1

Yes, you can do it with python Pretty Printing API. To start with pretty printing, you can look at this question and Tom Tromey's blog: http://tromey.com/blog/?p=524.

ks1322
  • 33,961
  • 14
  • 109
  • 164
  • (I didn't downvote but) I think you misunderstood the question. it asks for how to write C++ function (even before the recent edit) – user202729 Mar 10 '22 at 07:32