Fix build break
[chromium-blink-merge.git] / tools / gdb / gdb_chrome.py
blob0d043a5f2a620e2cb954745d09ff3ff6a7b8cb99
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
3 # found in the LICENSE file.
5 """GDB support for Chrome types.
7 Add this to your gdb by amending your ~/.gdbinit as follows:
8 python
9 import sys
10 sys.path.insert(0, "/path/to/tools/gdb/")
11 import gdb_chrome
12 end
14 This module relies on the WebKit gdb module already existing in
15 your Python path.
17 Use
18 (gdb) p /r any_variable
19 to print |any_variable| without using any printers.
20 """
22 import datetime
23 import gdb
24 import webkit
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
33 pp_set = gdb.printing.RegexpCollectionPrettyPrinter("chromium")
36 def typed_ptr(ptr):
37 """Prints a pointer along with its exact type.
39 By default, gdb would print just the address, which takes more
40 steps to interpret.
41 """
42 # Returning this as a cast expression surrounded by parentheses
43 # makes it easier to cut+paste inside of gdb.
44 return '((%s)%s)' % (ptr.dynamic_type, ptr)
47 class Printer(object):
48 def __init__(self, val):
49 self.val = val
52 class StringPrinter(Printer):
53 def display_hint(self):
54 return 'string'
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);
65 class GURLPrinter(StringPrinter):
66 def to_string(self):
67 return self.val['spec_']
68 pp_set.add_printer('GURL', '^GURL$', GURLPrinter)
71 class FilePathPrinter(StringPrinter):
72 def to_string(self):
73 return self.val['path_']['_M_dataplus']['_M_p']
74 pp_set.add_printer('FilePath', '^FilePath$', FilePathPrinter)
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)
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)
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)
97 class SmartPtrPrinter(Printer):
98 def to_string(self):
99 return '%s%s' % (self.typename, typed_ptr(self.ptr()))
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)
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)
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['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)
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)
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)
145 class TimeDeltaPrinter(object):
146 def __init__(self, val):
147 self._timedelta = datetime.timedelta(microseconds=int(val['delta_']))
149 def timedelta(self):
150 return self._timedelta
152 def to_string(self):
153 return str(self._timedelta)
154 pp_set.add_printer('base::TimeDelta', '^base::TimeDelta$', TimeDeltaPrinter)
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)
163 class TimePrinter(object):
164 def __init__(self, val):
165 timet_offset = gdb.parse_and_eval(
166 'base::Time::kTimeTToMicrosecondsOffset')
167 self._datetime = (datetime.datetime.fromtimestamp(0) +
168 datetime.timedelta(microseconds=
169 int(val['us_'] - timet_offset)))
171 def datetime(self):
172 return self._datetime
174 def to_string(self):
175 return str(self._datetime)
176 pp_set.add_printer('base::Time', '^base::Time$', TimePrinter)
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)
201 class SiteInstanceImplPrinter(object):
202 def __init__(self, val):
203 self.val = val.cast(val.dynamic_type)
205 def to_string(self):
206 return 'SiteInstanceImpl@%s for %s' % (
207 self.val.address, self.val['site_'])
209 def children(self):
210 yield ('id_', self.val['id_'])
211 yield ('has_site_', self.val['has_site_'])
212 if self.val['browsing_instance_']['ptr_']:
213 yield ('browsing_instance_', self.val['browsing_instance_']['ptr_'])
214 if self.val['process_']:
215 yield ('process_', typed_ptr(self.val['process_']))
216 if self.val['render_process_host_factory_']:
217 yield ('render_process_host_factory_',
218 self.val['render_process_host_factory_'])
219 pp_set.add_printer('content::SiteInstanceImpl', '^content::SiteInstanceImpl$',
220 SiteInstanceImplPrinter)
223 class RenderProcessHostImplPrinter(object):
224 def __init__(self, val):
225 self.val = val.cast(val.dynamic_type)
227 def to_string(self):
228 pid = ''
229 try:
230 child_process_launcher_ptr = (
231 self.val['child_process_launcher_']['impl_']['data_']['ptr'])
232 if child_process_launcher_ptr:
233 context = (child_process_launcher_ptr['context_']['ptr_'])
234 if context:
235 pid = ' PID %s' % str(context['process_']['process_'])
236 except gdb.error:
237 # The definition of the Context type may not be available.
238 # b/8242773
239 pass
240 return 'RenderProcessHostImpl@%s%s' % (self.val.address, pid)
242 def children(self):
243 yield ('id_', self.val['id_'])
244 yield ('render_widget_hosts_',
245 self.val['render_widget_hosts_']['data_'])
246 yield ('fast_shutdown_started_', self.val['fast_shutdown_started_'])
247 yield ('deleting_soon_', self.val['deleting_soon_'])
248 yield ('pending_views_', self.val['pending_views_'])
249 yield ('visible_widgets_', self.val['visible_widgets_'])
250 yield ('backgrounded_', self.val['backgrounded_'])
251 yield ('widget_helper_', self.val['widget_helper_'])
252 yield ('is_initialized_', self.val['is_initialized_'])
253 yield ('browser_context_', typed_ptr(self.val['browser_context_']))
254 yield ('sudden_termination_allowed_',
255 self.val['sudden_termination_allowed_'])
256 yield ('ignore_input_events_', self.val['ignore_input_events_'])
257 yield ('is_guest_', self.val['is_guest_'])
258 pp_set.add_printer('content::RenderProcessHostImpl',
259 '^content::RenderProcessHostImpl$',
260 RenderProcessHostImplPrinter)
263 gdb.printing.register_pretty_printer(gdb, pp_set, replace=_DEBUGGING)