diff options
Diffstat (limited to 'data')
-rw-r--r-- | data/gdb-pre7.0/ChangeLog | 66 | ||||
-rw-r--r-- | data/gdb-pre7.0/gdb-python.diff | 163 | ||||
-rw-r--r-- | data/gdb-pre7.0/mono-gdb.py | 247 | ||||
-rw-r--r-- | data/gdb-pre7.0/mono-gdbinit | 20 | ||||
-rw-r--r-- | data/gdb-pre7.0/test-xdb.py | 19 |
5 files changed, 515 insertions, 0 deletions
diff --git a/data/gdb-pre7.0/ChangeLog b/data/gdb-pre7.0/ChangeLog new file mode 100644 index 00000000000..5ae92a02312 --- /dev/null +++ b/data/gdb-pre7.0/ChangeLog @@ -0,0 +1,66 @@ +2009-10-09 Zoltan Varga <vargaz@gmail.com> + + * mono-gdb.py (MonoSupport.run_hook): Set MONO_XDEBUG to 'gdb' to activate + the GDB support mode in the runtime. + +2009-04-14 Zoltan Varga <vargaz@gmail.com> + + * mono-gdb.py (MonoClassPrinter.to_string): Add a MonoClass* pretty + printer. + +2009-04-12 Zoltan Varga <vargaz@gmail.com> + + * mono-gdb.py (MonoMethodPrinter.to_string): Add a MonoMethod* pretty + printer. + +2009-04-10 Zoltan Varga <vargaz@gmail.com> + + * mono-gdb.py: Update to the latest archer api. + +2009-04-07 Zoltan Varga <vargaz@gmail.com> + + * mono-gdb.py (ObjectPrinter.__init__): Update to latest archer api. + +2009-04-06 Zoltan Varga <vargaz@gmail.com> + + * test-xdb.py: New file, tester script for xdb. + + * mono-gdb.py (stringify_class_name): Handle classes without a namespace + correctly. + + * mono-gdb.py: Update after the changes to dwarfwriter.c. + +2009-04-05 Zoltan Varga <vargaz@gmail.com> + + * mono-gdb.py: Handle superclasses in the pretty printer. + +2009-03-27 Zoltan Varga <vargaz@gmail.com> + + * mono-gdb.py (StringPrinter.to_string): Fix support for non-ascii characters. + +2009-03-20 Zoltan Varga <vargaz@gmail.com> + + * mono-gdb.py: Update for the latest python API on the archer branch. + +2009-02-03 Zoltan Varga <vargaz@gmail.com> + + * mono-gdb.py: Remove the --64 argument to as, it is not needed. + + * mono-gdb.py (stringify_class_name): Helper function to print base types + using their short name. Also add a prototype implementation of registering + the hooks from python code instead of needing the mono-gdbinit file. + + * gdb-python.diff: Changes against the gdb archer branch at + http://sourceware.org/gdb/wiki/PythonGdb to fix some problems/add functionality. + +2009-02-03 Geoff Norton <gnorton@novell.com> + + * mono-gdbinit: Hook into backtrace as hook-stop seems to crash gdb + * mono-gdb.py: Find the gdbinit name from the executable name instead of + hardcoding mono + +2009-01-29 Zoltan Varga <vargaz@gmail.com> + + * mono-gdb.py mono-gdbinit: Support files to help debugging mono/mono apps + using a python enabled gdb. + diff --git a/data/gdb-pre7.0/gdb-python.diff b/data/gdb-pre7.0/gdb-python.diff new file mode 100644 index 00000000000..464a8bed1a8 --- /dev/null +++ b/data/gdb-pre7.0/gdb-python.diff @@ -0,0 +1,163 @@ +diff --git a/gdb/ChangeLog b/gdb/ChangeLog +index 640998b..fb73e9d 100644 +--- a/gdb/ChangeLog ++++ b/gdb/ChangeLog +@@ -1,3 +1,10 @@ ++2009-02-03 Zoltan Varga <vargaz@gmail.com> ++ ++ * cil-script.c python/python-cmd.c: Allow registration of pre/post hooks from ++ python. ++ ++ * symfile.c (add_symbol_file_command): Comment out verbose messages. ++ + 2009-02-03 Thiago Jung Bauermann <bauerman@br.ibm.com> + + * gdb/c-lang.c (c_get_string): Remove superfluous parenthesis from +diff --git a/gdb/cli/cli-script.c b/gdb/cli/cli-script.c +index 835d29c..3941aa5 100644 +--- a/gdb/cli/cli-script.c ++++ b/gdb/cli/cli-script.c +@@ -299,6 +299,13 @@ execute_user_command (struct cmd_list_element *c, char *args) + static int user_call_depth = 0; + extern int max_user_call_depth; + ++ /* Might be a user defined command implemented in Python */ ++ if (!c->user_commands && c->func) ++ { ++ (*c->func) (c, args, FALSE); ++ return; ++ } ++ + old_chain = setup_user_args (args); + + cmdlines = c->user_commands; +diff --git a/gdb/python/python-cmd.c b/gdb/python/python-cmd.c +index 61d5e5d..a3fbc08 100644 +--- a/gdb/python/python-cmd.c ++++ b/gdb/python/python-cmd.c +@@ -339,7 +339,8 @@ gdbpy_parse_command_name (char *text, struct cmd_list_element ***base_list, + + /* Object initializer; sets up gdb-side structures for command. + +- Use: __init__(NAME, CMDCLASS, [COMPLETERCLASS, [PREFIX]]). ++ Use: __init__(NAME, CMDCLASS, [completerclass=COMPLETERCLASS, prefix=PREFIX, ++ pre_hook_of=PREHOOK_OF, post_hook_of=POSTHOOK_OF]). + + NAME is the name of the command. It may consist of multiple words, + in which case the final word is the name of the new command, and +@@ -354,6 +355,11 @@ gdbpy_parse_command_name (char *text, struct cmd_list_element ***base_list, + + If PREFIX is True, then this command is a prefix command. + ++ PREHOOK_OF is the name of a gdb command this command becomes a ++ pre-execution hook of, same as if this command was defined using ++ "define hook-<cmdname>" ++ POSTHOOK_OF is the same for post-execution hooks. ++ + The documentation for the command is taken from the doc string for + the python class. + +@@ -362,15 +368,18 @@ static int + cmdpy_init (PyObject *self, PyObject *args, PyObject *kwds) + { + cmdpy_object *obj = (cmdpy_object *) self; +- char *name; ++ char *name, *pre_hook_of = NULL, *post_hook_of = NULL; + int cmdtype; + int completetype = -1; + char *docstring = NULL; + volatile struct gdb_exception except; + struct cmd_list_element **cmd_list; ++ struct cmd_list_element *pre_hookc = NULL, *post_hookc = NULL; + char *cmd_name, *pfx_name; + PyObject *is_prefix = NULL; + int cmp; ++ static char *kwlist[] = {"name", "cmdclass", "completerclass", "prefix", ++ "pre_hook_of", "post_hook_of", NULL}; + + if (obj->command) + { +@@ -381,8 +390,9 @@ cmdpy_init (PyObject *self, PyObject *args, PyObject *kwds) + return -1; + } + +- if (! PyArg_ParseTuple (args, "si|iO", &name, &cmdtype, +- &completetype, &is_prefix)) ++ if (! PyArg_ParseTupleAndKeywords (args, kwds, "si|iOss", kwlist, &name, &cmdtype, ++ &completetype, &is_prefix, &pre_hook_of, ++ &post_hook_of)) + return -1; + + if (cmdtype != no_class && cmdtype != class_run +@@ -402,6 +412,30 @@ cmdpy_init (PyObject *self, PyObject *args, PyObject *kwds) + return -1; + } + ++ if (pre_hook_of) ++ { ++ char *text = pre_hook_of; ++ ++ pre_hookc = lookup_cmd_1 (&text, cmdlist, NULL, 1); ++ if (! pre_hookc) ++ { ++ PyErr_Format (PyExc_RuntimeError, _("command name given by pre_hook argument not found")); ++ return -1; ++ } ++ } ++ ++ if (post_hook_of) ++ { ++ char *text = post_hook_of; ++ ++ post_hookc = lookup_cmd_1 (&text, cmdlist, NULL, 1); ++ if (! post_hookc) ++ { ++ PyErr_Format (PyExc_RuntimeError, _("command name given by post_hook argument not found")); ++ return -1; ++ } ++ } ++ + cmd_name = gdbpy_parse_command_name (name, &cmd_list, &cmdlist); + if (! cmd_name) + return -1; +@@ -470,6 +504,18 @@ cmdpy_init (PyObject *self, PyObject *args, PyObject *kwds) + cmd->func = cmdpy_function; + cmd->destroyer = cmdpy_destroyer; + ++ if (pre_hookc) ++ { ++ pre_hookc->hook_pre = cmd; ++ cmd->hookee_pre = pre_hookc; ++ } ++ ++ if (post_hookc) ++ { ++ post_hookc->hook_post = cmd; ++ cmd->hookee_post = post_hookc; ++ } ++ + obj->command = cmd; + set_cmd_context (cmd, self); + set_cmd_completer (cmd, ((completetype == -1) ? cmdpy_completer +diff --git a/gdb/symfile.c b/gdb/symfile.c +index 14cb7b8..6d0bb40 100644 +--- a/gdb/symfile.c ++++ b/gdb/symfile.c +@@ -2196,7 +2196,7 @@ add_symbol_file_command (char *args, int from_tty) + statements because hex_string returns a local static + string. */ + +- printf_unfiltered (_("add symbol table from file \"%s\" at\n"), filename); ++ /* printf_unfiltered (_("add symbol table from file \"%s\" at\n"), filename); */ + section_addrs = alloc_section_addr_info (section_index); + make_cleanup (xfree, section_addrs); + for (i = 0; i < section_index; i++) +@@ -2211,7 +2211,7 @@ add_symbol_file_command (char *args, int from_tty) + entered on the command line. */ + section_addrs->other[sec_num].name = sec; + section_addrs->other[sec_num].addr = addr; +- printf_unfiltered ("\t%s_addr = %s\n", sec, paddress (addr)); ++ /* printf_unfiltered ("\t%s_addr = %s\n", sec, paddress (addr)); */ + sec_num++; + + /* The object's sections are initialized when a diff --git a/data/gdb-pre7.0/mono-gdb.py b/data/gdb-pre7.0/mono-gdb.py new file mode 100644 index 00000000000..c360d658f6a --- /dev/null +++ b/data/gdb-pre7.0/mono-gdb.py @@ -0,0 +1,247 @@ +# +# Author: Zoltan Varga (vargaz@gmail.com) +# License: MIT/X11 +# + +# +# This is a mono support mode for a python-enabled gdb: +# http://sourceware.org/gdb/wiki/PythonGdb +# Usage: +# - copy/symlink this file, plus mono-gdbinit to the directory where the mono +# executable lives. +# - run mono under gdb, or attach to a mono process using gdb +# - Type 'xdb' in gdb to load/reload the debugging info emitted by the runtime. +# - The debug info is emitted to a file called xdb.s in the current working directory. +# When attaching to a mono process, make sure you are in the same directory. +# + +import os + +class StringPrinter: + "Print a C# string" + + def __init__(self, val): + self.val = val + + def to_string(self): + if int(self.val.cast (gdb.lookup_type ("guint64"))) == 0: + return "null" + + obj = self.val.cast (gdb.lookup_type ("MonoString").pointer ()).dereference () + len = obj ['length'] + chars = obj ['chars'] + i = 0 + res = ['"'] + while i < len: + val = (chars.cast(gdb.lookup_type ("gint64")) + (i * 2)).cast(gdb.lookup_type ("gunichar2").pointer ()).dereference () + if val >= 256: + c = "\u%X" % val + else: + c = chr (val) + res.append (c) + i = i + 1 + res.append ('"') + return ''.join (res) + +def stringify_class_name(ns, name): + if ns == "System": + if name == "Byte": + return "byte" + if name == "String": + return "string" + if ns == "": + return name + else: + return "%s.%s" % (ns, name) + +class ArrayPrinter: + "Print a C# array" + + def __init__(self, val, class_ns, class_name): + self.val = val + self.class_ns = class_ns + self.class_name = class_name + + def to_string(self): + obj = self.val.cast (gdb.lookup_type ("MonoArray").pointer ()).dereference () + length = obj ['max_length'] + return "%s [%d]" % (stringify_class_name (self.class_ns, self.class_name [0:len(self.class_name) - 2]), int(length)) + +class ObjectPrinter: + "Print a C# object" + + def __init__(self, val): + if str(val.type)[-1] == "&": + self.val = val.address.cast (gdb.lookup_type ("MonoObject").pointer ()) + else: + self.val = val.cast (gdb.lookup_type ("MonoObject").pointer ()) + + class _iterator: + def __init__(self,obj): + self.obj = obj + self.iter = self.obj.type.fields ().__iter__ () + pass + + def __iter__(self): + return self + + def next(self): + field = self.iter.next () + try: + if str(self.obj [field.name].type) == "object": + # Avoid recursion + return (field.name, self.obj [field.name].cast (gdb.lookup_type ("void").pointer ())) + else: + return (field.name, self.obj [field.name]) + except: + # Superclass + return (field.name, self.obj.cast (gdb.lookup_type ("%s" % (field.name)))) + + def children(self): + # FIXME: It would be easier if gdb.Value would support iteration itself + # It would also be better if we could return None + if int(self.val.cast (gdb.lookup_type ("guint64"))) == 0: + return {}.__iter__ () + try: + obj = self.val.dereference () + class_ns = obj ['vtable'].dereference ()['klass'].dereference ()['name_space'].string () + class_name = obj ['vtable'].dereference ()['klass'].dereference ()['name'].string () + if class_name [-2:len(class_name)] == "[]": + return {}.__iter__ () + gdb_type = gdb.lookup_type ("struct %s_%s" % (class_ns.replace (".", "_"), class_name)) + return self._iterator(obj.cast (gdb_type)) + except: + print sys.exc_info ()[0] + print sys.exc_info ()[1] + return {}.__iter__ () + + def to_string(self): + if int(self.val.cast (gdb.lookup_type ("guint64"))) == 0: + return "null" + try: + obj = self.val.dereference () + class_ns = obj ['vtable'].dereference ()['klass'].dereference ()['name_space'].string () + class_name = obj ['vtable'].dereference ()['klass'].dereference ()['name'].string () + if class_ns == "System" and class_name == "String": + return StringPrinter (self.val).to_string () + if class_name [-2:len(class_name)] == "[]": + return ArrayPrinter (self.val,class_ns,class_name).to_string () + if class_ns != "": + try: + gdb_type = gdb.lookup_type ("struct %s.%s" % (class_ns, class_name)) + except: + # Maybe there is no debug info for that type + return "%s.%s" % (class_ns, class_name) + #return obj.cast (gdb_type) + return "%s.%s" % (class_ns, class_name) + return class_name + except: + print sys.exc_info ()[0] + print sys.exc_info ()[1] + # FIXME: This can happen because we don't have liveness information + return self.val.cast (gdb.lookup_type ("guint64")) + +class MonoMethodPrinter: + "Print a MonoMethod structure" + + def __init__(self, val): + self.val = val + + def to_string(self): + if int(self.val.cast (gdb.lookup_type ("guint64"))) == 0: + return "0x0" + val = self.val.dereference () + klass = val ["klass"].dereference () + class_name = stringify_class_name (klass ["name_space"].string (), klass ["name"].string ()) + return "\"%s:%s ()\"" % (class_name, val ["name"].string ()) + # This returns more info but requires calling into the inferior + #return "\"%s\"" % (gdb.parse_and_eval ("mono_method_full_name (%s, 1)" % (str (int (self.val.cast (gdb.lookup_type ("guint64")))))).string ()) + +class MonoClassPrinter: + "Print a MonoClass structure" + + def __init__(self, val): + self.val = val + + def to_string(self): + if int(self.val.cast (gdb.lookup_type ("guint64"))) == 0: + return "0x0" + klass = self.val.dereference () + class_name = stringify_class_name (klass ["name_space"].string (), klass ["name"].string ()) + return "\"%s\"" % (class_name) + # This returns more info but requires calling into the inferior + #return "\"%s\"" % (gdb.parse_and_eval ("mono_type_full_name (&((MonoClass*)%s)->byval_arg)" % (str (int ((self.val).cast (gdb.lookup_type ("guint64"))))))) + +def lookup_pretty_printer(val): + t = str (val.type) + if t == "object": + return ObjectPrinter (val) + if t[0:5] == "class" and t[-1] == "&": + return ObjectPrinter (val) + if t == "string": + return StringPrinter (val) + if t == "MonoMethod *": + return MonoMethodPrinter (val) + if t == "MonoClass *": + return MonoClassPrinter (val) + return None + +def register_csharp_printers(obj): + "Register C# pretty-printers with objfile Obj." + + if obj == None: + obj = gdb + + obj.pretty_printers.append (lookup_pretty_printer) + +register_csharp_printers (gdb.current_objfile()) + +class MonoSupport(object): + + def __init__(self): + self.s_size = 0 + + def run_hook(self): + if os.access ("xdb.s", os.F_OK): + os.remove ("xdb.s") + gdb.execute ("set environment MONO_XDEBUG gdb") + + def stop_hook(self): + # Called when the program is stopped + # Need to recompile+reload the xdb.s file if needed + # FIXME: Need to detect half-written files created when the child is + # interrupted while executing the xdb.s writing code + # FIXME: Handle appdomain unload + if os.access ("xdb.s", os.F_OK): + new_size = os.stat ("xdb.s").st_size + if new_size > self.s_size: + sofile = "xdb.so" + gdb.execute ("shell as -o xdb.o xdb.s && ld -shared -o %s xdb.o" % sofile) + # FIXME: This prints messages which couldn't be turned off + gdb.execute ("add-symbol-file %s 0" % sofile) + self.s_size = new_size + +class RunHook (gdb.Command): + def __init__ (self): + super (RunHook, self).__init__ ("hook-run", gdb.COMMAND_NONE, + gdb.COMPLETE_COMMAND, pre_hook_of="run") + + def invoke(self, arg, from_tty): + mono_support.run_hook () + +print "Mono support loaded." + +mono_support = MonoSupport () + +# This depends on the changes in gdb-python.diff to work +#RunHook () + +# Register our hooks +# This currently cannot be done from python code + +exec_file = gdb.current_objfile ().filename +# FIXME: Is there a way to detect symbolic links ? +if os.stat (exec_file).st_size != os.lstat (exec_file).st_size: + exec_file = os.readlink (exec_file) +exec_dir = os.path.dirname (exec_file) +gdb.execute ("source %s/%s-gdbinit" % (exec_dir, os.path.basename (exec_file))) diff --git a/data/gdb-pre7.0/mono-gdbinit b/data/gdb-pre7.0/mono-gdbinit new file mode 100644 index 00000000000..aed152c5e28 --- /dev/null +++ b/data/gdb-pre7.0/mono-gdbinit @@ -0,0 +1,20 @@ +# Loaded by mono-gdb.py + +# FIXME: According to gdb docs, this is called _before_ anything is printed +# Got broken by this patch: +# http://sourceware.org/ml/gdb-patches/2008-09/msg00193.html +# FIXME: This seems to cause crashes inside gdb +#define hook-stop +# python mono_support.stop_hook () +#end +define hook-backtrace + python mono_support.stop_hook () +end + +define hook-run + python mono_support.run_hook () +end + +define xdb + python mono_support.stop_hook () +end diff --git a/data/gdb-pre7.0/test-xdb.py b/data/gdb-pre7.0/test-xdb.py new file mode 100644 index 00000000000..a78a998e769 --- /dev/null +++ b/data/gdb-pre7.0/test-xdb.py @@ -0,0 +1,19 @@ +# Tester script for the xdb functionality +# Run using gdb -P test-xdb.py <NORMAL GDB COMMAND LINE> + +import sys + +gdb.execute ("file %s" % sys.argv [0]) +gdb.execute ("r --break *:* %s" % " ".join (sys.argv[1:len(sys.argv)])) + +while True: + try: + if gdb.threads () == None: + break + gdb.execute("xdb") + gdb.execute("bt") + gdb.execute("info args") + gdb.execute("info locals") + gdb.execute("c") + except: + gdb.execute ("quit") |