1 """ 2 LLDB AppKit formatters 3 4 part of The LLVM Compiler Infrastructure 5 This file is distributed under the University of Illinois Open Source 6 License. See LICENSE.TXT for details. 7 """ 8 # summary provider for NSURL 9 import lldb 10 import ctypes 11 import lldb.runtime.objc.objc_runtime 12 import lldb.formatters.metrics 13 import CFString 14 import lldb.formatters.Logger 15 16 statistics = lldb.formatters.metrics.Metrics() 17 statistics.add_metric('invalid_isa') 18 statistics.add_metric('invalid_pointer') 19 statistics.add_metric('unknown_class') 20 statistics.add_metric('code_notrun') 21 22 # despite the similary to synthetic children providers, these classes are not 23 # trying to provide anything but a summary for an NSURL, so they need not 24 # obey the interface specification for synthetic children providers 25 class NSURLKnown_SummaryProvider: 26 def adjust_for_architecture(self): 27 pass 28 29 def __init__(self, valobj, params): 30 logger = lldb.formatters.Logger.Logger() 31 self.valobj = valobj; 32 self.sys_params = params 33 if not(self.sys_params.types_cache.NSString): 34 self.sys_params.types_cache.NSString = self.valobj.GetTarget().FindFirstType('NSString').GetPointerType() 35 if not(self.sys_params.types_cache.NSURL): 36 self.sys_params.types_cache.NSURL = self.valobj.GetTarget().FindFirstType('NSURL').GetPointerType() 37 self.update(); 38 39 def update(self): 40 logger = lldb.formatters.Logger.Logger() 41 self.adjust_for_architecture(); 42 43 # one pointer is the ISA 44 # then there is one more pointer and 8 bytes of plain data 45 # (which are also present on a 32-bit system) 46 # then there is a pointer to an NSString which is the url text 47 # optionally, the next pointer is another NSURL which is the "base" 48 # of this one when doing NSURLs composition (incidentally, NSURLs can 49 # recurse the base+text mechanism to any desired depth) 50 def offset_text(self): 51 logger = lldb.formatters.Logger.Logger() 52 return 24 if self.sys_params.is_64_bit else 16 53 def offset_base(self): 54 logger = lldb.formatters.Logger.Logger() 55 return self.offset_text()+self.sys_params.pointer_size 56 57 def url_text(self): 58 logger = lldb.formatters.Logger.Logger() 59 text = self.valobj.CreateChildAtOffset("text", 60 self.offset_text(), 61 self.sys_params.types_cache.NSString) 62 base = self.valobj.CreateChildAtOffset("base", 63 self.offset_base(), 64 self.sys_params.types_cache.NSURL) 65 my_string = CFString.CFString_SummaryProvider(text,None) 66 if len(my_string) > 0 and base.GetValueAsUnsigned(0) != 0: 67 # remove final " from myself 68 my_string = my_string[0:len(my_string)-1] 69 my_string = my_string + ' -- ' 70 my_base_string = NSURL_SummaryProvider(base,None) 71 if len(my_base_string) > 2: 72 # remove @" marker from base URL string 73 my_base_string = my_base_string[2:] 74 my_string = my_string + my_base_string 75 return my_string 76 77 78 class NSURLUnknown_SummaryProvider: 79 def adjust_for_architecture(self): 80 pass 81 82 def __init__(self, valobj, params): 83 logger = lldb.formatters.Logger.Logger() 84 self.valobj = valobj; 85 self.sys_params = params 86 self.update() 87 88 def update(self): 89 logger = lldb.formatters.Logger.Logger() 90 self.adjust_for_architecture(); 91 92 def url_text(self): 93 logger = lldb.formatters.Logger.Logger() 94 stream = lldb.SBStream() 95 self.valobj.GetExpressionPath(stream) 96 url_text_vo = self.valobj.CreateValueFromExpression("url","(NSString*)[" + stream.GetData() + " description]") 97 if url_text_vo.IsValid(): 98 return CFString.CFString_SummaryProvider(url_text_vo,None) 99 return '<variable is not NSURL>' 100 101 102 def GetSummary_Impl(valobj): 103 logger = lldb.formatters.Logger.Logger() 104 global statistics 105 class_data,wrapper =lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(valobj,statistics) 106 if wrapper: 107 return wrapper 108 109 name_string = class_data.class_name() 110 logger >> "class name is: " + str(name_string) 111 112 if name_string == 'NSURL': 113 wrapper = NSURLKnown_SummaryProvider(valobj, class_data.sys_params) 114 statistics.metric_hit('code_notrun',valobj) 115 else: 116 wrapper = NSURLUnknown_SummaryProvider(valobj, class_data.sys_params) 117 statistics.metric_hit('unknown_class',valobj.GetName() + " seen as " + name_string) 118 return wrapper; 119 120 def NSURL_SummaryProvider (valobj,dict): 121 logger = lldb.formatters.Logger.Logger() 122 provider = GetSummary_Impl(valobj); 123 if provider != None: 124 if isinstance(provider,lldb.runtime.objc.objc_runtime.SpecialSituation_Description): 125 return provider.message() 126 try: 127 summary = provider.url_text(); 128 except: 129 summary = None 130 logger >> "got summary " + str(summary) 131 if summary == None or summary == '': 132 summary = '<variable is not NSURL>' 133 return summary 134 return 'Summary Unavailable' 135 136 def __lldb_init_module(debugger,dict): 137 debugger.HandleCommand("type summary add -F NSURL.NSURL_SummaryProvider NSURL CFURLRef") 138