I made a proof of concept, which makes it a little nicer: https://github.com/ZedThree/Fortran-gdb-pp . It is not ideal, but it demonstrates a way to at least print dynamic types and their actual values ββand not just the _data and _vptr . I have included an explanation from README below.
How it works?
Unfortunately, we need to get around a few limitations of the gdb python API. First, gdb tells the dynamic_type polymorphic variable as its base type, not its actual dynamic type! This means that we need another way to get its dynamic type. Fortunately, the symbol for the _vptr component (at least with gfortran 7.2) contains a dynamic type, so we can use this. In short, we do the following:
- Find the character for
_vptr - Parse a character to get a dynamic type
- Pass the
_data component _data pointer to a dynamic type and dereference
For 1. we need to get the _vptr character. We can do this in gdb with info symbol foo%_vptr . The python API lacks such a function, so instead we do:
gdb.execute("info symbol {:#x}".format(int(val['_vptr'])))
int(val['_vptr']) gets the address _vptr
Then we need to parse the symbol. With the characters gfortran 7.2, _vptr look like this:
__<module name>_MOD___vtab_<module name>_<Dynamic type> for types defined in modules, or__vab_<program name>_<Dynamic type>.nnnn for types defined in the program
The names of modules and programs can contain underscores, but, fortunately, the type begins with a capital letter, and everything else is lowercase.
Finally, we need to actually print the _data component as a dynamic type. Although the python API provides a Value.cast(type) method, the Value.cast(type) argument must be a gdb.Type object. No matter, we can use the gdb.lookup_type(name) function ... except that this does not work with Fortran types. This time we refuse to use gdb.parse_and_eval :
cast_string = "*({type}*)({address:#x})".format( type=real_type, address=int(val['_data'])) real_val = gdb.parse_and_eval(cast_string)
where real_type is a string containing a dynamic type. This is basically done *(<dynamic type>)(value%_data) , and then we can pass the resulting value to a good printer, which simply returns str(val) , that is, as the default printer.