Hi all, one of the archer branches of gdb allows to turn gdb into a python interpreter and allow scripting.
My idea was to use this to track all refcounted objects in WebCore and answer questions like. How many objects are alive? How many objects changed from point a to b? What are the refcounts? Where was the ref count increased? I have a slightly modified release build to turn RefCountedBase into a non inline class and only compile the RefCounted.cpp with -ggdb3 debug support to easily set a breakpoint there. With the attached python script I'm able to keep track of RefCountedBase objects, have commands to print the python dictionary from a gdb cli. I have no other exploring functions in place. I wonder if I could develop this tool inside a subdirectory WebKitTools/Scripts without the usual review process? Due some limitations in the python support the workflow is currently like this: gdb -P script GtKLauncher (gdb) webkit-setup ... questions about pending breakpoints... (gdb) r CTRL+C (gdb) webkit-objects WebCore has 2891 live objects of 0 kinds 0xb3e05784 0xb3d99378 0xb3e1e6ac
""" WebKit object tracking system. This """ import gdb import sys # all allocated and non freed objects live_objects = {} class live_object: """ An object of WebCore with the RefCountedBase base class """ def __init__(self, initial_backtrace, addr): self.addr = addr self.initial_backtrace = initial_backtrace self.obj_type = live_object.determine_type(initial_backtrace) @staticmethod def determine_type(backtrace): """ In general we are not building with RTTI so we can not determine the WebCore type from the given pointer value. We will need to look at the backtrace to determine the type of this object. """ return None def find_this_pointer(frame): for sym in frame.block(): if not sym.is_argument: continue if sym.print_name == "this": return frame.read_var(sym) return None def hash_value(gdb_value): return str(gdb_value) # Functions for gdb as a replacement for callbacks class WebKitObjectCreated(gdb.Function): """ A new RefCountedBase object was created... keep track of it """ def __init__(self): super(WebKitObjectCreated, self).__init__("webkit_new_object") def invoke(self): ptr = find_this_pointer(gdb.selected_frame()) if ptr: assert hash_value(ptr) not in live_objects live_objects[hash_value(ptr)] = live_object(gdb.selected_frame, ptr) return False class WebKitObjectDeleted(gdb.Function): """ A RefCountedBase object was destroyed, clear references to it. """ def __init__(self): super(WebKitObjectDeleted, self).__init__("webkit_delete_object") def invoke(self): ptr = find_this_pointer(gdb.selected_frame()) if ptr: assert hash_value(ptr) in live_objects del live_objects[hash_value(ptr)] return False class WebKitSetup(gdb.Command): """ Setup breakpoints """ def __init__(self): super(WebKitSetup, self).__init__("webkit-setup", gdb.COMMAND_SUPPORT, gdb.COMPLETE_NONE, True) def invoke(self, arg, from_tty): gdb.execute("break WTF::RefCountedBase::RefCountedBase() if $webkit_new_object()") gdb.execute("break WTF::RefCountedBase::~RefCountedBase() if $webkit_delete_object()") class WebKitLiveObjects(gdb.Command): """ List the live objects in webkit... """ def __init__(self): super(WebKitLiveObjects, self).__init__("webkit-objects", gdb.COMMAND_SUPPORT, gdb.COMPLETE_NONE, True) def invoke(self, arg, from_tty): # TODO have some param to filter for a given backtrace/type... sys.stdout.write("WebCore has %d live objects of %d kinds\n" % (len(live_objects), 0)) for live_object in live_objects.keys(): print live_object def webkit_register(): """ Register commands for GDB to use. """ WebKitObjectCreated() WebKitObjectDeleted() #WebKitObjectRef() #WebKitObjectUnref() WebKitSetup() WebKitLiveObjects() def webkit_setup(): """ Setup the """ print sys.argv gdb.execute("file %s" % sys.argv[0]) webkit_register() webkit_setup() print "The executable was loaded. Please invoke the webkit-setup command" gdb.cli()
_______________________________________________ webkit-dev mailing list webkit-dev@lists.webkit.org http://lists.webkit.org/mailman/listinfo.cgi/webkit-dev