blob: 298150e6cc0a51392f1315f94bd52edf78683818 [file] [log] [blame]
Enrico Granata3f1052b2012-03-13 21:52:00 +00001"""
2LLDB AppKit formatters
3
4part of The LLVM Compiler Infrastructure
5This file is distributed under the University of Illinois Open Source
6License. See LICENSE.TXT for details.
7"""
Enrico Granata50b5ee52013-03-16 00:50:25 +00008# example summary provider for NSBundle
9# the real summary is now C++ code built into LLDB
Enrico Granataeb4a4792012-02-23 23:10:27 +000010import lldb
11import ctypes
Enrico Granata28399ad2012-04-25 01:39:27 +000012import lldb.runtime.objc.objc_runtime
13import lldb.formatters.metrics
Enrico Granataeb4a4792012-02-23 23:10:27 +000014import NSURL
Enrico Granata28399ad2012-04-25 01:39:27 +000015import lldb.formatters.Logger
Enrico Granataeb4a4792012-02-23 23:10:27 +000016
Enrico Granata28399ad2012-04-25 01:39:27 +000017statistics = lldb.formatters.metrics.Metrics()
Enrico Granataeb4a4792012-02-23 23:10:27 +000018statistics.add_metric('invalid_isa')
19statistics.add_metric('invalid_pointer')
20statistics.add_metric('unknown_class')
21statistics.add_metric('code_notrun')
22
23# despite the similary to synthetic children providers, these classes are not
24# trying to provide anything but a summary for an NSURL, so they need not
25# obey the interface specification for synthetic children providers
Kate Stoneb9c1b512016-09-06 20:57:50 +000026
27
Enrico Granataeb4a4792012-02-23 23:10:27 +000028class NSBundleKnown_SummaryProvider:
Enrico Granataeb4a4792012-02-23 23:10:27 +000029
Kate Stoneb9c1b512016-09-06 20:57:50 +000030 def adjust_for_architecture(self):
31 pass
Enrico Granataeb4a4792012-02-23 23:10:27 +000032
Kate Stoneb9c1b512016-09-06 20:57:50 +000033 def __init__(self, valobj, params):
34 logger = lldb.formatters.Logger.Logger()
35 self.valobj = valobj
36 self.sys_params = params
37 if not(self.sys_params.types_cache.NSString):
38 self.sys_params.types_cache.NSString = self.valobj.GetTarget(
39 ).FindFirstType('NSString').GetPointerType()
40 self.update()
Enrico Granataeb4a4792012-02-23 23:10:27 +000041
Kate Stoneb9c1b512016-09-06 20:57:50 +000042 def update(self):
43 logger = lldb.formatters.Logger.Logger()
44 self.adjust_for_architecture()
Enrico Granataeb4a4792012-02-23 23:10:27 +000045
Kate Stoneb9c1b512016-09-06 20:57:50 +000046 # we need to skip the ISA, plus four other values
47 # that are luckily each a pointer in size
48 # which makes our computation trivial :-)
49 def offset(self):
50 logger = lldb.formatters.Logger.Logger()
51 return 5 * self.sys_params.pointer_size
52
53 def url_text(self):
54 logger = lldb.formatters.Logger.Logger()
55 global statistics
56 text = self.valobj.CreateChildAtOffset(
57 "text", self.offset(), self.sys_params.types_cache.NSString)
58 my_string = text.GetSummary()
59 if (my_string is None) or (my_string == ''):
60 statistics.metric_hit(
61 'unknown_class', str(
62 self.valobj.GetName()) + " triggered unknown pointer location")
63 return NSBundleUnknown_SummaryProvider(
64 self.valobj, self.sys_params).url_text()
65 else:
66 statistics.metric_hit('code_notrun', self.valobj)
67 return my_string
Enrico Granataeb4a4792012-02-23 23:10:27 +000068
69
70class NSBundleUnknown_SummaryProvider:
Enrico Granataeb4a4792012-02-23 23:10:27 +000071
Kate Stoneb9c1b512016-09-06 20:57:50 +000072 def adjust_for_architecture(self):
73 pass
Enrico Granataeb4a4792012-02-23 23:10:27 +000074
Kate Stoneb9c1b512016-09-06 20:57:50 +000075 def __init__(self, valobj, params):
76 logger = lldb.formatters.Logger.Logger()
77 self.valobj = valobj
78 self.sys_params = params
79 self.update()
Enrico Granataeb4a4792012-02-23 23:10:27 +000080
Kate Stoneb9c1b512016-09-06 20:57:50 +000081 def update(self):
82 logger = lldb.formatters.Logger.Logger()
83 self.adjust_for_architecture()
84
85 def url_text(self):
86 logger = lldb.formatters.Logger.Logger()
87 stream = lldb.SBStream()
88 self.valobj.GetExpressionPath(stream)
89 expr = "(NSString*)[" + stream.GetData() + " bundlePath]"
90 url_text_vo = self.valobj.CreateValueFromExpression("path", expr)
91 if url_text_vo.IsValid():
92 return url_text_vo.GetSummary()
93 return '<variable is not NSBundle>'
Enrico Granataeb4a4792012-02-23 23:10:27 +000094
95
96def GetSummary_Impl(valobj):
Kate Stoneb9c1b512016-09-06 20:57:50 +000097 logger = lldb.formatters.Logger.Logger()
98 global statistics
99 class_data, wrapper = lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(
100 valobj, statistics)
101 if wrapper:
102 return wrapper
Enrico Granataeb4a4792012-02-23 23:10:27 +0000103
Kate Stoneb9c1b512016-09-06 20:57:50 +0000104 name_string = class_data.class_name()
105 logger >> "class name is: " + str(name_string)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000106
Kate Stoneb9c1b512016-09-06 20:57:50 +0000107 if name_string == 'NSBundle':
108 wrapper = NSBundleKnown_SummaryProvider(valobj, class_data.sys_params)
109 # [NSBundle mainBundle] does return an object that is
110 # not correctly filled out for our purposes, so we still
111 # end up having to run code in that case
112 # statistics.metric_hit('code_notrun',valobj)
113 else:
114 wrapper = NSBundleUnknown_SummaryProvider(
115 valobj, class_data.sys_params)
116 statistics.metric_hit(
117 'unknown_class',
118 valobj.GetName() +
119 " seen as " +
120 name_string)
121 return wrapper
122
123
124def NSBundle_SummaryProvider(valobj, dict):
125 logger = lldb.formatters.Logger.Logger()
126 provider = GetSummary_Impl(valobj)
127 if provider is not None:
128 if isinstance(
129 provider,
130 lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
131 return provider.message()
132 try:
133 summary = provider.url_text()
134 except:
135 summary = None
136 logger >> "got summary " + str(summary)
137 if summary is None or summary == '':
138 summary = '<variable is not NSBundle>'
139 return summary
140 return 'Summary Unavailable'
141
142
143def __lldb_init_module(debugger, dict):
144 debugger.HandleCommand(
145 "type summary add -F NSBundle.NSBundle_SummaryProvider NSBundle")