1""" 2LLDB AppKit formatters 3 4Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5See https://llvm.org/LICENSE.txt for license information. 6SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7""" 8# example summary provider for NSMachPort 9# the real summary is now C++ code built into LLDB 10import lldb 11import ctypes 12import lldb.runtime.objc.objc_runtime 13import lldb.formatters.metrics 14import lldb.formatters.Logger 15 16statistics = lldb.formatters.metrics.Metrics() 17statistics.add_metric("invalid_isa") 18statistics.add_metric("invalid_pointer") 19statistics.add_metric("unknown_class") 20statistics.add_metric("code_notrun") 21 22# despite the similary to synthetic children providers, these classes are not 23# trying to provide anything but the port number of an NSMachPort, so they need not 24# obey the interface specification for synthetic children providers 25 26 27class NSMachPortKnown_SummaryProvider: 28 def adjust_for_architecture(self): 29 pass 30 31 def __init__(self, valobj, params): 32 logger = lldb.formatters.Logger.Logger() 33 self.valobj = valobj 34 self.sys_params = params 35 if not (self.sys_params.types_cache.NSUInteger): 36 if self.sys_params.is_64_bit: 37 self.sys_params.types_cache.NSUInteger = ( 38 self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong) 39 ) 40 else: 41 self.sys_params.types_cache.NSUInteger = ( 42 self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt) 43 ) 44 self.update() 45 46 def update(self): 47 logger = lldb.formatters.Logger.Logger() 48 self.adjust_for_architecture() 49 50 # one pointer is the ISA 51 # then we have one other internal pointer, plus 52 # 4 bytes worth of flags. hence, these values 53 def offset(self): 54 logger = lldb.formatters.Logger.Logger() 55 if self.sys_params.is_64_bit: 56 return 20 57 else: 58 return 12 59 60 def port(self): 61 logger = lldb.formatters.Logger.Logger() 62 vport = self.valobj.CreateChildAtOffset( 63 "port", self.offset(), self.sys_params.types_cache.NSUInteger 64 ) 65 return vport.GetValueAsUnsigned(0) 66 67 68class NSMachPortUnknown_SummaryProvider: 69 def adjust_for_architecture(self): 70 pass 71 72 def __init__(self, valobj, params): 73 logger = lldb.formatters.Logger.Logger() 74 self.valobj = valobj 75 self.sys_params = params 76 self.update() 77 78 def update(self): 79 logger = lldb.formatters.Logger.Logger() 80 self.adjust_for_architecture() 81 82 def port(self): 83 logger = lldb.formatters.Logger.Logger() 84 stream = lldb.SBStream() 85 self.valobj.GetExpressionPath(stream) 86 num_children_vo = self.valobj.CreateValueFromExpression( 87 "port", "(int)[" + stream.GetData() + " machPort]" 88 ) 89 if num_children_vo.IsValid(): 90 return num_children_vo.GetValueAsUnsigned(0) 91 return "<variable is not NSMachPort>" 92 93 94def GetSummary_Impl(valobj): 95 logger = lldb.formatters.Logger.Logger() 96 global statistics 97 ( 98 class_data, 99 wrapper, 100 ) = lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection( 101 valobj, statistics 102 ) 103 if wrapper: 104 return wrapper 105 106 name_string = class_data.class_name() 107 logger >> "class name is: " + str(name_string) 108 109 if name_string == "NSMachPort": 110 wrapper = NSMachPortKnown_SummaryProvider(valobj, class_data.sys_params) 111 statistics.metric_hit("code_notrun", valobj) 112 else: 113 wrapper = NSMachPortUnknown_SummaryProvider(valobj, class_data.sys_params) 114 statistics.metric_hit( 115 "unknown_class", valobj.GetName() + " seen as " + name_string 116 ) 117 return wrapper 118 119 120def NSMachPort_SummaryProvider(valobj, dict): 121 logger = lldb.formatters.Logger.Logger() 122 provider = GetSummary_Impl(valobj) 123 if provider is not None: 124 if isinstance( 125 provider, lldb.runtime.objc.objc_runtime.SpecialSituation_Description 126 ): 127 return provider.message() 128 try: 129 summary = provider.port() 130 except: 131 summary = None 132 logger >> "got summary " + str(summary) 133 if summary is None: 134 summary = "<variable is not NSMachPort>" 135 if isinstance(summary, str): 136 return summay 137 return "mach port: " + str(summary) 138 return "Summary Unavailable" 139 140 141def __lldb_init_module(debugger, dict): 142 debugger.HandleCommand( 143 "type summary add -F NSMachPort.NSMachPort_SummaryProvider NSMachPort" 144 ) 145