]>
Commit | Line | Data |
---|---|---|
4027b015 | 1 | # Xmethods for libstdc++. |
e9e08827 | 2 | |
5624e564 | 3 | # Copyright (C) 2014-2015 Free Software Foundation, Inc. |
e9e08827 SCR |
4 | |
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. | |
9 | # | |
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. | |
14 | # | |
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/>. | |
17 | ||
18 | import gdb | |
19 | import gdb.xmethod | |
20 | import re | |
21 | ||
22 | matcher_name_prefix = 'libstdc++::' | |
23 | ||
4027b015 SCR |
24 | class LibStdCxxXMethod(gdb.xmethod.XMethod): |
25 | def __init__(self, name, worker_class): | |
26 | gdb.xmethod.XMethod.__init__(self, name) | |
27 | self.worker_class = worker_class | |
28 | ||
29 | # Xmethods for std::array | |
30 | ||
31 | class ArrayWorkerBase(gdb.xmethod.XMethodWorker): | |
32 | def __init__(self, valtype, size): | |
33 | self._valtype = valtype | |
34 | self._size = size | |
35 | ||
36 | def null_value(self): | |
37 | nullptr = gdb.parse_and_eval('(void *) 0') | |
38 | return nullptr.cast(self._valtype.pointer()).dereference() | |
39 | ||
40 | class ArraySizeWorker(ArrayWorkerBase): | |
41 | def __init__(self, valtype, size): | |
42 | ArrayWorkerBase.__init__(self, valtype, size) | |
43 | ||
44 | def get_arg_types(self): | |
45 | return None | |
46 | ||
47 | def __call__(self, obj): | |
48 | return self._size | |
49 | ||
50 | class ArrayEmptyWorker(ArrayWorkerBase): | |
51 | def __init__(self, valtype, size): | |
52 | ArrayWorkerBase.__init__(self, valtype, size) | |
53 | ||
54 | def get_arg_types(self): | |
55 | return None | |
56 | ||
57 | def __call__(self, obj): | |
58 | return (int(self._size) == 0) | |
59 | ||
60 | class ArrayFrontWorker(ArrayWorkerBase): | |
61 | def __init__(self, valtype, size): | |
62 | ArrayWorkerBase.__init__(self, valtype, size) | |
63 | ||
64 | def get_arg_types(self): | |
65 | return None | |
66 | ||
67 | def __call__(self, obj): | |
68 | if int(self._size) > 0: | |
69 | return obj['_M_elems'][0] | |
70 | else: | |
71 | return self.null_value() | |
72 | ||
73 | class ArrayBackWorker(ArrayWorkerBase): | |
74 | def __init__(self, valtype, size): | |
75 | ArrayWorkerBase.__init__(self, valtype, size) | |
76 | ||
77 | def get_arg_types(self): | |
78 | return None | |
79 | ||
80 | def __call__(self, obj): | |
81 | if int(self._size) > 0: | |
82 | return obj['_M_elems'][self._size - 1] | |
83 | else: | |
84 | return self.null_value() | |
85 | ||
86 | class ArrayAtWorker(ArrayWorkerBase): | |
87 | def __init__(self, valtype, size): | |
88 | ArrayWorkerBase.__init__(self, valtype, size) | |
89 | ||
90 | def get_arg_types(self): | |
91 | return gdb.lookup_type('std::size_t') | |
92 | ||
93 | def __call__(self, obj, index): | |
94 | if int(index) >= int(self._size): | |
95 | raise IndexError('Array index "%d" should not be >= %d.' % | |
96 | ((int(index), self._size))) | |
97 | return obj['_M_elems'][index] | |
98 | ||
99 | class ArraySubscriptWorker(ArrayWorkerBase): | |
100 | def __init__(self, valtype, size): | |
101 | ArrayWorkerBase.__init__(self, valtype, size) | |
102 | ||
103 | def get_arg_types(self): | |
104 | return gdb.lookup_type('std::size_t') | |
105 | ||
106 | def __call__(self, obj, index): | |
107 | if int(self._size) > 0: | |
108 | return obj['_M_elems'][index] | |
109 | else: | |
110 | return self.null_value() | |
e9e08827 | 111 | |
4027b015 | 112 | class ArrayMethodsMatcher(gdb.xmethod.XMethodMatcher): |
e9e08827 | 113 | def __init__(self): |
4027b015 SCR |
114 | gdb.xmethod.XMethodMatcher.__init__(self, |
115 | matcher_name_prefix + 'array') | |
116 | self._method_dict = { | |
117 | 'size': LibStdCxxXMethod('size', ArraySizeWorker), | |
118 | 'empty': LibStdCxxXMethod('empty', ArrayEmptyWorker), | |
119 | 'front': LibStdCxxXMethod('front', ArrayFrontWorker), | |
120 | 'back': LibStdCxxXMethod('back', ArrayBackWorker), | |
121 | 'at': LibStdCxxXMethod('at', ArrayAtWorker), | |
122 | 'operator[]': LibStdCxxXMethod('operator[]', ArraySubscriptWorker), | |
123 | } | |
124 | self.methods = [self._method_dict[m] for m in self._method_dict] | |
125 | ||
126 | def match(self, class_type, method_name): | |
127 | if not re.match('^std::array<.*>$', class_type.tag): | |
128 | return None | |
129 | method = self._method_dict.get(method_name) | |
130 | if method is None or not method.enabled: | |
131 | return None | |
132 | try: | |
133 | value_type = class_type.template_argument(0) | |
134 | size = class_type.template_argument(1) | |
135 | except: | |
136 | return None | |
137 | return method.worker_class(value_type, size) | |
138 | ||
139 | # Xmethods for std::deque | |
140 | ||
141 | class DequeWorkerBase(gdb.xmethod.XMethodWorker): | |
142 | def __init__(self, elemtype): | |
143 | self._bufsize = (512 / elemtype.sizeof) or 1 | |
144 | ||
145 | def size(self, obj): | |
146 | first_node = obj['_M_impl']['_M_start']['_M_node'] | |
147 | last_node = obj['_M_impl']['_M_finish']['_M_node'] | |
148 | cur = obj['_M_impl']['_M_finish']['_M_cur'] | |
149 | first = obj['_M_impl']['_M_finish']['_M_first'] | |
150 | return (last_node - first_node) * self._bufsize + (cur - first) | |
151 | ||
152 | def index(self, obj, index): | |
153 | first_node = obj['_M_impl']['_M_start']['_M_node'] | |
154 | index_node = first_node + index / self._bufsize | |
155 | return index_node[0][index % self._bufsize] | |
156 | ||
157 | class DequeEmptyWorker(DequeWorkerBase): | |
158 | def get_arg_types(self): | |
159 | return None | |
160 | ||
161 | def __call__(self, obj): | |
162 | return (obj['_M_impl']['_M_start']['_M_cur'] == | |
163 | obj['_M_impl']['_M_finish']['_M_cur']) | |
164 | ||
165 | class DequeSizeWorker(DequeWorkerBase): | |
166 | def get_arg_types(self): | |
167 | return None | |
168 | ||
169 | def __call__(self, obj): | |
170 | return self.size(obj) | |
171 | ||
172 | class DequeFrontWorker(DequeWorkerBase): | |
173 | def get_arg_types(self): | |
174 | return None | |
175 | ||
176 | def __call__(self, obj): | |
177 | return obj['_M_impl']['_M_start']['_M_cur'][0] | |
178 | ||
179 | class DequeBackWorker(DequeWorkerBase): | |
180 | def get_arg_types(self): | |
181 | return None | |
182 | ||
183 | def __call__(self, obj): | |
184 | if (obj['_M_impl']['_M_finish']['_M_cur'] == | |
185 | obj['_M_impl']['_M_finish']['_M_first']): | |
186 | prev_node = obj['_M_impl']['_M_finish']['_M_node'] - 1 | |
187 | return prev_node[0][self._bufsize - 1] | |
188 | else: | |
189 | return obj['_M_impl']['_M_finish']['_M_cur'][-1] | |
190 | ||
191 | class DequeSubscriptWorker(DequeWorkerBase): | |
192 | def get_arg_types(self): | |
193 | return gdb.lookup_type('std::size_t') | |
194 | ||
195 | def __call__(self, obj, subscript): | |
196 | return self.index(obj, subscript) | |
197 | ||
198 | class DequeAtWorker(DequeWorkerBase): | |
199 | def get_arg_types(self): | |
200 | return gdb.lookup_type('std::size_t') | |
201 | ||
202 | def __call__(self, obj, index): | |
203 | deque_size = int(self.size(obj)) | |
204 | if int(index) >= deque_size: | |
205 | raise IndexError('Deque index "%d" should not be >= %d.' % | |
206 | (int(index), deque_size)) | |
207 | else: | |
208 | return self.index(obj, index) | |
209 | ||
210 | class DequeMethodsMatcher(gdb.xmethod.XMethodMatcher): | |
211 | def __init__(self): | |
212 | gdb.xmethod.XMethodMatcher.__init__(self, | |
213 | matcher_name_prefix + 'deque') | |
214 | self._method_dict = { | |
215 | 'empty': LibStdCxxXMethod('empty', DequeEmptyWorker), | |
216 | 'size': LibStdCxxXMethod('size', DequeSizeWorker), | |
217 | 'front': LibStdCxxXMethod('front', DequeFrontWorker), | |
218 | 'back': LibStdCxxXMethod('back', DequeBackWorker), | |
219 | 'operator[]': LibStdCxxXMethod('operator[]', DequeSubscriptWorker), | |
220 | 'at': LibStdCxxXMethod('at', DequeAtWorker) | |
221 | } | |
222 | self.methods = [self._method_dict[m] for m in self._method_dict] | |
223 | ||
224 | def match(self, class_type, method_name): | |
225 | if not re.match('^std::deque<.*>$', class_type.tag): | |
226 | return None | |
227 | method = self._method_dict.get(method_name) | |
228 | if method is None or not method.enabled: | |
229 | return None | |
230 | return method.worker_class(class_type.template_argument(0)) | |
231 | ||
232 | # Xmethods for std::forward_list | |
233 | ||
234 | class ForwardListWorkerBase(gdb.xmethod.XMethodMatcher): | |
235 | def __init__(self, elem_type, node_type): | |
236 | self._elem_type = elem_type | |
237 | self._node_type = node_type | |
e9e08827 SCR |
238 | |
239 | def get_arg_types(self): | |
240 | return None | |
241 | ||
4027b015 SCR |
242 | class ForwardListEmptyWorker(ForwardListWorkerBase): |
243 | def __call__(self, obj): | |
244 | return obj['_M_impl']['_M_head']['_M_next'] == 0 | |
245 | ||
246 | class ForwardListFrontWorker(ForwardListWorkerBase): | |
e9e08827 | 247 | def __call__(self, obj): |
4027b015 SCR |
248 | node = obj['_M_impl']['_M_head']['_M_next'].cast(self._node_type) |
249 | elem_address = node['_M_storage']['_M_storage'].address | |
250 | return elem_address.cast(self._elem_type.pointer()).dereference() | |
e9e08827 | 251 | |
4027b015 | 252 | class ForwardListMethodsMatcher(gdb.xmethod.XMethodMatcher): |
e9e08827 | 253 | def __init__(self): |
4027b015 SCR |
254 | matcher_name = matcher_name_prefix + 'forward_list' |
255 | gdb.xmethod.XMethodMatcher.__init__(self, matcher_name) | |
256 | self._method_dict = { | |
257 | 'empty': LibStdCxxXMethod('empty', ForwardListEmptyWorker), | |
258 | 'front': LibStdCxxXMethod('front', ForwardListFrontWorker) | |
259 | } | |
260 | self.methods = [self._method_dict[m] for m in self._method_dict] | |
261 | ||
262 | def match(self, class_type, method_name): | |
263 | if not re.match('^std::forward_list<.*>$', class_type.tag): | |
264 | return None | |
265 | method = self._method_dict.get(method_name) | |
266 | if method is None or not method.enabled: | |
267 | return None | |
268 | elem_type = class_type.template_argument(0) | |
269 | node_type = gdb.lookup_type(str(class_type) + '::_Node').pointer() | |
270 | return method.worker_class(elem_type, node_type) | |
271 | ||
272 | # Xmethods for std::list | |
273 | ||
274 | class ListWorkerBase(gdb.xmethod.XMethodWorker): | |
275 | def __init__(self, node_type): | |
276 | self._node_type = node_type | |
277 | ||
278 | def get_arg_types(self): | |
279 | return None | |
280 | ||
281 | class ListEmptyWorker(ListWorkerBase): | |
282 | def __call__(self, obj): | |
283 | base_node = obj['_M_impl']['_M_node'] | |
284 | if base_node['_M_next'] == base_node.address: | |
285 | return True | |
286 | else: | |
287 | return False | |
288 | ||
289 | class ListSizeWorker(ListWorkerBase): | |
290 | def __call__(self, obj): | |
291 | begin_node = obj['_M_impl']['_M_node']['_M_next'] | |
292 | end_node = obj['_M_impl']['_M_node'].address | |
293 | size = 0 | |
294 | while begin_node != end_node: | |
295 | begin_node = begin_node['_M_next'] | |
296 | size += 1 | |
297 | return size | |
298 | ||
299 | class ListFrontWorker(ListWorkerBase): | |
300 | def __call__(self, obj): | |
301 | node = obj['_M_impl']['_M_node']['_M_next'].cast(self._node_type) | |
302 | return node['_M_data'] | |
303 | ||
304 | class ListBackWorker(ListWorkerBase): | |
305 | def __call__(self, obj): | |
306 | prev_node = obj['_M_impl']['_M_node']['_M_prev'].cast(self._node_type) | |
307 | return prev_node['_M_data'] | |
308 | ||
309 | class ListMethodsMatcher(gdb.xmethod.XMethodMatcher): | |
310 | def __init__(self): | |
311 | gdb.xmethod.XMethodMatcher.__init__(self, | |
312 | matcher_name_prefix + 'list') | |
313 | self._method_dict = { | |
314 | 'empty': LibStdCxxXMethod('empty', ListEmptyWorker), | |
315 | 'size': LibStdCxxXMethod('size', ListSizeWorker), | |
316 | 'front': LibStdCxxXMethod('front', ListFrontWorker), | |
317 | 'back': LibStdCxxXMethod('back', ListBackWorker) | |
318 | } | |
319 | self.methods = [self._method_dict[m] for m in self._method_dict] | |
320 | ||
321 | def match(self, class_type, method_name): | |
322 | if not re.match('^std::list<.*>$', class_type.tag): | |
323 | return None | |
324 | method = self._method_dict.get(method_name) | |
325 | if method is None or not method.enabled: | |
326 | return None | |
327 | node_type = gdb.lookup_type(str(class_type) + '::_Node').pointer() | |
328 | return method.worker_class(node_type) | |
329 | ||
330 | # Xmethods for std::vector | |
331 | ||
332 | class VectorWorkerBase(gdb.xmethod.XMethodWorker): | |
333 | def __init__(self, elemtype): | |
334 | self._elemtype = elemtype | |
335 | ||
336 | def size(self, obj): | |
337 | if self._elemtype.code == gdb.TYPE_CODE_BOOL: | |
338 | start = obj['_M_impl']['_M_start']['_M_p'] | |
339 | finish = obj['_M_impl']['_M_finish']['_M_p'] | |
340 | finish_offset = obj['_M_impl']['_M_finish']['_M_offset'] | |
341 | bit_size = start.dereference().type.sizeof * 8 | |
342 | return (finish - start) * bit_size + finish_offset | |
343 | else: | |
344 | return obj['_M_impl']['_M_finish'] - obj['_M_impl']['_M_start'] | |
345 | ||
346 | def get(self, obj, index): | |
347 | if self._elemtype.code == gdb.TYPE_CODE_BOOL: | |
348 | start = obj['_M_impl']['_M_start']['_M_p'] | |
349 | bit_size = start.dereference().type.sizeof * 8 | |
350 | valp = start + index / bit_size | |
351 | offset = index % bit_size | |
352 | return (valp.dereference() & (1 << offset)) > 0 | |
353 | else: | |
354 | return obj['_M_impl']['_M_start'][index] | |
355 | ||
356 | class VectorEmptyWorker(VectorWorkerBase): | |
357 | def get_arg_types(self): | |
358 | return None | |
359 | ||
360 | def __call__(self, obj): | |
361 | return int(self.size(obj)) == 0 | |
362 | ||
363 | class VectorSizeWorker(VectorWorkerBase): | |
364 | def get_arg_types(self): | |
365 | return None | |
366 | ||
367 | def __call__(self, obj): | |
368 | return self.size(obj) | |
369 | ||
370 | class VectorFrontWorker(VectorWorkerBase): | |
371 | def get_arg_types(self): | |
372 | return None | |
373 | ||
374 | def __call__(self, obj): | |
375 | return self.get(obj, 0) | |
376 | ||
377 | class VectorBackWorker(VectorWorkerBase): | |
378 | def get_arg_types(self): | |
379 | return None | |
e9e08827 | 380 | |
4027b015 SCR |
381 | def __call__(self, obj): |
382 | return self.get(obj, int(self.size(obj)) - 1) | |
383 | ||
384 | class VectorAtWorker(VectorWorkerBase): | |
385 | def get_arg_types(self): | |
386 | return gdb.lookup_type('std::size_t') | |
387 | ||
388 | def __call__(self, obj, index): | |
389 | size = int(self.size(obj)) | |
390 | if int(index) >= size: | |
391 | raise IndexError('Vector index "%d" should not be >= %d.' % | |
392 | ((int(index), size))) | |
393 | return self.get(obj, int(index)) | |
394 | ||
395 | class VectorSubscriptWorker(VectorWorkerBase): | |
e9e08827 SCR |
396 | def get_arg_types(self): |
397 | return gdb.lookup_type('std::size_t') | |
398 | ||
399 | def __call__(self, obj, subscript): | |
4027b015 | 400 | return self.get(obj, int(subscript)) |
e9e08827 SCR |
401 | |
402 | class VectorMethodsMatcher(gdb.xmethod.XMethodMatcher): | |
403 | def __init__(self): | |
404 | gdb.xmethod.XMethodMatcher.__init__(self, | |
405 | matcher_name_prefix + 'vector') | |
4027b015 SCR |
406 | self._method_dict = { |
407 | 'size': LibStdCxxXMethod('size', VectorSizeWorker), | |
408 | 'empty': LibStdCxxXMethod('empty', VectorEmptyWorker), | |
409 | 'front': LibStdCxxXMethod('front', VectorFrontWorker), | |
410 | 'back': LibStdCxxXMethod('back', VectorBackWorker), | |
411 | 'at': LibStdCxxXMethod('at', VectorAtWorker), | |
412 | 'operator[]': LibStdCxxXMethod('operator[]', | |
413 | VectorSubscriptWorker), | |
414 | } | |
415 | self.methods = [self._method_dict[m] for m in self._method_dict] | |
e9e08827 SCR |
416 | |
417 | def match(self, class_type, method_name): | |
418 | if not re.match('^std::vector<.*>$', class_type.tag): | |
419 | return None | |
4027b015 SCR |
420 | method = self._method_dict.get(method_name) |
421 | if method is None or not method.enabled: | |
422 | return None | |
423 | return method.worker_class(class_type.template_argument(0)) | |
e9e08827 | 424 | |
a5281f17 SCR |
425 | # Xmethods for associative containers |
426 | ||
427 | class AssociativeContainerWorkerBase(gdb.xmethod.XMethodWorker): | |
428 | def __init__(self, unordered): | |
429 | self._unordered = unordered | |
430 | ||
431 | def node_count(self, obj): | |
432 | if self._unordered: | |
433 | return obj['_M_h']['_M_element_count'] | |
434 | else: | |
435 | return obj['_M_t']['_M_impl']['_M_node_count'] | |
436 | ||
437 | def get_arg_types(self): | |
438 | return None | |
439 | ||
440 | class AssociativeContainerEmptyWorker(AssociativeContainerWorkerBase): | |
441 | def __call__(self, obj): | |
442 | return int(self.node_count(obj)) == 0 | |
443 | ||
444 | class AssociativeContainerSizeWorker(AssociativeContainerWorkerBase): | |
445 | def __call__(self, obj): | |
446 | return self.node_count(obj) | |
447 | ||
448 | class AssociativeContainerMethodsMatcher(gdb.xmethod.XMethodMatcher): | |
449 | def __init__(self, name): | |
450 | gdb.xmethod.XMethodMatcher.__init__(self, | |
451 | matcher_name_prefix + name) | |
452 | self._name = name | |
453 | self._method_dict = { | |
454 | 'size': LibStdCxxXMethod('size', AssociativeContainerSizeWorker), | |
455 | 'empty': LibStdCxxXMethod('empty', | |
456 | AssociativeContainerEmptyWorker), | |
457 | } | |
458 | self.methods = [self._method_dict[m] for m in self._method_dict] | |
459 | ||
460 | def match(self, class_type, method_name): | |
461 | if not re.match('^std::%s<.*>$' % self._name, class_type.tag): | |
462 | return None | |
463 | method = self._method_dict.get(method_name) | |
464 | if method is None or not method.enabled: | |
465 | return None | |
466 | unordered = 'unordered' in self._name | |
467 | return method.worker_class(unordered) | |
468 | ||
e9e08827 SCR |
469 | # Xmethods for std::unique_ptr |
470 | ||
471 | class UniquePtrGetWorker(gdb.xmethod.XMethodWorker): | |
472 | def __init__(self): | |
473 | self.name = 'get' | |
474 | self.enabled = True | |
475 | ||
476 | def get_arg_types(self): | |
477 | return None | |
478 | ||
479 | def __call__(self, obj): | |
480 | return obj['_M_t']['_M_head_impl'] | |
481 | ||
482 | class UniquePtrDerefWorker(UniquePtrGetWorker): | |
483 | def __init__(self): | |
484 | UniquePtrGetWorker.__init__(self) | |
485 | self.name = 'operator*' | |
486 | ||
487 | def __call__(self, obj): | |
488 | return UniquePtrGetWorker.__call__(self, obj).dereference() | |
489 | ||
490 | class UniquePtrMethodsMatcher(gdb.xmethod.XMethodMatcher): | |
491 | def __init__(self): | |
492 | gdb.xmethod.XMethodMatcher.__init__(self, | |
493 | matcher_name_prefix + 'unique_ptr') | |
494 | self._get_worker = UniquePtrGetWorker() | |
495 | self._deref_worker = UniquePtrDerefWorker() | |
496 | self.methods = [self._get_worker, self._deref_worker] | |
497 | ||
498 | def match(self, class_type, method_name): | |
499 | if not re.match('^std::unique_ptr<.*>$', class_type.tag): | |
500 | return None | |
501 | if method_name == 'operator*' and self._deref_worker.enabled: | |
502 | return self._deref_worker | |
503 | elif method_name == 'get' and self._get_worker.enabled: | |
504 | return self._get_worker | |
505 | \f | |
506 | def register_libstdcxx_xmethods(locus): | |
4027b015 SCR |
507 | gdb.xmethod.register_xmethod_matcher(locus, ArrayMethodsMatcher()) |
508 | gdb.xmethod.register_xmethod_matcher(locus, ForwardListMethodsMatcher()) | |
509 | gdb.xmethod.register_xmethod_matcher(locus, DequeMethodsMatcher()) | |
510 | gdb.xmethod.register_xmethod_matcher(locus, ListMethodsMatcher()) | |
e9e08827 | 511 | gdb.xmethod.register_xmethod_matcher(locus, VectorMethodsMatcher()) |
a5281f17 SCR |
512 | gdb.xmethod.register_xmethod_matcher( |
513 | locus, AssociativeContainerMethodsMatcher('set')) | |
514 | gdb.xmethod.register_xmethod_matcher( | |
515 | locus, AssociativeContainerMethodsMatcher('map')) | |
516 | gdb.xmethod.register_xmethod_matcher( | |
517 | locus, AssociativeContainerMethodsMatcher('multiset')) | |
518 | gdb.xmethod.register_xmethod_matcher( | |
519 | locus, AssociativeContainerMethodsMatcher('multimap')) | |
520 | gdb.xmethod.register_xmethod_matcher( | |
521 | locus, AssociativeContainerMethodsMatcher('unordered_set')) | |
522 | gdb.xmethod.register_xmethod_matcher( | |
523 | locus, AssociativeContainerMethodsMatcher('unordered_map')) | |
524 | gdb.xmethod.register_xmethod_matcher( | |
525 | locus, AssociativeContainerMethodsMatcher('unordered_multiset')) | |
526 | gdb.xmethod.register_xmethod_matcher( | |
527 | locus, AssociativeContainerMethodsMatcher('unordered_multimap')) | |
e9e08827 | 528 | gdb.xmethod.register_xmethod_matcher(locus, UniquePtrMethodsMatcher()) |