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

Reply via email to