160 lines · python
1"""2LLDB AppKit formatters3 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-exception7"""8# summary provider for NSURL9import lldb10import ctypes11import lldb.runtime.objc.objc_runtime12import lldb.formatters.metrics13import CFString14import lldb.formatters.Logger15 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 not23# trying to provide anything but a summary for an NSURL, so they need not24# obey the interface specification for synthetic children providers25 26 27class NSURLKnown_SummaryProvider:28 def adjust_for_architecture(self):29 pass30 31 def __init__(self, valobj, params):32 logger = lldb.formatters.Logger.Logger()33 self.valobj = valobj34 self.sys_params = params35 if not (self.sys_params.types_cache.NSString):36 self.sys_params.types_cache.NSString = (37 self.valobj.GetTarget().FindFirstType("NSString").GetPointerType()38 )39 if not (self.sys_params.types_cache.NSURL):40 self.sys_params.types_cache.NSURL = (41 self.valobj.GetTarget().FindFirstType("NSURL").GetPointerType()42 )43 self.update()44 45 def update(self):46 logger = lldb.formatters.Logger.Logger()47 self.adjust_for_architecture()48 49 # one pointer is the ISA50 # then there is one more pointer and 8 bytes of plain data51 # (which are also present on a 32-bit system)52 # then there is a pointer to an NSString which is the url text53 # optionally, the next pointer is another NSURL which is the "base"54 # of this one when doing NSURLs composition (incidentally, NSURLs can55 # recurse the base+text mechanism to any desired depth)56 def offset_text(self):57 logger = lldb.formatters.Logger.Logger()58 return 24 if self.sys_params.is_64_bit else 1659 60 def offset_base(self):61 logger = lldb.formatters.Logger.Logger()62 return self.offset_text() + self.sys_params.pointer_size63 64 def url_text(self):65 logger = lldb.formatters.Logger.Logger()66 text = self.valobj.CreateChildAtOffset(67 "text", self.offset_text(), self.sys_params.types_cache.NSString68 )69 base = self.valobj.CreateChildAtOffset(70 "base", self.offset_base(), self.sys_params.types_cache.NSURL71 )72 my_string = CFString.CFString_SummaryProvider(text, None)73 if len(my_string) > 0 and base.GetValueAsUnsigned(0) != 0:74 # remove final " from myself75 my_string = my_string[0 : len(my_string) - 1]76 my_string = my_string + " -- "77 my_base_string = NSURL_SummaryProvider(base, None)78 if len(my_base_string) > 2:79 # remove @" marker from base URL string80 my_base_string = my_base_string[2:]81 my_string = my_string + my_base_string82 return my_string83 84 85class NSURLUnknown_SummaryProvider:86 def adjust_for_architecture(self):87 pass88 89 def __init__(self, valobj, params):90 logger = lldb.formatters.Logger.Logger()91 self.valobj = valobj92 self.sys_params = params93 self.update()94 95 def update(self):96 logger = lldb.formatters.Logger.Logger()97 self.adjust_for_architecture()98 99 def url_text(self):100 logger = lldb.formatters.Logger.Logger()101 stream = lldb.SBStream()102 self.valobj.GetExpressionPath(stream)103 url_text_vo = self.valobj.CreateValueFromExpression(104 "url", "(NSString*)[" + stream.GetData() + " description]"105 )106 if url_text_vo.IsValid():107 return CFString.CFString_SummaryProvider(url_text_vo, None)108 return "<variable is not NSURL>"109 110 111def GetSummary_Impl(valobj):112 logger = lldb.formatters.Logger.Logger()113 global statistics114 (115 class_data,116 wrapper,117 ) = lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(118 valobj, statistics119 )120 if wrapper:121 return wrapper122 123 name_string = class_data.class_name()124 logger >> "class name is: " + str(name_string)125 126 if name_string == "NSURL":127 wrapper = NSURLKnown_SummaryProvider(valobj, class_data.sys_params)128 statistics.metric_hit("code_notrun", valobj)129 else:130 wrapper = NSURLUnknown_SummaryProvider(valobj, class_data.sys_params)131 statistics.metric_hit(132 "unknown_class", valobj.GetName() + " seen as " + name_string133 )134 return wrapper135 136 137def NSURL_SummaryProvider(valobj, dict):138 logger = lldb.formatters.Logger.Logger()139 provider = GetSummary_Impl(valobj)140 if provider is not None:141 if isinstance(142 provider, lldb.runtime.objc.objc_runtime.SpecialSituation_Description143 ):144 return provider.message()145 try:146 summary = provider.url_text()147 except:148 summary = None149 logger >> "got summary " + str(summary)150 if summary is None or summary == "":151 summary = "<variable is not NSURL>"152 return summary153 return "Summary Unavailable"154 155 156def __lldb_init_module(debugger, dict):157 debugger.HandleCommand(158 "type summary add -F NSURL.NSURL_SummaryProvider NSURL CFURLRef"159 )160