# 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": # 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" )