Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(181)

Side by Side Diff: tools/gdb/gdb_chrome.py

Issue 12465020: Add GDB printers for several more vocabulary types in Chrome (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: unsigned short*.string() doesn't work; add back webkit dependency Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 # Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 """GDB support for Chrome types. 5 """GDB support for Chrome types.
6 6
7 Add this to your gdb by amending your ~/.gdbinit as follows: 7 Add this to your gdb by amending your ~/.gdbinit as follows:
8 python 8 python
9 import sys 9 import sys
10 sys.path.insert(0, "/path/to/tools/gdb/") 10 sys.path.insert(0, "/path/to/tools/gdb/")
11 import gdb_chrome 11 import gdb_chrome
12 end
12 13
13 This module relies on the WebKit gdb module already existing in 14 This module relies on the WebKit gdb module already existing in
14 your Python path. 15 your Python path.
16
17 Use
18 (gdb) p /r any_variable
19 to print |any_variable| without using any printers.
15 """ 20 """
16 21
22 import datetime
17 import gdb 23 import gdb
18 import webkit 24 import webkit
19 25
26 # When debugging this module, set the below variable to True, and then use
27 # (gdb) python del sys.modules['gdb_chrome']
28 # (gdb) python import gdb_chrome
29 # to reload.
30 _DEBUGGING = False
31
32
33 pp_set = gdb.printing.RegexpCollectionPrettyPrinter("chromium")
34
35
20 def typed_ptr(ptr): 36 def typed_ptr(ptr):
21 """Prints a pointer along with its exact type. 37 """Prints a pointer along with its exact type.
22 38
23 By default, gdb would print just the address, which takes more 39 By default, gdb would print just the address, which takes more
24 steps to interpret. 40 steps to interpret.
25 """ 41 """
26 # Returning this as a cast expression surrounded by parentheses 42 # Returning this as a cast expression surrounded by parentheses
27 # makes it easier to cut+paste inside of gdb. 43 # makes it easier to cut+paste inside of gdb.
28 return '((%s)%s)' % (ptr.dynamic_type, ptr) 44 return '((%s)%s)' % (ptr.dynamic_type, ptr)
29 45
30 class String16Printer(webkit.StringPrinter):
31 def to_string(self):
32 return webkit.ustring_to_string(self.val['_M_dataplus']['_M_p'])
33 46
34 class GURLPrinter(webkit.StringPrinter): 47 class Printer(object):
35 def to_string(self):
36 return self.val['spec_']
37
38 class FilePathPrinter(object):
39 def __init__(self, val): 48 def __init__(self, val):
40 self.val = val 49 self.val = val
41 50
51
52 class StringPrinter(Printer):
53 def display_hint(self):
54 return 'string'
55
56
57 class String16Printer(StringPrinter):
58 def to_string(self):
59 return webkit.ustring_to_string(self.val['_M_dataplus']['_M_p'])
60 pp_set.add_printer('string16',
61 '^string16|std::basic_string<(unsigned short|char16).*>$',
62 String16Printer);
63
64
65 class GURLPrinter(StringPrinter):
66 def to_string(self):
67 return self.val['spec_']
68 pp_set.add_printer('GURL', '^GURL$', GURLPrinter)
69
70
71 class FilePathPrinter(StringPrinter):
42 def to_string(self): 72 def to_string(self):
43 return self.val['path_']['_M_dataplus']['_M_p'] 73 return self.val['path_']['_M_dataplus']['_M_p']
74 pp_set.add_printer('FilePath', '^FilePath$', FilePathPrinter)
44 75
45 class ScopedRefPtrPrinter(object): 76
77 class SizePrinter(Printer):
78 def to_string(self):
79 return '%sx%s' % (self.val['width_'], self.val['height_'])
80 pp_set.add_printer('gfx::Size', '^gfx::(Size|SizeF|SizeBase<.*>)$', SizePrinter)
81
82
83 class PointPrinter(Printer):
84 def to_string(self):
85 return '%s,%s' % (self.val['x_'], self.val['y_'])
86 pp_set.add_printer('gfx::Point', '^gfx::(Point|PointF|PointBase<.*>)$',
87 PointPrinter)
88
89
90 class RectPrinter(Printer):
91 def to_string(self):
92 return '%s %s' % (self.val['origin_'], self.val['size_'])
93 pp_set.add_printer('gfx::Rect', '^gfx::(Rect|RectF|RectBase<.*>)$',
94 RectPrinter)
95
96
97 class SmartPtrPrinter(Printer):
98 def to_string(self):
99 return '%s%s' % (self.typename, typed_ptr(self.ptr()))
100
101
102 class ScopedRefPtrPrinter(SmartPtrPrinter):
103 typename = 'scoped_refptr'
104 def ptr(self):
105 return self.val['ptr_']
106 pp_set.add_printer('scoped_refptr', '^scoped_refptr<.*>$', ScopedRefPtrPrinter)
107
108
109 class LinkedPtrPrinter(SmartPtrPrinter):
110 typename = 'linked_ptr'
111 def ptr(self):
112 return self.val['value_']
113 pp_set.add_printer('linked_ptr', '^linked_ptr<.*>$', LinkedPtrPrinter)
114
115
116 class WeakPtrPrinter(SmartPtrPrinter):
117 typename = 'base::WeakPtr'
118 def ptr(self):
119 flag = ScopedRefPtrPrinter(self.val['ref_']['flag_']).ptr()
120 if flag and flag.dereference()['is_valid_']:
Jeffrey Yasskin 2013/03/22 00:17:29 Oh, one thing I wanted to ask: I could write this
tony 2013/03/22 16:48:43 I would probably use the implicit flag['is_valid']
121 return self.val['ptr_']
122 return gdb.Value(0).cast(self.val['ptr_'].type)
123 pp_set.add_printer('base::WeakPtr', '^base::WeakPtr<.*>$', WeakPtrPrinter)
124
125
126 class CallbackPrinter(Printer):
127 """Callbacks provide no usable information so reduce the space they take."""
128 def to_string(self):
129 return '...'
130 pp_set.add_printer('base::Callback', '^base::Callback<.*>$', CallbackPrinter)
131
132
133 class LockPrinter(Printer):
134 def to_string(self):
135 try:
136 if self.val['owned_by_thread_']:
137 return 'Locked by thread %s' % self.val['owning_thread_id_']
138 else:
139 return 'Unlocked'
140 except gdb.error:
141 return 'Unknown state'
142 pp_set.add_printer('base::Lock', '^base::Lock$', LockPrinter)
143
144
145 class TimeDeltaPrinter(object):
46 def __init__(self, val): 146 def __init__(self, val):
47 self.val = val 147 self._timedelta = datetime.timedelta(microseconds=int(val['delta_']))
148
149 def timedelta(self):
150 return self._timedelta
48 151
49 def to_string(self): 152 def to_string(self):
50 return 'scoped_refptr' + typed_ptr(self.val['ptr_']) 153 return str(self._timedelta)
154 pp_set.add_printer('base::TimeDelta', '^base::TimeDelta$', TimeDeltaPrinter)
155
156
157 class TimeTicksPrinter(TimeDeltaPrinter):
158 def __init__(self, val):
159 self._timedelta = datetime.timedelta(microseconds=int(val['ticks_']))
160 pp_set.add_printer('base::TimeTicks', '^base::TimeTicks$', TimeTicksPrinter)
161
162
163 class TimePrinter(object):
164 def __init__(self, val):
165 timet_offset = gdb.parse_and_eval(
166 'base::Time::kTimeTToMicrosecondsOffset')
tony 2013/03/22 00:05:05 Cute.
167 self._datetime = (datetime.datetime.fromtimestamp(0) +
168 datetime.timedelta(microseconds=
169 int(val['us_'] - timet_offset)))
tony 2013/03/22 00:05:05 Does this subtraction work? It looks like val['us
Jeffrey Yasskin 2013/03/22 00:17:29 Yeah, 'val' is a base::Time, and val['us_'] means
tony 2013/03/22 16:48:43 I see. Thanks for explaining!
170
171 def datetime(self):
172 return self._datetime
173
174 def to_string(self):
175 return str(self._datetime)
176 pp_set.add_printer('base::Time', '^base::Time$', TimePrinter)
177
178
179 class NotificationRegistrarPrinter(Printer):
180 def to_string(self):
181 try:
182 registrations = self.val['registered_']
183 vector_finish = registrations['_M_impl']['_M_finish']
184 vector_start = registrations['_M_impl']['_M_start']
185 if vector_start == vector_finish:
186 return 'Not watching notifications'
187 if vector_start.dereference().type.sizeof == 0:
188 # Incomplete type: b/8242773
189 return 'Watching some notifications'
190 return ('Watching %s notifications; '
191 'print %s->registered_ for details') % (
192 int(vector_finish - vector_start),
193 typed_ptr(self.val.address))
194 except gdb.error:
195 return 'NotificationRegistrar'
196 pp_set.add_printer('content::NotificationRegistrar',
197 '^content::NotificationRegistrar$',
198 NotificationRegistrarPrinter)
199
51 200
52 class SiteInstanceImplPrinter(object): 201 class SiteInstanceImplPrinter(object):
53 def __init__(self, val): 202 def __init__(self, val):
54 self.val = val.cast(val.dynamic_type) 203 self.val = val.cast(val.dynamic_type)
55 204
56 def to_string(self): 205 def to_string(self):
57 return 'SiteInstanceImpl@%s for %s' % ( 206 return 'SiteInstanceImpl@%s for %s' % (
58 self.val.address, self.val['site_']) 207 self.val.address, self.val['site_'])
59 208
60 def children(self): 209 def children(self):
61 yield ('id_', self.val['id_']) 210 yield ('id_', self.val['id_'])
62 yield ('has_site_', self.val['has_site_']) 211 yield ('has_site_', self.val['has_site_'])
63 if self.val['browsing_instance_']['ptr_']: 212 if self.val['browsing_instance_']['ptr_']:
64 yield ('browsing_instance_', self.val['browsing_instance_']['ptr_']) 213 yield ('browsing_instance_', self.val['browsing_instance_']['ptr_'])
65 if self.val['process_']: 214 if self.val['process_']:
66 yield ('process_', typed_ptr(self.val['process_'])) 215 yield ('process_', typed_ptr(self.val['process_']))
67 if self.val['render_process_host_factory_']: 216 if self.val['render_process_host_factory_']:
68 yield ('render_process_host_factory_', 217 yield ('render_process_host_factory_',
69 self.val['render_process_host_factory_']) 218 self.val['render_process_host_factory_'])
219 pp_set.add_printer('content::SiteInstanceImpl', '^content::SiteInstanceImpl$',
220 SiteInstanceImplPrinter)
221
70 222
71 class RenderProcessHostImplPrinter(object): 223 class RenderProcessHostImplPrinter(object):
72 def __init__(self, val): 224 def __init__(self, val):
73 self.val = val.cast(val.dynamic_type) 225 self.val = val.cast(val.dynamic_type)
74 226
75 def to_string(self): 227 def to_string(self):
76 pid = '' 228 pid = ''
77 child_process_launcher_ptr = ( 229 try:
78 self.val['child_process_launcher_']['impl_']['data_']['ptr']) 230 child_process_launcher_ptr = (
79 if child_process_launcher_ptr: 231 self.val['child_process_launcher_']['impl_']['data_']['ptr'])
80 context = (child_process_launcher_ptr.dereference() 232 if child_process_launcher_ptr:
81 ['context_']['ptr_']) 233 context = (child_process_launcher_ptr.dereference()
82 if context: 234 ['context_']['ptr_'])
83 pid = ' PID %s' % str(context.dereference() 235 if context:
84 ['process_']['process_']) 236 pid = ' PID %s' % str(context.dereference()
237 ['process_']['process_'])
238 except gdb.error:
239 # The definition of the Context type may not be available.
240 # b/8242773
241 pass
85 return 'RenderProcessHostImpl@%s%s' % (self.val.address, pid) 242 return 'RenderProcessHostImpl@%s%s' % (self.val.address, pid)
86 243
87 def children(self): 244 def children(self):
88 yield ('id_', self.val['id_']) 245 yield ('id_', self.val['id_'])
89 yield ('render_widget_hosts_', 246 yield ('render_widget_hosts_',
90 self.val['render_widget_hosts_']['data_']) 247 self.val['render_widget_hosts_']['data_'])
91 yield ('fast_shutdown_started_', self.val['fast_shutdown_started_']) 248 yield ('fast_shutdown_started_', self.val['fast_shutdown_started_'])
92 yield ('deleting_soon_', self.val['deleting_soon_']) 249 yield ('deleting_soon_', self.val['deleting_soon_'])
93 yield ('pending_views_', self.val['pending_views_']) 250 yield ('pending_views_', self.val['pending_views_'])
94 yield ('visible_widgets_', self.val['visible_widgets_']) 251 yield ('visible_widgets_', self.val['visible_widgets_'])
95 yield ('backgrounded_', self.val['backgrounded_']) 252 yield ('backgrounded_', self.val['backgrounded_'])
96 yield ('widget_helper_', self.val['widget_helper_']) 253 yield ('widget_helper_', self.val['widget_helper_'])
97 yield ('is_initialized_', self.val['is_initialized_']) 254 yield ('is_initialized_', self.val['is_initialized_'])
98 yield ('browser_context_', typed_ptr(self.val['browser_context_'])) 255 yield ('browser_context_', typed_ptr(self.val['browser_context_']))
99 yield ('sudden_termination_allowed_', 256 yield ('sudden_termination_allowed_',
100 self.val['sudden_termination_allowed_']) 257 self.val['sudden_termination_allowed_'])
101 yield ('ignore_input_events_', self.val['ignore_input_events_']) 258 yield ('ignore_input_events_', self.val['ignore_input_events_'])
102 yield ('is_guest_', self.val['is_guest_']) 259 yield ('is_guest_', self.val['is_guest_'])
103
104
105 pp_set = gdb.printing.RegexpCollectionPrettyPrinter("chromium")
106
107 pp_set.add_printer('FilePath', '^FilePath$', FilePathPrinter)
108 pp_set.add_printer('GURL', '^GURL$', GURLPrinter)
109 pp_set.add_printer('content::RenderProcessHostImpl', 260 pp_set.add_printer('content::RenderProcessHostImpl',
110 '^content::RenderProcessHostImpl$', 261 '^content::RenderProcessHostImpl$',
111 RenderProcessHostImplPrinter) 262 RenderProcessHostImplPrinter)
112 pp_set.add_printer('content::SiteInstanceImpl', '^content::SiteInstanceImpl$',
113 SiteInstanceImplPrinter)
114 pp_set.add_printer('scoped_refptr', '^scoped_refptr<.*>$', ScopedRefPtrPrinter)
115 pp_set.add_printer('string16', '^string16$', String16Printer);
116 263
117 gdb.printing.register_pretty_printer(gdb, pp_set) 264
265 gdb.printing.register_pretty_printer(gdb, pp_set, replace=_DEBUGGING)
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698