165 lines
5.9 KiB
Python
165 lines
5.9 KiB
Python
# Any copyright is dedicated to the Public Domain.
|
|
# http://creativecommons.org/publicdomain/zero/1.0/
|
|
|
|
import lldb
|
|
|
|
from lldbutils import utils
|
|
|
|
|
|
def summarize_string(valobj, internal_dict):
|
|
data = valobj.GetChildMemberWithName("mData")
|
|
length = valobj.GetChildMemberWithName("mLength").GetValueAsUnsigned(0)
|
|
return utils.format_string(data, length)
|
|
|
|
|
|
def summarize_atom(valobj, internal_dict):
|
|
target = lldb.debugger.GetSelectedTarget()
|
|
length = valobj.GetChildMemberWithName("mLength").GetValueAsUnsigned()
|
|
string = target.EvaluateExpression(
|
|
"(char16_t*)%s.GetUTF16String()" % valobj.GetName()
|
|
)
|
|
return utils.format_string(string, length)
|
|
|
|
|
|
class TArraySyntheticChildrenProvider:
|
|
def __init__(self, valobj, internal_dict):
|
|
self.valobj = valobj
|
|
self.header = self.valobj.GetChildMemberWithName("mHdr")
|
|
self.element_type = self.valobj.GetType().GetTemplateArgumentType(0)
|
|
self.element_size = self.element_type.GetByteSize()
|
|
header_size = self.header.GetType().GetPointeeType().GetByteSize()
|
|
self.element_base_addr = self.header.GetValueAsUnsigned(0) + header_size
|
|
|
|
def num_children(self):
|
|
return (
|
|
self.header.Dereference()
|
|
.GetChildMemberWithName("mLength")
|
|
.GetValueAsUnsigned(0)
|
|
)
|
|
|
|
def get_child_index(self, name):
|
|
try:
|
|
index = int(name)
|
|
if index >= self.num_children():
|
|
return None
|
|
# Ideally we'd use the exception type, but it's unclear what that is
|
|
# without knowing how to trigger the original exception.
|
|
except: # NOQA: E501, E722
|
|
pass
|
|
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)
|
|
|
|
|
|
# Used to work around http://llvm.org/bugs/show_bug.cgi?id=22211
|
|
def callfunc(debugger, command, result, dict):
|
|
"""Calls a function for which debugger information is unavailable by getting its address
|
|
from the symbol table. The function is assumed to return void."""
|
|
|
|
if "(" not in command:
|
|
print("Usage: callfunc your_function(args)")
|
|
return
|
|
|
|
command_parts = command.split("(")
|
|
funcname = command_parts[0].strip()
|
|
args = command_parts[1]
|
|
|
|
target = debugger.GetSelectedTarget()
|
|
symbols = target.FindFunctions(funcname).symbols
|
|
if not symbols:
|
|
print('Could not find a function symbol for a function called "%s"' % funcname)
|
|
return
|
|
|
|
sym = symbols[0]
|
|
arg_types = "()"
|
|
if sym.name and sym.name.startswith(funcname + "("):
|
|
arg_types = sym.name[len(funcname) :]
|
|
debugger.HandleCommand(
|
|
"print ((void(*)%s)0x%0x)(%s"
|
|
% (arg_types, sym.addr.GetLoadAddress(target), args)
|
|
)
|
|
|
|
|
|
def init(debugger):
|
|
debugger.HandleCommand(
|
|
"type summary add nsAString -F lldbutils.general.summarize_string"
|
|
)
|
|
debugger.HandleCommand(
|
|
"type summary add nsACString -F lldbutils.general.summarize_string"
|
|
)
|
|
debugger.HandleCommand(
|
|
"type summary add nsFixedString -F lldbutils.general.summarize_string"
|
|
)
|
|
debugger.HandleCommand(
|
|
"type summary add nsFixedCString -F lldbutils.general.summarize_string"
|
|
)
|
|
debugger.HandleCommand(
|
|
"type summary add nsAutoString -F lldbutils.general.summarize_string"
|
|
)
|
|
debugger.HandleCommand(
|
|
"type summary add nsAutoCString -F lldbutils.general.summarize_string"
|
|
)
|
|
debugger.HandleCommand(
|
|
"type summary add nsAtom -F lldbutils.general.summarize_atom"
|
|
)
|
|
debugger.HandleCommand(
|
|
'type synthetic add -x "nsTArray<" -l lldbutils.general.TArraySyntheticChildrenProvider'
|
|
)
|
|
debugger.HandleCommand(
|
|
'type synthetic add -x "AutoTArray<" -l lldbutils.general.TArraySyntheticChildrenProvider' # NOQA: E501
|
|
)
|
|
debugger.HandleCommand(
|
|
'type synthetic add -x "FallibleTArray<" -l lldbutils.general.TArraySyntheticChildrenProvider' # NOQA: E501
|
|
)
|
|
debugger.HandleCommand(
|
|
"command script add -f lldbutils.general.prefcnt -f lldbutils.general.prefcnt prefcnt"
|
|
)
|
|
debugger.HandleCommand(
|
|
"command script add -f lldbutils.general.callfunc -f lldbutils.general.callfunc callfunc"
|
|
)
|