Bug 959445 - Add lldb summaries for nsIAtoms, nsTextNodes and nsTextFragments showing their text content. r=ehsan
authorCameron McCormack <cam@mcc.id.au>
Wed, 15 Jan 2014 11:29:36 +1100
changeset 163411 bb7af8904cac445e8d044d2e5b49748c64ec24a9
parent 163410 a26c945e9a5c9e6bd5ebd4d668e97ec5cfa20316
child 163412 cd6c3a4beacd3bcd8c818caa4cd0f9c2d93cf282
push id38468
push usercmccormack@mozilla.com
push dateWed, 15 Jan 2014 00:30:27 +0000
treeherdermozilla-inbound@def1c895cd80 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersehsan
bugs959445
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 959445 - Add lldb summaries for nsIAtoms, nsTextNodes and nsTextFragments showing their text content. r=ehsan
.lldbinit
python/lldbutils/lldbutils/__init__.py
python/lldbutils/lldbutils/content.py
python/lldbutils/lldbutils/utils.py
--- a/.lldbinit
+++ b/.lldbinit
@@ -9,8 +9,14 @@ settings set target.inline-breakpoint-st
 # will show a variable declared as "nsIFrame *" that points to an nsBlockFrame
 # object as being of type "nsBlockFrame *" rather than "nsIFrame *".
 settings set target.prefer-dynamic-value run-target
 
 # Import the module that defines complex Gecko debugging commands.  Rather
 # than do any kind of searching, this assumes that you are running lldb from
 # the top level source directory.
 script sys.path.append('python/lldbutils'); import lldbutils; lldbutils.init()
+
+# Show the string value in atoms.
+type summary add nsIAtom --summary-string "${var.mString}"
+
+# Show the value of text nodes.
+type summary add nsTextNode --summary-string "${var.mText}"
--- a/python/lldbutils/lldbutils/__init__.py
+++ b/python/lldbutils/lldbutils/__init__.py
@@ -1,7 +1,13 @@
 import lldb
 
-__all__ = ['layout']
+__all__ = ['content', 'layout', 'utils']
 
 def init():
     for name in __all__:
-        __import__('lldbutils.' + name, globals(), locals(), ['init']).init(lldb.debugger)
+        init = None
+        try:
+            init = __import__('lldbutils.' + name, globals(), locals(), ['init']).init
+        except AttributeError:
+            pass
+        if init:
+            init(lldb.debugger)
new file mode 100644
--- /dev/null
+++ b/python/lldbutils/lldbutils/content.py
@@ -0,0 +1,16 @@
+import lldb
+from lldbutils import utils
+
+def summarize_text_fragment(valobj, internal_dict):
+    content_union = valobj.GetChildAtIndex(0)
+    state_union = valobj.GetChildAtIndex(1).GetChildMemberWithName("mState")
+    length = state_union.GetChildMemberWithName("mLength").GetValueAsUnsigned(0)
+    if state_union.GetChildMemberWithName("mIs2b").GetValueAsUnsigned(0):
+        field = "m2b"
+    else:
+        field = "m1b"
+    ptr = content_union.GetChildMemberWithName(field)
+    return utils.format_string(ptr, length)
+
+def init(debugger):
+    debugger.HandleCommand("type summary add nsTextFragment -F lldbutils.content.summarize_text_fragment")
new file mode 100644
--- /dev/null
+++ b/python/lldbutils/lldbutils/utils.py
@@ -0,0 +1,58 @@
+def format_char(c):
+    if c == 0:
+        return "\\0"
+    elif c == 0x07:
+        return "\\a"
+    elif c == 0x08:
+        return "\\b"
+    elif c == 0x0c:
+        return "\\f"
+    elif c == 0x0a:
+        return "\\n"
+    elif c == 0x0d:
+        return "\\r"
+    elif c == 0x09:
+        return "\\t"
+    elif c == 0x0b:
+        return "\\v"
+    elif c == 0x5c:
+        return "\\"
+    elif c == 0x22:
+        return "\\\""
+    elif c == 0x39:
+        return "\\'"
+    elif c < 0x20 or c >= 0x80 and c <= 0xff:
+        return "\\x%02x" % c
+    elif c >= 0x0100:
+        return "\\u%04x" % c
+    else:
+        return chr(c)
+
+# Take an SBValue that is either a char* or char16_t* and formats it like lldb
+# would when printing it.
+def format_string(lldb_value, length=100):
+    ptr = lldb_value.GetValueAsUnsigned(0)
+    char_type = lldb_value.GetType().GetPointeeType()
+    if char_type.GetByteSize() == 1:
+        s = "\""
+        size = 1
+        mask = 0xff
+    elif char_type.GetByteSize() == 2:
+        s = "u\""
+        size = 2
+        mask = 0xffff
+    else:
+        return "(cannot format string with char type %s)" % char_type.GetName()
+    i = 0
+    terminated = False
+    while i < length:
+        c = lldb_value.CreateValueFromAddress("x", ptr + i * size, char_type).GetValueAsUnsigned(0) & mask
+        if c == 0:
+            terminated = True
+            break
+        s += format_char(c)
+        i = i + 1
+    s += "\""
+    if not terminated and i != length:
+        s += "..."
+    return s