User forums > Announcements
Release 12.11 has arrived
pitti platsch:
--- Quote from: Taiki on December 26, 2012, 12:43:10 am ---1- Watches window: no more a list of variable of the current function: well, I deal with some quite big functions with over 50 variables. To deal with so much, I've functions that modify a lot of them in the same time but as I don't want to read the whole function, with the old system, I'd to watch on what become red after the function, now, I'll have to add _every variable_ to the window, manually... Please, tell me there is a way to get them all easily, the new system seems to have a lot of things to show but without this, I can't do anything :(
--- End quote ---
Hi,
if you use a recent Python-scriptable GDB (see http://forums.codeblocks.org/index.php/topic,11301.0.html), you can register a pretty printer by calling the register_peter_printers(None) from the following code which I just hacked together. Then add a watch to `(void*****)"FRAME"` and you see all local variables and function arguments.
--- Code: ---import sys
import gdb
import re
class static:
"Creates a 'static' method"
def __init__(self, function):
self.__call__ = function
peter_pretty_printers = []
def register_pretty_printer(pretty_printer):
"Registers a Pretty Printer"
peter_pretty_printers.append(pretty_printer)
return pretty_printer
@register_pretty_printer
class AllLocalsOrArgumentsPrinter:
""" pretty prints `(void*****)"LOCALS"` as a map of all local variables
or `(void*****)"ARGS"` as a map of all function arguments
or `(void*****)"FRAME"` as both
"""
@static
def supports_value(val):
if val.type != gdb.parse_and_eval("(void*****)0").type:
return False
try:
return val.cast(gdb.lookup_type('char').pointer()).string() in ['LOCALS', 'ARGS', 'FRAME']
except:
return False
def __init__(self, val):
self.cmd = val.cast(gdb.lookup_type('char').pointer()).string()
@static
def info_to_string(gdb_command):
result = gdb.execute(gdb_command, to_string=True).strip()
if result in ['No locals.', 'No arguments.']:
return '{}'
# make unique
split_result = re.split(r'^([a-zA-Z_][a-zA-Z0-9_]*) = ', result, flags=re.MULTILINE)
split_result.remove('')
tuples = [(split_result[2*i], split_result[2*i+1].strip('\n')) for i in range(len(split_result)/2)]
tuples.reverse()
result = ''.join([',\n' + k + ' = ' + v for (k,v) in dict(tuples).iteritems()]).lstrip(',')
return '{' + result + '\n}'
def to_string(self):
if self.cmd == 'LOCALS':
return AllLocalsOrArgumentsPrinter.info_to_string('info local')
if self.cmd == 'ARGS':
return AllLocalsOrArgumentsPrinter.info_to_string('info arg')
if self.cmd == 'FRAME':
locals = AllLocalsOrArgumentsPrinter.info_to_string('info local')
args = AllLocalsOrArgumentsPrinter.info_to_string('info arg')
return '{\nLocal Variables = ' + locals + ',\nFunction Arguments = ' + args + '\n}'
return '?'
def register_peter_printers(obj):
if obj == None:
obj = gdb
obj.pretty_printers.append(lookup_function)
def lookup_function(val):
for pp in peter_pretty_printers:
if pp.supports_value(val):
return pp(val)
return None
--- End code ---
cheers,
Peter
ollydbg:
pitti platsch, I see you wrap the gdb command in a "dummy variable in python" :). Please note that why we remove such feature in the debugger plugin. In my gdb release: unofficial MinGW GDB gdb with python released, I use a special patch that compare the current instruction line(Program counter) with the line of a local variable definition, this can void the python script print the uninitialzed local variables.
pitti platsch:
@ollydbg: Yes, my pretty printer works best (or only ;D) with your patched gdb. If I knew a way to iterate all symbols of a frame in python, I would not just call "info local".
But in my opinion, gdb pretty printers must be able to deal with arbitrary/corrupt data.
If a pretty printer crashes/turns into an infinite loop/takes too long to complete when handed some arbitrary bytes, then that pretty printer is buggy and needs to be fixed or disabled:
One of the main points in debugging is to inspect data corruption bugs.
ollydbg:
--- Quote from: pitti platsch on February 04, 2013, 01:43:06 pm ---@ollydbg: Yes, my pretty printer works best (or only ;D) with your patched gdb.
--- End quote ---
Did you test some uninitialzed C++ container as local variables. E.g.
--- Code: ---void f()
{
int a;
vector<string> b;
....Some statement;
map<string,string> c;
}
--- End code ---
If you set a breakpoint in the first line of "f", then "b" and "c" are uninitialized variables, they will cause the python pretty printer try to print a large number of elements. Sometimes, it will take a long time, sometime, gdb may crash. Currently no good way to detect a variable is initialized or not. If not, it may have some corrupt values, as the constructor of the container is not called, mayb, the size of the container may be a large value.
--- Quote ---If I knew a way to iterate all symbols of a frame in python, I would not just call "info local".
But in my opinion, gdb pretty printers must be able to deal with arbitrary/corrupt data.
If a pretty printer crashes/turns into an infinite loop/takes too long to complete when handed some arbitrary bytes, then that pretty printer is buggy and needs to be fixed or disabled:
One of the main points in debugging is to inspect data corruption bugs.
--- End quote ---
I have asked such question in gdb maillist, but it looks like there is no quick solution/fix to handle this issue. Mostly I think the c-runtime-library should fill the memory with some value like "0xCDCDCDCD", and gdb try to exam its value when it want to deference a pointer.....:)
pitti platsch:
With your patched gdb, the variables b and c are not listed in "info local" until I hit there declaration lines. And directly adding a watch to b displays as `No symbol "b" in current context.` when I just enter the function.
You are right that there is no nice simple solution yet. My `(void*****)"LOCALS"` python code is just an ugly hack for those who missed the feature and/or do plain C programming without many other fancy pretty printers. It was the only regression that stopped me from upgrading until I learned python. But now I already fell in love with the 'Evaluate expression' tooltips :)
Apart from that, it would be nice to have a checkbox next to each entry in the Watches window to temporarily enable/disable the watch.
Navigation
[0] Message Index
[#] Next page
[*] Previous page
Go to full version