1 # Xmethods for libstdc++.
3 # Copyright (C) 2014-2019 Free Software Foundation, Inc.
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 3 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program. If not, see <http://www.gnu.org/licenses/>.
22 matcher_name_prefix
= 'libstdc++::'
25 return gdb
.lookup_type('bool')
27 def get_std_size_type():
28 return gdb
.lookup_type('std::size_t')
30 class LibStdCxxXMethod(gdb
.xmethod
.XMethod
):
31 def __init__(self
, name
, worker_class
):
32 gdb
.xmethod
.XMethod
.__init
__(self
, name
)
33 self
.worker_class
= worker_class
35 # Xmethods for std::array
37 class ArrayWorkerBase(gdb
.xmethod
.XMethodWorker
):
38 def __init__(self
, val_type
, size
):
39 self
._val
_type
= val_type
43 nullptr
= gdb
.parse_and_eval('(void *) 0')
44 return nullptr
.cast(self
._val
_type
.pointer()).dereference()
46 class ArraySizeWorker(ArrayWorkerBase
):
47 def __init__(self
, val_type
, size
):
48 ArrayWorkerBase
.__init
__(self
, val_type
, size
)
50 def get_arg_types(self
):
53 def get_result_type(self
, obj
):
54 return get_std_size_type()
56 def __call__(self
, obj
):
59 class ArrayEmptyWorker(ArrayWorkerBase
):
60 def __init__(self
, val_type
, size
):
61 ArrayWorkerBase
.__init
__(self
, val_type
, size
)
63 def get_arg_types(self
):
66 def get_result_type(self
, obj
):
67 return get_bool_type()
69 def __call__(self
, obj
):
70 return (int(self
._size
) == 0)
72 class ArrayFrontWorker(ArrayWorkerBase
):
73 def __init__(self
, val_type
, size
):
74 ArrayWorkerBase
.__init
__(self
, val_type
, size
)
76 def get_arg_types(self
):
79 def get_result_type(self
, obj
):
82 def __call__(self
, obj
):
83 if int(self
._size
) > 0:
84 return obj
['_M_elems'][0]
86 return self
.null_value()
88 class ArrayBackWorker(ArrayWorkerBase
):
89 def __init__(self
, val_type
, size
):
90 ArrayWorkerBase
.__init
__(self
, val_type
, size
)
92 def get_arg_types(self
):
95 def get_result_type(self
, obj
):
98 def __call__(self
, obj
):
99 if int(self
._size
) > 0:
100 return obj
['_M_elems'][self
._size
- 1]
102 return self
.null_value()
104 class ArrayAtWorker(ArrayWorkerBase
):
105 def __init__(self
, val_type
, size
):
106 ArrayWorkerBase
.__init
__(self
, val_type
, size
)
108 def get_arg_types(self
):
109 return get_std_size_type()
111 def get_result_type(self
, obj
, index
):
112 return self
._val
_type
114 def __call__(self
, obj
, index
):
115 if int(index
) >= int(self
._size
):
116 raise IndexError('Array index "%d" should not be >= %d.' %
117 ((int(index
), self
._size
)))
118 return obj
['_M_elems'][index
]
120 class ArraySubscriptWorker(ArrayWorkerBase
):
121 def __init__(self
, val_type
, size
):
122 ArrayWorkerBase
.__init
__(self
, val_type
, size
)
124 def get_arg_types(self
):
125 return get_std_size_type()
127 def get_result_type(self
, obj
, index
):
128 return self
._val
_type
130 def __call__(self
, obj
, index
):
131 if int(self
._size
) > 0:
132 return obj
['_M_elems'][index
]
134 return self
.null_value()
136 class ArrayMethodsMatcher(gdb
.xmethod
.XMethodMatcher
):
138 gdb
.xmethod
.XMethodMatcher
.__init
__(self
,
139 matcher_name_prefix
+ 'array')
140 self
._method
_dict
= {
141 'size': LibStdCxxXMethod('size', ArraySizeWorker
),
142 'empty': LibStdCxxXMethod('empty', ArrayEmptyWorker
),
143 'front': LibStdCxxXMethod('front', ArrayFrontWorker
),
144 'back': LibStdCxxXMethod('back', ArrayBackWorker
),
145 'at': LibStdCxxXMethod('at', ArrayAtWorker
),
146 'operator[]': LibStdCxxXMethod('operator[]', ArraySubscriptWorker
),
148 self
.methods
= [self
._method
_dict
[m
] for m
in self
._method
_dict
]
150 def match(self
, class_type
, method_name
):
151 if not re
.match('^std::(__\d+::)?array<.*>$', class_type
.tag
):
153 method
= self
._method
_dict
.get(method_name
)
154 if method
is None or not method
.enabled
:
157 value_type
= class_type
.template_argument(0)
158 size
= class_type
.template_argument(1)
161 return method
.worker_class(value_type
, size
)
163 # Xmethods for std::deque
165 class DequeWorkerBase(gdb
.xmethod
.XMethodWorker
):
166 def __init__(self
, val_type
):
167 self
._val
_type
= val_type
168 self
._bufsize
= 512 // val_type
.sizeof
or 1
171 first_node
= obj
['_M_impl']['_M_start']['_M_node']
172 last_node
= obj
['_M_impl']['_M_finish']['_M_node']
173 cur
= obj
['_M_impl']['_M_finish']['_M_cur']
174 first
= obj
['_M_impl']['_M_finish']['_M_first']
175 return (last_node
- first_node
) * self
._bufsize
+ (cur
- first
)
177 def index(self
, obj
, idx
):
178 first_node
= obj
['_M_impl']['_M_start']['_M_node']
179 index_node
= first_node
+ int(idx
) // self
._bufsize
180 return index_node
[0][idx
% self
._bufsize
]
182 class DequeEmptyWorker(DequeWorkerBase
):
183 def get_arg_types(self
):
186 def get_result_type(self
, obj
):
187 return get_bool_type()
189 def __call__(self
, obj
):
190 return (obj
['_M_impl']['_M_start']['_M_cur'] ==
191 obj
['_M_impl']['_M_finish']['_M_cur'])
193 class DequeSizeWorker(DequeWorkerBase
):
194 def get_arg_types(self
):
197 def get_result_type(self
, obj
):
198 return get_std_size_type()
200 def __call__(self
, obj
):
201 return self
.size(obj
)
203 class DequeFrontWorker(DequeWorkerBase
):
204 def get_arg_types(self
):
207 def get_result_type(self
, obj
):
208 return self
._val
_type
210 def __call__(self
, obj
):
211 return obj
['_M_impl']['_M_start']['_M_cur'][0]
213 class DequeBackWorker(DequeWorkerBase
):
214 def get_arg_types(self
):
217 def get_result_type(self
, obj
):
218 return self
._val
_type
220 def __call__(self
, obj
):
221 if (obj
['_M_impl']['_M_finish']['_M_cur'] ==
222 obj
['_M_impl']['_M_finish']['_M_first']):
223 prev_node
= obj
['_M_impl']['_M_finish']['_M_node'] - 1
224 return prev_node
[0][self
._bufsize
- 1]
226 return obj
['_M_impl']['_M_finish']['_M_cur'][-1]
228 class DequeSubscriptWorker(DequeWorkerBase
):
229 def get_arg_types(self
):
230 return get_std_size_type()
232 def get_result_type(self
, obj
, subscript
):
233 return self
._val
_type
235 def __call__(self
, obj
, subscript
):
236 return self
.index(obj
, subscript
)
238 class DequeAtWorker(DequeWorkerBase
):
239 def get_arg_types(self
):
240 return get_std_size_type()
242 def get_result_type(self
, obj
, index
):
243 return self
._val
_type
245 def __call__(self
, obj
, index
):
246 deque_size
= int(self
.size(obj
))
247 if int(index
) >= deque_size
:
248 raise IndexError('Deque index "%d" should not be >= %d.' %
249 (int(index
), deque_size
))
251 return self
.index(obj
, index
)
253 class DequeMethodsMatcher(gdb
.xmethod
.XMethodMatcher
):
255 gdb
.xmethod
.XMethodMatcher
.__init
__(self
,
256 matcher_name_prefix
+ 'deque')
257 self
._method
_dict
= {
258 'empty': LibStdCxxXMethod('empty', DequeEmptyWorker
),
259 'size': LibStdCxxXMethod('size', DequeSizeWorker
),
260 'front': LibStdCxxXMethod('front', DequeFrontWorker
),
261 'back': LibStdCxxXMethod('back', DequeBackWorker
),
262 'operator[]': LibStdCxxXMethod('operator[]', DequeSubscriptWorker
),
263 'at': LibStdCxxXMethod('at', DequeAtWorker
)
265 self
.methods
= [self
._method
_dict
[m
] for m
in self
._method
_dict
]
267 def match(self
, class_type
, method_name
):
268 if not re
.match('^std::(__\d+::)?deque<.*>$', class_type
.tag
):
270 method
= self
._method
_dict
.get(method_name
)
271 if method
is None or not method
.enabled
:
273 return method
.worker_class(class_type
.template_argument(0))
275 # Xmethods for std::forward_list
277 class ForwardListWorkerBase(gdb
.xmethod
.XMethodMatcher
):
278 def __init__(self
, val_type
, node_type
):
279 self
._val
_type
= val_type
280 self
._node
_type
= node_type
282 def get_arg_types(self
):
285 class ForwardListEmptyWorker(ForwardListWorkerBase
):
286 def get_result_type(self
, obj
):
287 return get_bool_type()
289 def __call__(self
, obj
):
290 return obj
['_M_impl']['_M_head']['_M_next'] == 0
292 class ForwardListFrontWorker(ForwardListWorkerBase
):
293 def get_result_type(self
, obj
):
294 return self
._val
_type
296 def __call__(self
, obj
):
297 node
= obj
['_M_impl']['_M_head']['_M_next'].cast(self
._node
_type
)
298 val_address
= node
['_M_storage']['_M_storage'].address
299 return val_address
.cast(self
._val
_type
.pointer()).dereference()
301 class ForwardListMethodsMatcher(gdb
.xmethod
.XMethodMatcher
):
303 matcher_name
= matcher_name_prefix
+ 'forward_list'
304 gdb
.xmethod
.XMethodMatcher
.__init
__(self
, matcher_name
)
305 self
._method
_dict
= {
306 'empty': LibStdCxxXMethod('empty', ForwardListEmptyWorker
),
307 'front': LibStdCxxXMethod('front', ForwardListFrontWorker
)
309 self
.methods
= [self
._method
_dict
[m
] for m
in self
._method
_dict
]
311 def match(self
, class_type
, method_name
):
312 if not re
.match('^std::(__\d+::)?forward_list<.*>$', class_type
.tag
):
314 method
= self
._method
_dict
.get(method_name
)
315 if method
is None or not method
.enabled
:
317 val_type
= class_type
.template_argument(0)
318 node_type
= gdb
.lookup_type(str(class_type
) + '::_Node').pointer()
319 return method
.worker_class(val_type
, node_type
)
321 # Xmethods for std::list
323 class ListWorkerBase(gdb
.xmethod
.XMethodWorker
):
324 def __init__(self
, val_type
, node_type
):
325 self
._val
_type
= val_type
326 self
._node
_type
= node_type
328 def get_arg_types(self
):
331 def get_value_from_node(self
, node
):
332 node
= node
.dereference()
333 if node
.type.fields()[1].name
== '_M_data':
334 # C++03 implementation, node contains the value as a member
335 return node
['_M_data']
336 # C++11 implementation, node stores value in __aligned_membuf
337 addr
= node
['_M_storage'].address
338 return addr
.cast(self
._val
_type
.pointer()).dereference()
340 class ListEmptyWorker(ListWorkerBase
):
341 def get_result_type(self
, obj
):
342 return get_bool_type()
344 def __call__(self
, obj
):
345 base_node
= obj
['_M_impl']['_M_node']
346 if base_node
['_M_next'] == base_node
.address
:
351 class ListSizeWorker(ListWorkerBase
):
352 def get_result_type(self
, obj
):
353 return get_std_size_type()
355 def __call__(self
, obj
):
356 begin_node
= obj
['_M_impl']['_M_node']['_M_next']
357 end_node
= obj
['_M_impl']['_M_node'].address
359 while begin_node
!= end_node
:
360 begin_node
= begin_node
['_M_next']
364 class ListFrontWorker(ListWorkerBase
):
365 def get_result_type(self
, obj
):
366 return self
._val
_type
368 def __call__(self
, obj
):
369 node
= obj
['_M_impl']['_M_node']['_M_next'].cast(self
._node
_type
)
370 return self
.get_value_from_node(node
)
372 class ListBackWorker(ListWorkerBase
):
373 def get_result_type(self
, obj
):
374 return self
._val
_type
376 def __call__(self
, obj
):
377 prev_node
= obj
['_M_impl']['_M_node']['_M_prev'].cast(self
._node
_type
)
378 return self
.get_value_from_node(prev_node
)
380 class ListMethodsMatcher(gdb
.xmethod
.XMethodMatcher
):
382 gdb
.xmethod
.XMethodMatcher
.__init
__(self
,
383 matcher_name_prefix
+ 'list')
384 self
._method
_dict
= {
385 'empty': LibStdCxxXMethod('empty', ListEmptyWorker
),
386 'size': LibStdCxxXMethod('size', ListSizeWorker
),
387 'front': LibStdCxxXMethod('front', ListFrontWorker
),
388 'back': LibStdCxxXMethod('back', ListBackWorker
)
390 self
.methods
= [self
._method
_dict
[m
] for m
in self
._method
_dict
]
392 def match(self
, class_type
, method_name
):
393 if not re
.match('^std::(__\d+::)?(__cxx11::)?list<.*>$', class_type
.tag
):
395 method
= self
._method
_dict
.get(method_name
)
396 if method
is None or not method
.enabled
:
398 val_type
= class_type
.template_argument(0)
399 node_type
= gdb
.lookup_type(str(class_type
) + '::_Node').pointer()
400 return method
.worker_class(val_type
, node_type
)
402 # Xmethods for std::vector
404 class VectorWorkerBase(gdb
.xmethod
.XMethodWorker
):
405 def __init__(self
, val_type
):
406 self
._val
_type
= val_type
409 if self
._val
_type
.code
== gdb
.TYPE_CODE_BOOL
:
410 start
= obj
['_M_impl']['_M_start']['_M_p']
411 finish
= obj
['_M_impl']['_M_finish']['_M_p']
412 finish_offset
= obj
['_M_impl']['_M_finish']['_M_offset']
413 bit_size
= start
.dereference().type.sizeof
* 8
414 return (finish
- start
) * bit_size
+ finish_offset
416 return obj
['_M_impl']['_M_finish'] - obj
['_M_impl']['_M_start']
418 def get(self
, obj
, index
):
419 if self
._val
_type
.code
== gdb
.TYPE_CODE_BOOL
:
420 start
= obj
['_M_impl']['_M_start']['_M_p']
421 bit_size
= start
.dereference().type.sizeof
* 8
422 valp
= start
+ index
// bit_size
423 offset
= index
% bit_size
424 return (valp
.dereference() & (1 << offset
)) > 0
426 return obj
['_M_impl']['_M_start'][index
]
428 class VectorEmptyWorker(VectorWorkerBase
):
429 def get_arg_types(self
):
432 def get_result_type(self
, obj
):
433 return get_bool_type()
435 def __call__(self
, obj
):
436 return int(self
.size(obj
)) == 0
438 class VectorSizeWorker(VectorWorkerBase
):
439 def get_arg_types(self
):
442 def get_result_type(self
, obj
):
443 return get_std_size_type()
445 def __call__(self
, obj
):
446 return self
.size(obj
)
448 class VectorFrontWorker(VectorWorkerBase
):
449 def get_arg_types(self
):
452 def get_result_type(self
, obj
):
453 return self
._val
_type
455 def __call__(self
, obj
):
456 return self
.get(obj
, 0)
458 class VectorBackWorker(VectorWorkerBase
):
459 def get_arg_types(self
):
462 def get_result_type(self
, obj
):
463 return self
._val
_type
465 def __call__(self
, obj
):
466 return self
.get(obj
, int(self
.size(obj
)) - 1)
468 class VectorAtWorker(VectorWorkerBase
):
469 def get_arg_types(self
):
470 return get_std_size_type()
472 def get_result_type(self
, obj
, index
):
473 return self
._val
_type
475 def __call__(self
, obj
, index
):
476 size
= int(self
.size(obj
))
477 if int(index
) >= size
:
478 raise IndexError('Vector index "%d" should not be >= %d.' %
479 ((int(index
), size
)))
480 return self
.get(obj
, int(index
))
482 class VectorSubscriptWorker(VectorWorkerBase
):
483 def get_arg_types(self
):
484 return get_std_size_type()
486 def get_result_type(self
, obj
, subscript
):
487 return self
._val
_type
489 def __call__(self
, obj
, subscript
):
490 return self
.get(obj
, int(subscript
))
492 class VectorMethodsMatcher(gdb
.xmethod
.XMethodMatcher
):
494 gdb
.xmethod
.XMethodMatcher
.__init
__(self
,
495 matcher_name_prefix
+ 'vector')
496 self
._method
_dict
= {
497 'size': LibStdCxxXMethod('size', VectorSizeWorker
),
498 'empty': LibStdCxxXMethod('empty', VectorEmptyWorker
),
499 'front': LibStdCxxXMethod('front', VectorFrontWorker
),
500 'back': LibStdCxxXMethod('back', VectorBackWorker
),
501 'at': LibStdCxxXMethod('at', VectorAtWorker
),
502 'operator[]': LibStdCxxXMethod('operator[]',
503 VectorSubscriptWorker
),
505 self
.methods
= [self
._method
_dict
[m
] for m
in self
._method
_dict
]
507 def match(self
, class_type
, method_name
):
508 if not re
.match('^std::(__\d+::)?vector<.*>$', class_type
.tag
):
510 method
= self
._method
_dict
.get(method_name
)
511 if method
is None or not method
.enabled
:
513 return method
.worker_class(class_type
.template_argument(0))
515 # Xmethods for associative containers
517 class AssociativeContainerWorkerBase(gdb
.xmethod
.XMethodWorker
):
518 def __init__(self
, unordered
):
519 self
._unordered
= unordered
521 def node_count(self
, obj
):
523 return obj
['_M_h']['_M_element_count']
525 return obj
['_M_t']['_M_impl']['_M_node_count']
527 def get_arg_types(self
):
530 class AssociativeContainerEmptyWorker(AssociativeContainerWorkerBase
):
531 def get_result_type(self
, obj
):
532 return get_bool_type()
534 def __call__(self
, obj
):
535 return int(self
.node_count(obj
)) == 0
537 class AssociativeContainerSizeWorker(AssociativeContainerWorkerBase
):
538 def get_result_type(self
, obj
):
539 return get_std_size_type()
541 def __call__(self
, obj
):
542 return self
.node_count(obj
)
544 class AssociativeContainerMethodsMatcher(gdb
.xmethod
.XMethodMatcher
):
545 def __init__(self
, name
):
546 gdb
.xmethod
.XMethodMatcher
.__init
__(self
,
547 matcher_name_prefix
+ name
)
549 self
._method
_dict
= {
550 'size': LibStdCxxXMethod('size', AssociativeContainerSizeWorker
),
551 'empty': LibStdCxxXMethod('empty',
552 AssociativeContainerEmptyWorker
),
554 self
.methods
= [self
._method
_dict
[m
] for m
in self
._method
_dict
]
556 def match(self
, class_type
, method_name
):
557 if not re
.match('^std::(__\d+::)?%s<.*>$' % self
._name
, class_type
.tag
):
559 method
= self
._method
_dict
.get(method_name
)
560 if method
is None or not method
.enabled
:
562 unordered
= 'unordered' in self
._name
563 return method
.worker_class(unordered
)
565 # Xmethods for std::unique_ptr
567 class UniquePtrGetWorker(gdb
.xmethod
.XMethodWorker
):
568 "Implements std::unique_ptr<T>::get() and std::unique_ptr<T>::operator->()"
570 def __init__(self
, elem_type
):
571 self
._is
_array
= elem_type
.code
== gdb
.TYPE_CODE_ARRAY
573 self
._elem
_type
= elem_type
.target()
575 self
._elem
_type
= elem_type
577 def get_arg_types(self
):
580 def get_result_type(self
, obj
):
581 return self
._elem
_type
.pointer()
583 def _supports(self
, method_name
):
584 "operator-> is not supported for unique_ptr<T[]>"
585 return method_name
== 'get' or not self
._is
_array
587 def __call__(self
, obj
):
588 impl_type
= obj
.dereference().type.fields()[0].type.tag
589 # Check for new implementations first:
590 if re
.match('^std::(__\d+::)?__uniq_ptr_(data|impl)<.*>$', impl_type
):
591 tuple_member
= obj
['_M_t']['_M_t']
592 elif re
.match('^std::(__\d+::)?tuple<.*>$', impl_type
):
593 tuple_member
= obj
['_M_t']
596 tuple_impl_type
= tuple_member
.type.fields()[0].type # _Tuple_impl
597 tuple_head_type
= tuple_impl_type
.fields()[1].type # _Head_base
598 head_field
= tuple_head_type
.fields()[0]
599 if head_field
.name
== '_M_head_impl':
600 return tuple_member
['_M_head_impl']
601 elif head_field
.is_base_class
:
602 return tuple_member
.cast(head_field
.type)
606 class UniquePtrDerefWorker(UniquePtrGetWorker
):
607 "Implements std::unique_ptr<T>::operator*()"
609 def __init__(self
, elem_type
):
610 UniquePtrGetWorker
.__init
__(self
, elem_type
)
612 def get_result_type(self
, obj
):
613 return self
._elem
_type
615 def _supports(self
, method_name
):
616 "operator* is not supported for unique_ptr<T[]>"
617 return not self
._is
_array
619 def __call__(self
, obj
):
620 return UniquePtrGetWorker
.__call
__(self
, obj
).dereference()
622 class UniquePtrSubscriptWorker(UniquePtrGetWorker
):
623 "Implements std::unique_ptr<T>::operator[](size_t)"
625 def __init__(self
, elem_type
):
626 UniquePtrGetWorker
.__init
__(self
, elem_type
)
628 def get_arg_types(self
):
629 return get_std_size_type()
631 def get_result_type(self
, obj
, index
):
632 return self
._elem
_type
634 def _supports(self
, method_name
):
635 "operator[] is only supported for unique_ptr<T[]>"
636 return self
._is
_array
638 def __call__(self
, obj
, index
):
639 return UniquePtrGetWorker
.__call
__(self
, obj
)[index
]
641 class UniquePtrMethodsMatcher(gdb
.xmethod
.XMethodMatcher
):
643 gdb
.xmethod
.XMethodMatcher
.__init
__(self
,
644 matcher_name_prefix
+ 'unique_ptr')
645 self
._method
_dict
= {
646 'get': LibStdCxxXMethod('get', UniquePtrGetWorker
),
647 'operator->': LibStdCxxXMethod('operator->', UniquePtrGetWorker
),
648 'operator*': LibStdCxxXMethod('operator*', UniquePtrDerefWorker
),
649 'operator[]': LibStdCxxXMethod('operator[]', UniquePtrSubscriptWorker
),
651 self
.methods
= [self
._method
_dict
[m
] for m
in self
._method
_dict
]
653 def match(self
, class_type
, method_name
):
654 if not re
.match('^std::(__\d+::)?unique_ptr<.*>$', class_type
.tag
):
656 method
= self
._method
_dict
.get(method_name
)
657 if method
is None or not method
.enabled
:
659 worker
= method
.worker_class(class_type
.template_argument(0))
660 if worker
._supports
(method_name
):
664 # Xmethods for std::shared_ptr
666 class SharedPtrGetWorker(gdb
.xmethod
.XMethodWorker
):
667 "Implements std::shared_ptr<T>::get() and std::shared_ptr<T>::operator->()"
669 def __init__(self
, elem_type
):
670 self
._is
_array
= elem_type
.code
== gdb
.TYPE_CODE_ARRAY
672 self
._elem
_type
= elem_type
.target()
674 self
._elem
_type
= elem_type
676 def get_arg_types(self
):
679 def get_result_type(self
, obj
):
680 return self
._elem
_type
.pointer()
682 def _supports(self
, method_name
):
683 "operator-> is not supported for shared_ptr<T[]>"
684 return method_name
== 'get' or not self
._is
_array
686 def __call__(self
, obj
):
689 class SharedPtrDerefWorker(SharedPtrGetWorker
):
690 "Implements std::shared_ptr<T>::operator*()"
692 def __init__(self
, elem_type
):
693 SharedPtrGetWorker
.__init
__(self
, elem_type
)
695 def get_result_type(self
, obj
):
696 return self
._elem
_type
698 def _supports(self
, method_name
):
699 "operator* is not supported for shared_ptr<T[]>"
700 return not self
._is
_array
702 def __call__(self
, obj
):
703 return SharedPtrGetWorker
.__call
__(self
, obj
).dereference()
705 class SharedPtrSubscriptWorker(SharedPtrGetWorker
):
706 "Implements std::shared_ptr<T>::operator[](size_t)"
708 def __init__(self
, elem_type
):
709 SharedPtrGetWorker
.__init
__(self
, elem_type
)
711 def get_arg_types(self
):
712 return get_std_size_type()
714 def get_result_type(self
, obj
, index
):
715 return self
._elem
_type
717 def _supports(self
, method_name
):
718 "operator[] is only supported for shared_ptr<T[]>"
719 return self
._is
_array
721 def __call__(self
, obj
, index
):
722 # Check bounds if _elem_type is an array of known bound
723 m
= re
.match('.*\[(\d+)]$', str(self
._elem
_type
))
724 if m
and index
>= int(m
.group(1)):
725 raise IndexError('shared_ptr<%s> index "%d" should not be >= %d.' %
726 (self
._elem
_type
, int(index
), int(m
.group(1))))
727 return SharedPtrGetWorker
.__call
__(self
, obj
)[index
]
729 class SharedPtrUseCountWorker(gdb
.xmethod
.XMethodWorker
):
730 "Implements std::shared_ptr<T>::use_count()"
732 def __init__(self
, elem_type
):
733 SharedPtrUseCountWorker
.__init
__(self
, elem_type
)
735 def get_arg_types(self
):
738 def get_result_type(self
, obj
):
739 return gdb
.lookup_type('long')
741 def __call__(self
, obj
):
742 refcounts
= obj
['_M_refcount']['_M_pi']
743 return refcounts
['_M_use_count'] if refcounts
else 0
745 class SharedPtrUniqueWorker(SharedPtrUseCountWorker
):
746 "Implements std::shared_ptr<T>::unique()"
748 def __init__(self
, elem_type
):
749 SharedPtrUseCountWorker
.__init
__(self
, elem_type
)
751 def get_result_type(self
, obj
):
752 return gdb
.lookup_type('bool')
754 def __call__(self
, obj
):
755 return SharedPtrUseCountWorker
.__call
__(self
, obj
) == 1
757 class SharedPtrMethodsMatcher(gdb
.xmethod
.XMethodMatcher
):
759 gdb
.xmethod
.XMethodMatcher
.__init
__(self
,
760 matcher_name_prefix
+ 'shared_ptr')
761 self
._method
_dict
= {
762 'get': LibStdCxxXMethod('get', SharedPtrGetWorker
),
763 'operator->': LibStdCxxXMethod('operator->', SharedPtrGetWorker
),
764 'operator*': LibStdCxxXMethod('operator*', SharedPtrDerefWorker
),
765 'operator[]': LibStdCxxXMethod('operator[]', SharedPtrSubscriptWorker
),
766 'use_count': LibStdCxxXMethod('use_count', SharedPtrUseCountWorker
),
767 'unique': LibStdCxxXMethod('unique', SharedPtrUniqueWorker
),
769 self
.methods
= [self
._method
_dict
[m
] for m
in self
._method
_dict
]
771 def match(self
, class_type
, method_name
):
772 if not re
.match('^std::(__\d+::)?shared_ptr<.*>$', class_type
.tag
):
774 method
= self
._method
_dict
.get(method_name
)
775 if method
is None or not method
.enabled
:
777 worker
= method
.worker_class(class_type
.template_argument(0))
778 if worker
._supports
(method_name
):
782 def register_libstdcxx_xmethods(locus
):
783 gdb
.xmethod
.register_xmethod_matcher(locus
, ArrayMethodsMatcher())
784 gdb
.xmethod
.register_xmethod_matcher(locus
, ForwardListMethodsMatcher())
785 gdb
.xmethod
.register_xmethod_matcher(locus
, DequeMethodsMatcher())
786 gdb
.xmethod
.register_xmethod_matcher(locus
, ListMethodsMatcher())
787 gdb
.xmethod
.register_xmethod_matcher(locus
, VectorMethodsMatcher())
788 gdb
.xmethod
.register_xmethod_matcher(
789 locus
, AssociativeContainerMethodsMatcher('set'))
790 gdb
.xmethod
.register_xmethod_matcher(
791 locus
, AssociativeContainerMethodsMatcher('map'))
792 gdb
.xmethod
.register_xmethod_matcher(
793 locus
, AssociativeContainerMethodsMatcher('multiset'))
794 gdb
.xmethod
.register_xmethod_matcher(
795 locus
, AssociativeContainerMethodsMatcher('multimap'))
796 gdb
.xmethod
.register_xmethod_matcher(
797 locus
, AssociativeContainerMethodsMatcher('unordered_set'))
798 gdb
.xmethod
.register_xmethod_matcher(
799 locus
, AssociativeContainerMethodsMatcher('unordered_map'))
800 gdb
.xmethod
.register_xmethod_matcher(
801 locus
, AssociativeContainerMethodsMatcher('unordered_multiset'))
802 gdb
.xmethod
.register_xmethod_matcher(
803 locus
, AssociativeContainerMethodsMatcher('unordered_multimap'))
804 gdb
.xmethod
.register_xmethod_matcher(locus
, UniquePtrMethodsMatcher())
805 gdb
.xmethod
.register_xmethod_matcher(locus
, SharedPtrMethodsMatcher())