This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Re: [rfc] expose gdb values to python
- From: Tom Tromey <tromey at redhat dot com>
- To: Joel Brobecker <brobecker at adacore dot com>
- Cc: Thiago Jung Bauermann <bauerman at br dot ibm dot com>, gdb-patches ml <gdb-patches at sourceware dot org>
- Date: Sat, 04 Oct 2008 17:58:16 -0600
- Subject: Re: [rfc] expose gdb values to python
- References: <1221199426.24580.26.camel@localhost.localdomain> <m3skrv92wf.fsf@fleche.redhat.com> <20081001054741.GE3665@adacore.com> <m3ljx8l5cf.fsf@fleche.redhat.com> <20081004222055.GA7541@caradoc.them.org>
- Reply-to: Tom Tromey <tromey at redhat dot com>
>>>>> "Daniel" == Daniel Jacobowitz <drow@false.org> writes:
Daniel> WDYT about making this work anyway - and using a documented namespace
Daniel> for any methods we add? Then the common case will be able to use the
Daniel> attributes safely.
In practice, I don't mind how it works now. I wrote a few
pretty-printers (appended for your viewing pleasure) and I found that
the array syntax is not a real impediment. If anything, the
dereference method is more of a pain.
FYI -- on the current python branch, Value already has a few more
methods: address, cast, and type.
I guess I wouldn't mind a mangling scheme if it were unobtrusive enough.
Tom
# Pretty-printers for libstc++.
def printstdlist(val):
"Print a std::list"
itype = val.type().template_argument(0)
nodetype = gdb.Type('std::_List_node<%s>' % itype).pointer()
head = val['_M_impl']['_M_node']
base = head['_M_next']
head = head.address()
max = gdb.get_parameter('print elements')
n = 0
result = []
while base != head and (max == 0 or n < max):
elt = base.cast(nodetype).dereference()
datum = elt['_M_data']
result.append ('[%d] = %s' % (n, str (datum)))
n = n + 1
base = elt['_M_next']
if len (result) == 0:
result.append('<<empty list>>')
return "\n".join(result)
def printstdvector(val):
"Print a std::vector"
start = val['_M_impl']['_M_start']
finish = val['_M_impl']['_M_finish']
end = val['_M_impl']['_M_end_of_storage']
max = gdb.get_parameter('print elements')
result = []
result.append('std::vector of length %d, capacity %d'
% (int (finish - start), int (end - start)))
i = 0
while start < finish and (max == 0 or i < max):
result.append('[%d] = %s' % (i, str(start.dereference())))
start = start + 1
i = i + 1
return "\n".join(result)
def printstdstack(val):
"Print a std::stack or std::queue"
# Maybe we should print stack and queue in opposite orders?
cur = val['c']['_M_impl']['_M_start']['_M_cur']
finish = val['c']['_M_impl']['_M_finish']['_M_cur']
i = 0
max = gdb.get_parameter('print elements')
result = ['std::stack or std::queue of size %d' % int (finish -cur)]
while cur != finish and (max == 0 or i < max):
result.append('[%d] = %s' % (i, str (cur.dereference())))
cur = cur + 1
i = i + 1
return "\n".join(result)
def rbtree_to_list(val):
"Turn an rbtree into a size and a list of elements."
maxprint = gdb.get_parameter('print elements')
size = val['_M_t']['_M_impl']['_M_node_count']
if maxprint == 0 or maxprint > size:
maxprint = size
node = val['_M_t']['_M_impl']['_M_header']['_M_left']
i = 0
result = []
while i < maxprint:
result.append(node)
if node.dereference()['_M_right']:
node = node.dereference()['_M_right']
while node.dereference()['_M_left']:
node = node.dereference()['_M_left']
else:
parent = node.dereference()['_M_parent']
while node == parent.dereference()['_M_right']:
node = parent
parent = parent.dereference()['_M_parent']
if node.dereference()['_M_right'] != parent:
node = parent
i = i + 1
return (size, result)
def printstdmap(val):
"Print a std::map"
keytype = val.type().template_argument(0)
valuetype = val.type().template_argument(1)
nodetype = gdb.Type('std::_Rb_tree_node< std::pair< const %s, %s > >' % (keytype, valuetype))
nodetype = nodetype.pointer()
(size, nodes) = rbtree_to_list (val)
result = ['std::map with %d elements' % int (size)]
for node in nodes:
pair = node.cast(nodetype).dereference()['_M_value_field']
result.append('[%s] = %s' % (str (pair['first']), str (pair['second'])))
return "\n".join(result)
def printstdset(val):
"Print a std::set"
keytype = val.type().template_argument(0)
nodetype = gdb.Type("std::_Rb_tree_node< %s >" % keytype).pointer()
(size, nodes) = rbtree_to_list (val)
result = ['std::set with %d elements' % int (size)]
for node in nodes:
elt = node.cast(nodetype).dereference()['_M_value_field']
result.append(' %s' % str (elt))
return "\n".join(result)
def printstdstring(val):
"Print a std::string"
return val['_M_dataplus']['_M_p']
gdb.pretty_printers['^std::list<.*>$'] = printstdlist
gdb.pretty_printers['^std::vector<.*>$'] = printstdvector
gdb.pretty_printers['^std::map<.*>$'] = printstdmap
gdb.pretty_printers['^std::set<.*>$'] = printstdset
gdb.pretty_printers['^std::basic_string<char.*>$'] = printstdstring
gdb.pretty_printers['^std::stack<.*>$'] = printstdstack
gdb.pretty_printers['^std::queue<.*>$'] = printstdstack