Bug 959922 - Add lldb command to print an object refcount. (DONTBUILD) r=ehsan
authorCameron McCormack <cam@mcc.id.au>
Thu, 16 Jan 2014 17:51:54 +1100
changeset 163750 1c32f9cb5b53e833b52ace7ccacae0a56a06d28f
parent 163749 fbb977ca1d5fa5d1450ccec580085523644d8f56
child 163751 89cb8d7a3719f52df7fe3b13cbfcbb7e6fe43955
push id26011
push userryanvm@gmail.com
push dateThu, 16 Jan 2014 20:06:29 +0000
treeherdermozilla-central@bcbe93f41547 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersehsan
bugs959922
milestone29.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 959922 - Add lldb command to print an object refcount. (DONTBUILD) r=ehsan
python/lldbutils/lldbutils/general.py
python/lldbutils/lldbutils/utils.py
--- a/python/lldbutils/lldbutils/general.py
+++ b/python/lldbutils/lldbutils/general.py
@@ -28,15 +28,49 @@ class TArraySyntheticChildrenProvider:
         return None
 
     def get_child_at_index(self, index):
         if index >= self.num_children():
             return None
         addr = self.element_base_addr + index * self.element_size
         return self.valobj.CreateValueFromAddress("[%d]" % index, addr, self.element_type)
 
+def prefcnt(debugger, command, result, dict):
+    """Displays the refcount of an object."""
+    # We handled regular nsISupports-like refcounted objects and cycle collected
+    # objects.
+    target = debugger.GetSelectedTarget()
+    process = target.GetProcess()
+    thread = process.GetSelectedThread()
+    frame = thread.GetSelectedFrame()
+    obj = frame.EvaluateExpression(command)
+    if obj.GetError().Fail():
+        print "could not evaluate expression"
+        return
+    obj = utils.dereference(obj)
+    field = obj.GetChildMemberWithName("mRefCnt")
+    if field.GetError().Fail():
+        field = obj.GetChildMemberWithName("refCnt")
+    if field.GetError().Fail():
+        print "not a refcounted object"
+        return
+    refcnt_type = field.GetType().GetCanonicalType().GetName()
+    if refcnt_type == "nsAutoRefCnt":
+        print field.GetChildMemberWithName("mValue").GetValueAsUnsigned(0)
+    elif refcnt_type == "nsCycleCollectingAutoRefCnt":
+        print field.GetChildMemberWithName("mRefCntAndFlags").GetValueAsUnsigned(0) >> 2
+    elif refcnt_type == "mozilla::ThreadSafeAutoRefCnt":
+        print field.GetChildMemberWithName("mValue").GetChildMemberWithName("mValue").GetValueAsUnsigned(0)
+    elif refcnt_type == "int":  # non-atomic mozilla::RefCounted object
+        print field.GetValueAsUnsigned(0)
+    elif refcnt_type == "mozilla::Atomic<int>":  # atomic mozilla::RefCounted object
+        print field.GetChildMemberWithName("mValue").GetValueAsUnsigned(0)
+    else:
+        print "unknown mRefCnt type " + refcnt_type
+
 def init(debugger):
     debugger.HandleCommand("type summary add nsAString_internal -F lldbutils.general.summarize_string")
     debugger.HandleCommand("type summary add nsACString_internal -F lldbutils.general.summarize_string")
     debugger.HandleCommand("type synthetic add -x \"nsTArray<\" -l lldbutils.general.TArraySyntheticChildrenProvider")
     debugger.HandleCommand("type synthetic add -x \"nsAutoTArray<\" -l lldbutils.general.TArraySyntheticChildrenProvider")
     debugger.HandleCommand("type synthetic add -x \"FallibleTArray<\" -l lldbutils.general.TArraySyntheticChildrenProvider")
     debugger.HandleCommand("type synthetic add -x \"AutoFallibleTArray<\" -l lldbutils.general.TArraySyntheticChildrenProvider")
+    debugger.HandleCommand("command script add -f lldbutils.general.prefcnt -f lldbutils.general.prefcnt prefcnt")
--- a/python/lldbutils/lldbutils/utils.py
+++ b/python/lldbutils/lldbutils/utils.py
@@ -51,8 +51,20 @@ def format_string(lldb_value, length=100
             terminated = True
             break
         s += format_char(c)
         i = i + 1
     s += "\""
     if not terminated and i != length:
         s += "..."
     return s
+
+# Dereferences a raw pointer, nsCOMPtr, nsRefPtr, nsAutoPtr, already_AddRefed or
+# mozilla::RefPtr; otherwise returns the value unchanged.
+def dereference(lldb_value):
+    if lldb_value.TypeIsPointerType():
+        return lldb_value.Dereference()
+    name = lldb_value.GetType().GetUnqualifiedType().GetName()
+    if name.startswith("nsCOMPtr<") or name.startswith("nsRefPtr<") or name.startswith("nsAutoPtr<") or name.startswith("already_AddRefed<"):
+        return lldb_value.GetChildMemberWithName("mRawPtr")
+    if name.startswith("mozilla::RefPtr<"):
+        return lldb_value.GetChildMemberWithName("ptr")
+    return lldb_value