GDB-Python-scripting: alle Proben Durchlaufen C/C++ - struct-Felder
Den neuen GDB-Python-scripting-API sieht Recht mächtig und sollte sehr nützlich sein. Jedoch schreiben ein nützliches script zum Durchlaufen der Felder in einem struct in C oder C++ ist nicht trivial. Hat jemand wissen, einige Feste Proben, was genau das macht?
Vielen Dank im Voraus.
Update die endgültige Stichprobe: Ersetzen Sie die _print_fields()
im frühen Probe.
if l.type.code == gdb.TYPE_CODE_STRUCT:
print "Found a struct %s " % n
#self._print_fields(n, t)
self._print_deep_items(n, t, l)
else:
print "Found no struct"
def _print_deep_items (self, n_, type_, instance_):
for fld in type_.fields():
fn = fld.name
ft = fld.type
fv = instance_[fn]
if fv.type.code == gdb.TYPE_CODE_STRUCT:
print " Found a sub struct %s " % fn
self._print_deep_items(fn, ft, fv)
else:
print " Field %s " % fn, " type %s " % ft.tag, " value %s " % fv
Und die Ausgabe:
variable s1 type S1
Found a struct s1
Field v1 type None value 0
Field v2 type None value 0
Found a sub struct v3
Field w3 type None value 0
Update mit der ersten Probe: haben Sie das folgende Beispiel-code funktioniert. Dies ist nicht das optimale, wie es ist ein look-up auf jedes Feld nach dem verfassen des string-Feld name. abarnert zeigt eine vielversprechende und eleganten Ansatz, den funktionierenden code aktualisiert wird, der oben in der letzten update-Abschnitt.
import gdb
class PrintGList(gdb.Command):
"""print fields of a struct: wzd struct_object
Iterate through the fields of a struct, and display
a human-readable form of the objects."""
def __init__(self):
gdb.Command.__init__(self, "wzd", gdb.COMMAND_DATA, gdb.COMPLETE_SYMBOL, True)
def invoke(self, arg, from_tty):
arg_list = gdb.string_to_argv(arg)
if len(arg_list) < 1:
print "usage: wzd struct"
return
n = arg_list[0]
l = gdb.parse_and_eval(arg_list[0])
m = l.type.tag
print " variable %s " % n, " type %s " % m
try:
t = gdb.lookup_type(m)
except RuntimeError, e:
print "type %s not found" % t
return
if l.type.code == gdb.TYPE_CODE_STRUCT:
print "Found a struct %s " % n
self._print_fields(n, t)
else:
print "Found no struct"
def _print_fields(self, n, typeobject):
print typeobject
flds = typeobject.fields()
for x in flds:
sn = n + "." + x.name
print " field %s" % sn, " code %s " % x.type.code, " type %s " % x.type.tag
if x.type.code == gdb.TYPE_CODE_STRUCT:
print "Found sub level struct %s " % sn
sl = gdb.parse_and_eval(sn)
sm = sl.type.tag
st = gdb.lookup_type( sm )
self._print_fields(sn, x.type)
def _deep_items (self, type_):
for k, v in type_.iteritems():
if k:
print " k v %s " % k , " %s " % v
else:
print " v ", " %s " % v
PrintGList()
Der source-Datei zu testen mit:
struct S2 { int w3; };
struct S1 { int v1, v2; struct S2 v3; } s1;
int main(int argc, char *argv[]) { return 0; }
Beispiel-Ausgabe:
variable s1 type S1
Found a struct s1
S1
field s1.v1 typecode 8 type None
field s1.v2 typecode 8 type None
field s1.v3 typecode 3 type S2
Found sub level struct s1.v3
S2
field s1.v3.w3 typecode 8 type None
GDB-Sitzung zu bekommen:
Quelle /home/me/testpath/wzdfile.py
Datei ein.aus
b main
r
wzd s1
beenden Sie
- Haben Sie versucht, Suche durch die Python-Quelltext für die pretty-printers, die mit gcc und gdb? Es müssen gute Beispiele gibt.
- Sind Sie mit Python 2.x, oder 3.x? Was ich sagen kann, gdb kann nun entweder. Und die gdb-docs bedeuten, dass die Arten sind effektiv ausgesetzt, wie python
dict
Objekte. Und die API fürdict
Objekte ist der Unterschied zwischen den beiden Versionen. (Zum Beispiel in 2.x,iteritems()
gibt eine lazy iterator über die Schlüssel-Wert-Paare, währenditems()
gibt eine Liste von Schlüssel-Wert-Paare; in 3.x,items()
gibt eine lazy-iterator, und es gibt keineiteritems()
.) - python 2.6.6, gdb-7.2, x86_64
Du musst angemeldet sein, um einen Kommentar abzugeben.
Laut die docs, Durchlaufen die Felder eines C-struct sollte ziemlich trivial:
Können Sie auch
Type.fields
um die Felder einerstruct
explizit, aber (ab 7.4), können Sie einfach die normalendict
Methoden als gut, so dass man eine Liste von Namen/Field
Paare:Oder, um nur die Namen:
Und so weiter.
Scheint dies nicht direkt dokumentiert auf dieser Seite, aber gdb.Typen deutet es ziemlich stark, wenn es sagt, dass
deep_items
:Beispielsweise diese C-Typ:
Können Sie dies tun:
Von einem schnellen Blick auf die
types.py
Quelle, schauen Sie, wiegdb.types.deep_item(type_)
implementiert ist, und das scheint tatsächlich so zu sein, alles dort ist zu ihm.Bevor gdb 7.4, man konnte nicht behandeln, ein Typ direkt als
dict
. Das heißt, keinefor name in instance_.type:
oderinstance_.type.iteritems()
usw. Sie hatte explizit nennenfields
. Trotzdem, setzen Sie alle zusammen, hier ist ein einfaches Beispiel für die Iteration über alle Felder einer Struktur mit gdb 7.2:Außer, dass das nicht funktionieren, wenn Ihr
struct
hat eine anonymestruct
drin. Für diese, müssen Siedeep_items
(und wenn, dass gibt es nicht in 7.2, müssen Sie Blick auf den code werfen und herausfinden, wie man es selbst implementieren).So, nicht ganz trivial in 7.2, aber ziemlich einfach. Und, wenn Sie möchten, trivial, einfach ein upgrade auf 7.4.
iteritems
ist das auslösen einerAttributeError
währendkeys
ist arbeiten, meine erste Vermutung ist, dass Sie mit Python 3.x, und ich habe Ihnen eine 2.x Antwort. Wenn ja, lassen Sie mich wissen, und ich kann es ändern.print str(instance_)
zeigt{v1 = 0, v2 = 0, v3 = {w3 = 0}}
. Wahrscheinlich ist es trivial, aber wie kann man Sie durchqueren es? Sobald das geschehen ist, denke ich, noch brauchen, um den Typ der einzelnen Elemente. Das sollte alles, was benötigt wird. Ich sah dieser Frage ALSO über den Zugriff auf GDB-python Wert Schlüssel und Werte, dass ist in der Nähe, aber nicht genau das was ich brauche.dict
ist, dass Sie 7.2. Wenn Sie ein upgrade auf eine neuere 7.x der code in meiner Antwort funktioniert. Ansonsten müssen Sie ausdrücklich nennenfields()
.instance_
; Sie haben zu Durchlaufeninstance_.type
oderinstance_.type.fields()
um die Namen und Typen; dann können Sieinstance_[name]
für jeden Namen. Lassen Sie mich aktualisieren meine Antwort zu gehören 7.2 Beispiele (obwohl ich eigentlich gar nicht haben, 7.2, so wird dies nicht getestet).iteritems
auf Ihre eigenen, Feuer einen regelmäßigen Python-interpreter und verwenden Sie die integrierte Hilfe. Sie können, z.B., schreibend={'key': 'value'}
, dannhelp(d)
zu sehen, alle die Dinge, die Sie tun können, mit einemdict
.