136ac495dSmrg# Xmethods for libstdc++. 236ac495dSmrg 38feb0f0bSmrg# Copyright (C) 2014-2020 Free Software Foundation, Inc. 436ac495dSmrg 536ac495dSmrg# This program is free software; you can redistribute it and/or modify 636ac495dSmrg# it under the terms of the GNU General Public License as published by 736ac495dSmrg# the Free Software Foundation; either version 3 of the License, or 836ac495dSmrg# (at your option) any later version. 936ac495dSmrg# 1036ac495dSmrg# This program is distributed in the hope that it will be useful, 1136ac495dSmrg# but WITHOUT ANY WARRANTY; without even the implied warranty of 1236ac495dSmrg# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1336ac495dSmrg# GNU General Public License for more details. 1436ac495dSmrg# 1536ac495dSmrg# You should have received a copy of the GNU General Public License 1636ac495dSmrg# along with this program. If not, see <http://www.gnu.org/licenses/>. 1736ac495dSmrg 1836ac495dSmrgimport gdb 1936ac495dSmrgimport gdb.xmethod 2036ac495dSmrgimport re 2136ac495dSmrg 2236ac495dSmrgmatcher_name_prefix = 'libstdc++::' 2336ac495dSmrg 2436ac495dSmrgdef get_bool_type(): 2536ac495dSmrg return gdb.lookup_type('bool') 2636ac495dSmrg 2736ac495dSmrgdef get_std_size_type(): 2836ac495dSmrg return gdb.lookup_type('std::size_t') 2936ac495dSmrg 3036ac495dSmrgclass LibStdCxxXMethod(gdb.xmethod.XMethod): 3136ac495dSmrg def __init__(self, name, worker_class): 3236ac495dSmrg gdb.xmethod.XMethod.__init__(self, name) 3336ac495dSmrg self.worker_class = worker_class 3436ac495dSmrg 3536ac495dSmrg# Xmethods for std::array 3636ac495dSmrg 3736ac495dSmrgclass ArrayWorkerBase(gdb.xmethod.XMethodWorker): 3836ac495dSmrg def __init__(self, val_type, size): 3936ac495dSmrg self._val_type = val_type 4036ac495dSmrg self._size = size 4136ac495dSmrg 4236ac495dSmrg def null_value(self): 4336ac495dSmrg nullptr = gdb.parse_and_eval('(void *) 0') 4436ac495dSmrg return nullptr.cast(self._val_type.pointer()).dereference() 4536ac495dSmrg 4636ac495dSmrgclass ArraySizeWorker(ArrayWorkerBase): 4736ac495dSmrg def __init__(self, val_type, size): 4836ac495dSmrg ArrayWorkerBase.__init__(self, val_type, size) 4936ac495dSmrg 5036ac495dSmrg def get_arg_types(self): 5136ac495dSmrg return None 5236ac495dSmrg 5336ac495dSmrg def get_result_type(self, obj): 5436ac495dSmrg return get_std_size_type() 5536ac495dSmrg 5636ac495dSmrg def __call__(self, obj): 5736ac495dSmrg return self._size 5836ac495dSmrg 5936ac495dSmrgclass ArrayEmptyWorker(ArrayWorkerBase): 6036ac495dSmrg def __init__(self, val_type, size): 6136ac495dSmrg ArrayWorkerBase.__init__(self, val_type, size) 6236ac495dSmrg 6336ac495dSmrg def get_arg_types(self): 6436ac495dSmrg return None 6536ac495dSmrg 6636ac495dSmrg def get_result_type(self, obj): 6736ac495dSmrg return get_bool_type() 6836ac495dSmrg 6936ac495dSmrg def __call__(self, obj): 7036ac495dSmrg return (int(self._size) == 0) 7136ac495dSmrg 7236ac495dSmrgclass ArrayFrontWorker(ArrayWorkerBase): 7336ac495dSmrg def __init__(self, val_type, size): 7436ac495dSmrg ArrayWorkerBase.__init__(self, val_type, size) 7536ac495dSmrg 7636ac495dSmrg def get_arg_types(self): 7736ac495dSmrg return None 7836ac495dSmrg 7936ac495dSmrg def get_result_type(self, obj): 8036ac495dSmrg return self._val_type 8136ac495dSmrg 8236ac495dSmrg def __call__(self, obj): 8336ac495dSmrg if int(self._size) > 0: 8436ac495dSmrg return obj['_M_elems'][0] 8536ac495dSmrg else: 8636ac495dSmrg return self.null_value() 8736ac495dSmrg 8836ac495dSmrgclass ArrayBackWorker(ArrayWorkerBase): 8936ac495dSmrg def __init__(self, val_type, size): 9036ac495dSmrg ArrayWorkerBase.__init__(self, val_type, size) 9136ac495dSmrg 9236ac495dSmrg def get_arg_types(self): 9336ac495dSmrg return None 9436ac495dSmrg 9536ac495dSmrg def get_result_type(self, obj): 9636ac495dSmrg return self._val_type 9736ac495dSmrg 9836ac495dSmrg def __call__(self, obj): 9936ac495dSmrg if int(self._size) > 0: 10036ac495dSmrg return obj['_M_elems'][self._size - 1] 10136ac495dSmrg else: 10236ac495dSmrg return self.null_value() 10336ac495dSmrg 10436ac495dSmrgclass ArrayAtWorker(ArrayWorkerBase): 10536ac495dSmrg def __init__(self, val_type, size): 10636ac495dSmrg ArrayWorkerBase.__init__(self, val_type, size) 10736ac495dSmrg 10836ac495dSmrg def get_arg_types(self): 10936ac495dSmrg return get_std_size_type() 11036ac495dSmrg 11136ac495dSmrg def get_result_type(self, obj, index): 11236ac495dSmrg return self._val_type 11336ac495dSmrg 11436ac495dSmrg def __call__(self, obj, index): 11536ac495dSmrg if int(index) >= int(self._size): 11636ac495dSmrg raise IndexError('Array index "%d" should not be >= %d.' % 11736ac495dSmrg ((int(index), self._size))) 11836ac495dSmrg return obj['_M_elems'][index] 11936ac495dSmrg 12036ac495dSmrgclass ArraySubscriptWorker(ArrayWorkerBase): 12136ac495dSmrg def __init__(self, val_type, size): 12236ac495dSmrg ArrayWorkerBase.__init__(self, val_type, size) 12336ac495dSmrg 12436ac495dSmrg def get_arg_types(self): 12536ac495dSmrg return get_std_size_type() 12636ac495dSmrg 12736ac495dSmrg def get_result_type(self, obj, index): 12836ac495dSmrg return self._val_type 12936ac495dSmrg 13036ac495dSmrg def __call__(self, obj, index): 13136ac495dSmrg if int(self._size) > 0: 13236ac495dSmrg return obj['_M_elems'][index] 13336ac495dSmrg else: 13436ac495dSmrg return self.null_value() 13536ac495dSmrg 13636ac495dSmrgclass ArrayMethodsMatcher(gdb.xmethod.XMethodMatcher): 13736ac495dSmrg def __init__(self): 13836ac495dSmrg gdb.xmethod.XMethodMatcher.__init__(self, 13936ac495dSmrg matcher_name_prefix + 'array') 14036ac495dSmrg self._method_dict = { 14136ac495dSmrg 'size': LibStdCxxXMethod('size', ArraySizeWorker), 14236ac495dSmrg 'empty': LibStdCxxXMethod('empty', ArrayEmptyWorker), 14336ac495dSmrg 'front': LibStdCxxXMethod('front', ArrayFrontWorker), 14436ac495dSmrg 'back': LibStdCxxXMethod('back', ArrayBackWorker), 14536ac495dSmrg 'at': LibStdCxxXMethod('at', ArrayAtWorker), 14636ac495dSmrg 'operator[]': LibStdCxxXMethod('operator[]', ArraySubscriptWorker), 14736ac495dSmrg } 14836ac495dSmrg self.methods = [self._method_dict[m] for m in self._method_dict] 14936ac495dSmrg 15036ac495dSmrg def match(self, class_type, method_name): 15136ac495dSmrg if not re.match('^std::(__\d+::)?array<.*>$', class_type.tag): 15236ac495dSmrg return None 15336ac495dSmrg method = self._method_dict.get(method_name) 15436ac495dSmrg if method is None or not method.enabled: 15536ac495dSmrg return None 15636ac495dSmrg try: 15736ac495dSmrg value_type = class_type.template_argument(0) 15836ac495dSmrg size = class_type.template_argument(1) 15936ac495dSmrg except: 16036ac495dSmrg return None 16136ac495dSmrg return method.worker_class(value_type, size) 16236ac495dSmrg 16336ac495dSmrg# Xmethods for std::deque 16436ac495dSmrg 16536ac495dSmrgclass DequeWorkerBase(gdb.xmethod.XMethodWorker): 16636ac495dSmrg def __init__(self, val_type): 16736ac495dSmrg self._val_type = val_type 16836ac495dSmrg self._bufsize = 512 // val_type.sizeof or 1 16936ac495dSmrg 17036ac495dSmrg def size(self, obj): 17136ac495dSmrg first_node = obj['_M_impl']['_M_start']['_M_node'] 17236ac495dSmrg last_node = obj['_M_impl']['_M_finish']['_M_node'] 17336ac495dSmrg cur = obj['_M_impl']['_M_finish']['_M_cur'] 17436ac495dSmrg first = obj['_M_impl']['_M_finish']['_M_first'] 17536ac495dSmrg return (last_node - first_node) * self._bufsize + (cur - first) 17636ac495dSmrg 17736ac495dSmrg def index(self, obj, idx): 17836ac495dSmrg first_node = obj['_M_impl']['_M_start']['_M_node'] 17936ac495dSmrg index_node = first_node + int(idx) // self._bufsize 18036ac495dSmrg return index_node[0][idx % self._bufsize] 18136ac495dSmrg 18236ac495dSmrgclass DequeEmptyWorker(DequeWorkerBase): 18336ac495dSmrg def get_arg_types(self): 18436ac495dSmrg return None 18536ac495dSmrg 18636ac495dSmrg def get_result_type(self, obj): 18736ac495dSmrg return get_bool_type() 18836ac495dSmrg 18936ac495dSmrg def __call__(self, obj): 19036ac495dSmrg return (obj['_M_impl']['_M_start']['_M_cur'] == 19136ac495dSmrg obj['_M_impl']['_M_finish']['_M_cur']) 19236ac495dSmrg 19336ac495dSmrgclass DequeSizeWorker(DequeWorkerBase): 19436ac495dSmrg def get_arg_types(self): 19536ac495dSmrg return None 19636ac495dSmrg 19736ac495dSmrg def get_result_type(self, obj): 19836ac495dSmrg return get_std_size_type() 19936ac495dSmrg 20036ac495dSmrg def __call__(self, obj): 20136ac495dSmrg return self.size(obj) 20236ac495dSmrg 20336ac495dSmrgclass DequeFrontWorker(DequeWorkerBase): 20436ac495dSmrg def get_arg_types(self): 20536ac495dSmrg return None 20636ac495dSmrg 20736ac495dSmrg def get_result_type(self, obj): 20836ac495dSmrg return self._val_type 20936ac495dSmrg 21036ac495dSmrg def __call__(self, obj): 21136ac495dSmrg return obj['_M_impl']['_M_start']['_M_cur'][0] 21236ac495dSmrg 21336ac495dSmrgclass DequeBackWorker(DequeWorkerBase): 21436ac495dSmrg def get_arg_types(self): 21536ac495dSmrg return None 21636ac495dSmrg 21736ac495dSmrg def get_result_type(self, obj): 21836ac495dSmrg return self._val_type 21936ac495dSmrg 22036ac495dSmrg def __call__(self, obj): 22136ac495dSmrg if (obj['_M_impl']['_M_finish']['_M_cur'] == 22236ac495dSmrg obj['_M_impl']['_M_finish']['_M_first']): 22336ac495dSmrg prev_node = obj['_M_impl']['_M_finish']['_M_node'] - 1 22436ac495dSmrg return prev_node[0][self._bufsize - 1] 22536ac495dSmrg else: 22636ac495dSmrg return obj['_M_impl']['_M_finish']['_M_cur'][-1] 22736ac495dSmrg 22836ac495dSmrgclass DequeSubscriptWorker(DequeWorkerBase): 22936ac495dSmrg def get_arg_types(self): 23036ac495dSmrg return get_std_size_type() 23136ac495dSmrg 23236ac495dSmrg def get_result_type(self, obj, subscript): 23336ac495dSmrg return self._val_type 23436ac495dSmrg 23536ac495dSmrg def __call__(self, obj, subscript): 23636ac495dSmrg return self.index(obj, subscript) 23736ac495dSmrg 23836ac495dSmrgclass DequeAtWorker(DequeWorkerBase): 23936ac495dSmrg def get_arg_types(self): 24036ac495dSmrg return get_std_size_type() 24136ac495dSmrg 24236ac495dSmrg def get_result_type(self, obj, index): 24336ac495dSmrg return self._val_type 24436ac495dSmrg 24536ac495dSmrg def __call__(self, obj, index): 24636ac495dSmrg deque_size = int(self.size(obj)) 24736ac495dSmrg if int(index) >= deque_size: 24836ac495dSmrg raise IndexError('Deque index "%d" should not be >= %d.' % 24936ac495dSmrg (int(index), deque_size)) 25036ac495dSmrg else: 25136ac495dSmrg return self.index(obj, index) 25236ac495dSmrg 25336ac495dSmrgclass DequeMethodsMatcher(gdb.xmethod.XMethodMatcher): 25436ac495dSmrg def __init__(self): 25536ac495dSmrg gdb.xmethod.XMethodMatcher.__init__(self, 25636ac495dSmrg matcher_name_prefix + 'deque') 25736ac495dSmrg self._method_dict = { 25836ac495dSmrg 'empty': LibStdCxxXMethod('empty', DequeEmptyWorker), 25936ac495dSmrg 'size': LibStdCxxXMethod('size', DequeSizeWorker), 26036ac495dSmrg 'front': LibStdCxxXMethod('front', DequeFrontWorker), 26136ac495dSmrg 'back': LibStdCxxXMethod('back', DequeBackWorker), 26236ac495dSmrg 'operator[]': LibStdCxxXMethod('operator[]', DequeSubscriptWorker), 26336ac495dSmrg 'at': LibStdCxxXMethod('at', DequeAtWorker) 26436ac495dSmrg } 26536ac495dSmrg self.methods = [self._method_dict[m] for m in self._method_dict] 26636ac495dSmrg 26736ac495dSmrg def match(self, class_type, method_name): 26836ac495dSmrg if not re.match('^std::(__\d+::)?deque<.*>$', class_type.tag): 26936ac495dSmrg return None 27036ac495dSmrg method = self._method_dict.get(method_name) 27136ac495dSmrg if method is None or not method.enabled: 27236ac495dSmrg return None 27336ac495dSmrg return method.worker_class(class_type.template_argument(0)) 27436ac495dSmrg 27536ac495dSmrg# Xmethods for std::forward_list 27636ac495dSmrg 27736ac495dSmrgclass ForwardListWorkerBase(gdb.xmethod.XMethodMatcher): 27836ac495dSmrg def __init__(self, val_type, node_type): 27936ac495dSmrg self._val_type = val_type 28036ac495dSmrg self._node_type = node_type 28136ac495dSmrg 28236ac495dSmrg def get_arg_types(self): 28336ac495dSmrg return None 28436ac495dSmrg 28536ac495dSmrgclass ForwardListEmptyWorker(ForwardListWorkerBase): 28636ac495dSmrg def get_result_type(self, obj): 28736ac495dSmrg return get_bool_type() 28836ac495dSmrg 28936ac495dSmrg def __call__(self, obj): 29036ac495dSmrg return obj['_M_impl']['_M_head']['_M_next'] == 0 29136ac495dSmrg 29236ac495dSmrgclass ForwardListFrontWorker(ForwardListWorkerBase): 29336ac495dSmrg def get_result_type(self, obj): 29436ac495dSmrg return self._val_type 29536ac495dSmrg 29636ac495dSmrg def __call__(self, obj): 29736ac495dSmrg node = obj['_M_impl']['_M_head']['_M_next'].cast(self._node_type) 29836ac495dSmrg val_address = node['_M_storage']['_M_storage'].address 29936ac495dSmrg return val_address.cast(self._val_type.pointer()).dereference() 30036ac495dSmrg 30136ac495dSmrgclass ForwardListMethodsMatcher(gdb.xmethod.XMethodMatcher): 30236ac495dSmrg def __init__(self): 30336ac495dSmrg matcher_name = matcher_name_prefix + 'forward_list' 30436ac495dSmrg gdb.xmethod.XMethodMatcher.__init__(self, matcher_name) 30536ac495dSmrg self._method_dict = { 30636ac495dSmrg 'empty': LibStdCxxXMethod('empty', ForwardListEmptyWorker), 30736ac495dSmrg 'front': LibStdCxxXMethod('front', ForwardListFrontWorker) 30836ac495dSmrg } 30936ac495dSmrg self.methods = [self._method_dict[m] for m in self._method_dict] 31036ac495dSmrg 31136ac495dSmrg def match(self, class_type, method_name): 31236ac495dSmrg if not re.match('^std::(__\d+::)?forward_list<.*>$', class_type.tag): 31336ac495dSmrg return None 31436ac495dSmrg method = self._method_dict.get(method_name) 31536ac495dSmrg if method is None or not method.enabled: 31636ac495dSmrg return None 31736ac495dSmrg val_type = class_type.template_argument(0) 31836ac495dSmrg node_type = gdb.lookup_type(str(class_type) + '::_Node').pointer() 31936ac495dSmrg return method.worker_class(val_type, node_type) 32036ac495dSmrg 32136ac495dSmrg# Xmethods for std::list 32236ac495dSmrg 32336ac495dSmrgclass ListWorkerBase(gdb.xmethod.XMethodWorker): 32436ac495dSmrg def __init__(self, val_type, node_type): 32536ac495dSmrg self._val_type = val_type 32636ac495dSmrg self._node_type = node_type 32736ac495dSmrg 32836ac495dSmrg def get_arg_types(self): 32936ac495dSmrg return None 33036ac495dSmrg 33136ac495dSmrg def get_value_from_node(self, node): 33236ac495dSmrg node = node.dereference() 33336ac495dSmrg if node.type.fields()[1].name == '_M_data': 33436ac495dSmrg # C++03 implementation, node contains the value as a member 33536ac495dSmrg return node['_M_data'] 33636ac495dSmrg # C++11 implementation, node stores value in __aligned_membuf 33736ac495dSmrg addr = node['_M_storage'].address 33836ac495dSmrg return addr.cast(self._val_type.pointer()).dereference() 33936ac495dSmrg 34036ac495dSmrgclass ListEmptyWorker(ListWorkerBase): 34136ac495dSmrg def get_result_type(self, obj): 34236ac495dSmrg return get_bool_type() 34336ac495dSmrg 34436ac495dSmrg def __call__(self, obj): 34536ac495dSmrg base_node = obj['_M_impl']['_M_node'] 34636ac495dSmrg if base_node['_M_next'] == base_node.address: 34736ac495dSmrg return True 34836ac495dSmrg else: 34936ac495dSmrg return False 35036ac495dSmrg 35136ac495dSmrgclass ListSizeWorker(ListWorkerBase): 35236ac495dSmrg def get_result_type(self, obj): 35336ac495dSmrg return get_std_size_type() 35436ac495dSmrg 35536ac495dSmrg def __call__(self, obj): 35636ac495dSmrg begin_node = obj['_M_impl']['_M_node']['_M_next'] 35736ac495dSmrg end_node = obj['_M_impl']['_M_node'].address 35836ac495dSmrg size = 0 35936ac495dSmrg while begin_node != end_node: 36036ac495dSmrg begin_node = begin_node['_M_next'] 36136ac495dSmrg size += 1 36236ac495dSmrg return size 36336ac495dSmrg 36436ac495dSmrgclass ListFrontWorker(ListWorkerBase): 36536ac495dSmrg def get_result_type(self, obj): 36636ac495dSmrg return self._val_type 36736ac495dSmrg 36836ac495dSmrg def __call__(self, obj): 36936ac495dSmrg node = obj['_M_impl']['_M_node']['_M_next'].cast(self._node_type) 37036ac495dSmrg return self.get_value_from_node(node) 37136ac495dSmrg 37236ac495dSmrgclass ListBackWorker(ListWorkerBase): 37336ac495dSmrg def get_result_type(self, obj): 37436ac495dSmrg return self._val_type 37536ac495dSmrg 37636ac495dSmrg def __call__(self, obj): 37736ac495dSmrg prev_node = obj['_M_impl']['_M_node']['_M_prev'].cast(self._node_type) 37836ac495dSmrg return self.get_value_from_node(prev_node) 37936ac495dSmrg 38036ac495dSmrgclass ListMethodsMatcher(gdb.xmethod.XMethodMatcher): 38136ac495dSmrg def __init__(self): 38236ac495dSmrg gdb.xmethod.XMethodMatcher.__init__(self, 38336ac495dSmrg matcher_name_prefix + 'list') 38436ac495dSmrg self._method_dict = { 38536ac495dSmrg 'empty': LibStdCxxXMethod('empty', ListEmptyWorker), 38636ac495dSmrg 'size': LibStdCxxXMethod('size', ListSizeWorker), 38736ac495dSmrg 'front': LibStdCxxXMethod('front', ListFrontWorker), 38836ac495dSmrg 'back': LibStdCxxXMethod('back', ListBackWorker) 38936ac495dSmrg } 39036ac495dSmrg self.methods = [self._method_dict[m] for m in self._method_dict] 39136ac495dSmrg 39236ac495dSmrg def match(self, class_type, method_name): 39336ac495dSmrg if not re.match('^std::(__\d+::)?(__cxx11::)?list<.*>$', class_type.tag): 39436ac495dSmrg return None 39536ac495dSmrg method = self._method_dict.get(method_name) 39636ac495dSmrg if method is None or not method.enabled: 39736ac495dSmrg return None 39836ac495dSmrg val_type = class_type.template_argument(0) 39936ac495dSmrg node_type = gdb.lookup_type(str(class_type) + '::_Node').pointer() 40036ac495dSmrg return method.worker_class(val_type, node_type) 40136ac495dSmrg 40236ac495dSmrg# Xmethods for std::vector 40336ac495dSmrg 40436ac495dSmrgclass VectorWorkerBase(gdb.xmethod.XMethodWorker): 40536ac495dSmrg def __init__(self, val_type): 40636ac495dSmrg self._val_type = val_type 40736ac495dSmrg 40836ac495dSmrg def size(self, obj): 40936ac495dSmrg if self._val_type.code == gdb.TYPE_CODE_BOOL: 41036ac495dSmrg start = obj['_M_impl']['_M_start']['_M_p'] 41136ac495dSmrg finish = obj['_M_impl']['_M_finish']['_M_p'] 41236ac495dSmrg finish_offset = obj['_M_impl']['_M_finish']['_M_offset'] 41336ac495dSmrg bit_size = start.dereference().type.sizeof * 8 41436ac495dSmrg return (finish - start) * bit_size + finish_offset 41536ac495dSmrg else: 41636ac495dSmrg return obj['_M_impl']['_M_finish'] - obj['_M_impl']['_M_start'] 41736ac495dSmrg 41836ac495dSmrg def get(self, obj, index): 41936ac495dSmrg if self._val_type.code == gdb.TYPE_CODE_BOOL: 42036ac495dSmrg start = obj['_M_impl']['_M_start']['_M_p'] 42136ac495dSmrg bit_size = start.dereference().type.sizeof * 8 42236ac495dSmrg valp = start + index // bit_size 42336ac495dSmrg offset = index % bit_size 42436ac495dSmrg return (valp.dereference() & (1 << offset)) > 0 42536ac495dSmrg else: 42636ac495dSmrg return obj['_M_impl']['_M_start'][index] 42736ac495dSmrg 42836ac495dSmrgclass VectorEmptyWorker(VectorWorkerBase): 42936ac495dSmrg def get_arg_types(self): 43036ac495dSmrg return None 43136ac495dSmrg 43236ac495dSmrg def get_result_type(self, obj): 43336ac495dSmrg return get_bool_type() 43436ac495dSmrg 43536ac495dSmrg def __call__(self, obj): 43636ac495dSmrg return int(self.size(obj)) == 0 43736ac495dSmrg 43836ac495dSmrgclass VectorSizeWorker(VectorWorkerBase): 43936ac495dSmrg def get_arg_types(self): 44036ac495dSmrg return None 44136ac495dSmrg 44236ac495dSmrg def get_result_type(self, obj): 44336ac495dSmrg return get_std_size_type() 44436ac495dSmrg 44536ac495dSmrg def __call__(self, obj): 44636ac495dSmrg return self.size(obj) 44736ac495dSmrg 44836ac495dSmrgclass VectorFrontWorker(VectorWorkerBase): 44936ac495dSmrg def get_arg_types(self): 45036ac495dSmrg return None 45136ac495dSmrg 45236ac495dSmrg def get_result_type(self, obj): 45336ac495dSmrg return self._val_type 45436ac495dSmrg 45536ac495dSmrg def __call__(self, obj): 45636ac495dSmrg return self.get(obj, 0) 45736ac495dSmrg 45836ac495dSmrgclass VectorBackWorker(VectorWorkerBase): 45936ac495dSmrg def get_arg_types(self): 46036ac495dSmrg return None 46136ac495dSmrg 46236ac495dSmrg def get_result_type(self, obj): 46336ac495dSmrg return self._val_type 46436ac495dSmrg 46536ac495dSmrg def __call__(self, obj): 46636ac495dSmrg return self.get(obj, int(self.size(obj)) - 1) 46736ac495dSmrg 46836ac495dSmrgclass VectorAtWorker(VectorWorkerBase): 46936ac495dSmrg def get_arg_types(self): 47036ac495dSmrg return get_std_size_type() 47136ac495dSmrg 47236ac495dSmrg def get_result_type(self, obj, index): 47336ac495dSmrg return self._val_type 47436ac495dSmrg 47536ac495dSmrg def __call__(self, obj, index): 47636ac495dSmrg size = int(self.size(obj)) 47736ac495dSmrg if int(index) >= size: 47836ac495dSmrg raise IndexError('Vector index "%d" should not be >= %d.' % 47936ac495dSmrg ((int(index), size))) 48036ac495dSmrg return self.get(obj, int(index)) 48136ac495dSmrg 48236ac495dSmrgclass VectorSubscriptWorker(VectorWorkerBase): 48336ac495dSmrg def get_arg_types(self): 48436ac495dSmrg return get_std_size_type() 48536ac495dSmrg 48636ac495dSmrg def get_result_type(self, obj, subscript): 48736ac495dSmrg return self._val_type 48836ac495dSmrg 48936ac495dSmrg def __call__(self, obj, subscript): 49036ac495dSmrg return self.get(obj, int(subscript)) 49136ac495dSmrg 49236ac495dSmrgclass VectorMethodsMatcher(gdb.xmethod.XMethodMatcher): 49336ac495dSmrg def __init__(self): 49436ac495dSmrg gdb.xmethod.XMethodMatcher.__init__(self, 49536ac495dSmrg matcher_name_prefix + 'vector') 49636ac495dSmrg self._method_dict = { 49736ac495dSmrg 'size': LibStdCxxXMethod('size', VectorSizeWorker), 49836ac495dSmrg 'empty': LibStdCxxXMethod('empty', VectorEmptyWorker), 49936ac495dSmrg 'front': LibStdCxxXMethod('front', VectorFrontWorker), 50036ac495dSmrg 'back': LibStdCxxXMethod('back', VectorBackWorker), 50136ac495dSmrg 'at': LibStdCxxXMethod('at', VectorAtWorker), 50236ac495dSmrg 'operator[]': LibStdCxxXMethod('operator[]', 50336ac495dSmrg VectorSubscriptWorker), 50436ac495dSmrg } 50536ac495dSmrg self.methods = [self._method_dict[m] for m in self._method_dict] 50636ac495dSmrg 50736ac495dSmrg def match(self, class_type, method_name): 50836ac495dSmrg if not re.match('^std::(__\d+::)?vector<.*>$', class_type.tag): 50936ac495dSmrg return None 51036ac495dSmrg method = self._method_dict.get(method_name) 51136ac495dSmrg if method is None or not method.enabled: 51236ac495dSmrg return None 51336ac495dSmrg return method.worker_class(class_type.template_argument(0)) 51436ac495dSmrg 51536ac495dSmrg# Xmethods for associative containers 51636ac495dSmrg 51736ac495dSmrgclass AssociativeContainerWorkerBase(gdb.xmethod.XMethodWorker): 51836ac495dSmrg def __init__(self, unordered): 51936ac495dSmrg self._unordered = unordered 52036ac495dSmrg 52136ac495dSmrg def node_count(self, obj): 52236ac495dSmrg if self._unordered: 52336ac495dSmrg return obj['_M_h']['_M_element_count'] 52436ac495dSmrg else: 52536ac495dSmrg return obj['_M_t']['_M_impl']['_M_node_count'] 52636ac495dSmrg 52736ac495dSmrg def get_arg_types(self): 52836ac495dSmrg return None 52936ac495dSmrg 53036ac495dSmrgclass AssociativeContainerEmptyWorker(AssociativeContainerWorkerBase): 53136ac495dSmrg def get_result_type(self, obj): 53236ac495dSmrg return get_bool_type() 53336ac495dSmrg 53436ac495dSmrg def __call__(self, obj): 53536ac495dSmrg return int(self.node_count(obj)) == 0 53636ac495dSmrg 53736ac495dSmrgclass AssociativeContainerSizeWorker(AssociativeContainerWorkerBase): 53836ac495dSmrg def get_result_type(self, obj): 53936ac495dSmrg return get_std_size_type() 54036ac495dSmrg 54136ac495dSmrg def __call__(self, obj): 54236ac495dSmrg return self.node_count(obj) 54336ac495dSmrg 54436ac495dSmrgclass AssociativeContainerMethodsMatcher(gdb.xmethod.XMethodMatcher): 54536ac495dSmrg def __init__(self, name): 54636ac495dSmrg gdb.xmethod.XMethodMatcher.__init__(self, 54736ac495dSmrg matcher_name_prefix + name) 54836ac495dSmrg self._name = name 54936ac495dSmrg self._method_dict = { 55036ac495dSmrg 'size': LibStdCxxXMethod('size', AssociativeContainerSizeWorker), 55136ac495dSmrg 'empty': LibStdCxxXMethod('empty', 55236ac495dSmrg AssociativeContainerEmptyWorker), 55336ac495dSmrg } 55436ac495dSmrg self.methods = [self._method_dict[m] for m in self._method_dict] 55536ac495dSmrg 55636ac495dSmrg def match(self, class_type, method_name): 55736ac495dSmrg if not re.match('^std::(__\d+::)?%s<.*>$' % self._name, class_type.tag): 55836ac495dSmrg return None 55936ac495dSmrg method = self._method_dict.get(method_name) 56036ac495dSmrg if method is None or not method.enabled: 56136ac495dSmrg return None 56236ac495dSmrg unordered = 'unordered' in self._name 56336ac495dSmrg return method.worker_class(unordered) 56436ac495dSmrg 56536ac495dSmrg# Xmethods for std::unique_ptr 56636ac495dSmrg 56736ac495dSmrgclass UniquePtrGetWorker(gdb.xmethod.XMethodWorker): 56836ac495dSmrg "Implements std::unique_ptr<T>::get() and std::unique_ptr<T>::operator->()" 56936ac495dSmrg 57036ac495dSmrg def __init__(self, elem_type): 57136ac495dSmrg self._is_array = elem_type.code == gdb.TYPE_CODE_ARRAY 57236ac495dSmrg if self._is_array: 57336ac495dSmrg self._elem_type = elem_type.target() 57436ac495dSmrg else: 57536ac495dSmrg self._elem_type = elem_type 57636ac495dSmrg 57736ac495dSmrg def get_arg_types(self): 57836ac495dSmrg return None 57936ac495dSmrg 58036ac495dSmrg def get_result_type(self, obj): 58136ac495dSmrg return self._elem_type.pointer() 58236ac495dSmrg 58336ac495dSmrg def _supports(self, method_name): 58436ac495dSmrg "operator-> is not supported for unique_ptr<T[]>" 58536ac495dSmrg return method_name == 'get' or not self._is_array 58636ac495dSmrg 58736ac495dSmrg def __call__(self, obj): 58836ac495dSmrg impl_type = obj.dereference().type.fields()[0].type.tag 5898feb0f0bSmrg # Check for new implementations first: 5908feb0f0bSmrg if re.match('^std::(__\d+::)?__uniq_ptr_(data|impl)<.*>$', impl_type): 5918feb0f0bSmrg tuple_member = obj['_M_t']['_M_t'] 59236ac495dSmrg elif re.match('^std::(__\d+::)?tuple<.*>$', impl_type): 5938feb0f0bSmrg tuple_member = obj['_M_t'] 5948feb0f0bSmrg else: 5958feb0f0bSmrg return None 5968feb0f0bSmrg tuple_impl_type = tuple_member.type.fields()[0].type # _Tuple_impl 5978feb0f0bSmrg tuple_head_type = tuple_impl_type.fields()[1].type # _Head_base 5988feb0f0bSmrg head_field = tuple_head_type.fields()[0] 5998feb0f0bSmrg if head_field.name == '_M_head_impl': 6008feb0f0bSmrg return tuple_member.cast(tuple_head_type)['_M_head_impl'] 6018feb0f0bSmrg elif head_field.is_base_class: 6028feb0f0bSmrg return tuple_member.cast(head_field.type) 6038feb0f0bSmrg else: 60436ac495dSmrg return None 60536ac495dSmrg 60636ac495dSmrgclass UniquePtrDerefWorker(UniquePtrGetWorker): 60736ac495dSmrg "Implements std::unique_ptr<T>::operator*()" 60836ac495dSmrg 60936ac495dSmrg def __init__(self, elem_type): 61036ac495dSmrg UniquePtrGetWorker.__init__(self, elem_type) 61136ac495dSmrg 61236ac495dSmrg def get_result_type(self, obj): 61336ac495dSmrg return self._elem_type 61436ac495dSmrg 61536ac495dSmrg def _supports(self, method_name): 61636ac495dSmrg "operator* is not supported for unique_ptr<T[]>" 61736ac495dSmrg return not self._is_array 61836ac495dSmrg 61936ac495dSmrg def __call__(self, obj): 62036ac495dSmrg return UniquePtrGetWorker.__call__(self, obj).dereference() 62136ac495dSmrg 62236ac495dSmrgclass UniquePtrSubscriptWorker(UniquePtrGetWorker): 62336ac495dSmrg "Implements std::unique_ptr<T>::operator[](size_t)" 62436ac495dSmrg 62536ac495dSmrg def __init__(self, elem_type): 62636ac495dSmrg UniquePtrGetWorker.__init__(self, elem_type) 62736ac495dSmrg 62836ac495dSmrg def get_arg_types(self): 62936ac495dSmrg return get_std_size_type() 63036ac495dSmrg 63136ac495dSmrg def get_result_type(self, obj, index): 63236ac495dSmrg return self._elem_type 63336ac495dSmrg 63436ac495dSmrg def _supports(self, method_name): 63536ac495dSmrg "operator[] is only supported for unique_ptr<T[]>" 63636ac495dSmrg return self._is_array 63736ac495dSmrg 63836ac495dSmrg def __call__(self, obj, index): 63936ac495dSmrg return UniquePtrGetWorker.__call__(self, obj)[index] 64036ac495dSmrg 64136ac495dSmrgclass UniquePtrMethodsMatcher(gdb.xmethod.XMethodMatcher): 64236ac495dSmrg def __init__(self): 64336ac495dSmrg gdb.xmethod.XMethodMatcher.__init__(self, 64436ac495dSmrg matcher_name_prefix + 'unique_ptr') 64536ac495dSmrg self._method_dict = { 64636ac495dSmrg 'get': LibStdCxxXMethod('get', UniquePtrGetWorker), 64736ac495dSmrg 'operator->': LibStdCxxXMethod('operator->', UniquePtrGetWorker), 64836ac495dSmrg 'operator*': LibStdCxxXMethod('operator*', UniquePtrDerefWorker), 64936ac495dSmrg 'operator[]': LibStdCxxXMethod('operator[]', UniquePtrSubscriptWorker), 65036ac495dSmrg } 65136ac495dSmrg self.methods = [self._method_dict[m] for m in self._method_dict] 65236ac495dSmrg 65336ac495dSmrg def match(self, class_type, method_name): 65436ac495dSmrg if not re.match('^std::(__\d+::)?unique_ptr<.*>$', class_type.tag): 65536ac495dSmrg return None 65636ac495dSmrg method = self._method_dict.get(method_name) 65736ac495dSmrg if method is None or not method.enabled: 65836ac495dSmrg return None 65936ac495dSmrg worker = method.worker_class(class_type.template_argument(0)) 66036ac495dSmrg if worker._supports(method_name): 66136ac495dSmrg return worker 66236ac495dSmrg return None 66336ac495dSmrg 66436ac495dSmrg# Xmethods for std::shared_ptr 66536ac495dSmrg 66636ac495dSmrgclass SharedPtrGetWorker(gdb.xmethod.XMethodWorker): 66736ac495dSmrg "Implements std::shared_ptr<T>::get() and std::shared_ptr<T>::operator->()" 66836ac495dSmrg 66936ac495dSmrg def __init__(self, elem_type): 67036ac495dSmrg self._is_array = elem_type.code == gdb.TYPE_CODE_ARRAY 67136ac495dSmrg if self._is_array: 67236ac495dSmrg self._elem_type = elem_type.target() 67336ac495dSmrg else: 67436ac495dSmrg self._elem_type = elem_type 67536ac495dSmrg 67636ac495dSmrg def get_arg_types(self): 67736ac495dSmrg return None 67836ac495dSmrg 67936ac495dSmrg def get_result_type(self, obj): 68036ac495dSmrg return self._elem_type.pointer() 68136ac495dSmrg 68236ac495dSmrg def _supports(self, method_name): 68336ac495dSmrg "operator-> is not supported for shared_ptr<T[]>" 68436ac495dSmrg return method_name == 'get' or not self._is_array 68536ac495dSmrg 68636ac495dSmrg def __call__(self, obj): 68736ac495dSmrg return obj['_M_ptr'] 68836ac495dSmrg 68936ac495dSmrgclass SharedPtrDerefWorker(SharedPtrGetWorker): 69036ac495dSmrg "Implements std::shared_ptr<T>::operator*()" 69136ac495dSmrg 69236ac495dSmrg def __init__(self, elem_type): 69336ac495dSmrg SharedPtrGetWorker.__init__(self, elem_type) 69436ac495dSmrg 69536ac495dSmrg def get_result_type(self, obj): 69636ac495dSmrg return self._elem_type 69736ac495dSmrg 69836ac495dSmrg def _supports(self, method_name): 69936ac495dSmrg "operator* is not supported for shared_ptr<T[]>" 70036ac495dSmrg return not self._is_array 70136ac495dSmrg 70236ac495dSmrg def __call__(self, obj): 70336ac495dSmrg return SharedPtrGetWorker.__call__(self, obj).dereference() 70436ac495dSmrg 70536ac495dSmrgclass SharedPtrSubscriptWorker(SharedPtrGetWorker): 70636ac495dSmrg "Implements std::shared_ptr<T>::operator[](size_t)" 70736ac495dSmrg 70836ac495dSmrg def __init__(self, elem_type): 70936ac495dSmrg SharedPtrGetWorker.__init__(self, elem_type) 71036ac495dSmrg 71136ac495dSmrg def get_arg_types(self): 71236ac495dSmrg return get_std_size_type() 71336ac495dSmrg 71436ac495dSmrg def get_result_type(self, obj, index): 71536ac495dSmrg return self._elem_type 71636ac495dSmrg 71736ac495dSmrg def _supports(self, method_name): 71836ac495dSmrg "operator[] is only supported for shared_ptr<T[]>" 71936ac495dSmrg return self._is_array 72036ac495dSmrg 72136ac495dSmrg def __call__(self, obj, index): 72236ac495dSmrg # Check bounds if _elem_type is an array of known bound 72336ac495dSmrg m = re.match('.*\[(\d+)]$', str(self._elem_type)) 72436ac495dSmrg if m and index >= int(m.group(1)): 72536ac495dSmrg raise IndexError('shared_ptr<%s> index "%d" should not be >= %d.' % 72636ac495dSmrg (self._elem_type, int(index), int(m.group(1)))) 72736ac495dSmrg return SharedPtrGetWorker.__call__(self, obj)[index] 72836ac495dSmrg 72936ac495dSmrgclass SharedPtrUseCountWorker(gdb.xmethod.XMethodWorker): 73036ac495dSmrg "Implements std::shared_ptr<T>::use_count()" 73136ac495dSmrg 73236ac495dSmrg def __init__(self, elem_type): 733*23f5f463Smrg pass 73436ac495dSmrg 73536ac495dSmrg def get_arg_types(self): 73636ac495dSmrg return None 73736ac495dSmrg 73836ac495dSmrg def get_result_type(self, obj): 73936ac495dSmrg return gdb.lookup_type('long') 74036ac495dSmrg 741*23f5f463Smrg def _supports(self, method_name): 742*23f5f463Smrg return True 743*23f5f463Smrg 74436ac495dSmrg def __call__(self, obj): 745a2dc1f3fSmrg refcounts = obj['_M_refcount']['_M_pi'] 74636ac495dSmrg return refcounts['_M_use_count'] if refcounts else 0 74736ac495dSmrg 74836ac495dSmrgclass SharedPtrUniqueWorker(SharedPtrUseCountWorker): 74936ac495dSmrg "Implements std::shared_ptr<T>::unique()" 75036ac495dSmrg 75136ac495dSmrg def __init__(self, elem_type): 75236ac495dSmrg SharedPtrUseCountWorker.__init__(self, elem_type) 75336ac495dSmrg 75436ac495dSmrg def get_result_type(self, obj): 75536ac495dSmrg return gdb.lookup_type('bool') 75636ac495dSmrg 75736ac495dSmrg def __call__(self, obj): 75836ac495dSmrg return SharedPtrUseCountWorker.__call__(self, obj) == 1 75936ac495dSmrg 76036ac495dSmrgclass SharedPtrMethodsMatcher(gdb.xmethod.XMethodMatcher): 76136ac495dSmrg def __init__(self): 76236ac495dSmrg gdb.xmethod.XMethodMatcher.__init__(self, 76336ac495dSmrg matcher_name_prefix + 'shared_ptr') 76436ac495dSmrg self._method_dict = { 76536ac495dSmrg 'get': LibStdCxxXMethod('get', SharedPtrGetWorker), 76636ac495dSmrg 'operator->': LibStdCxxXMethod('operator->', SharedPtrGetWorker), 76736ac495dSmrg 'operator*': LibStdCxxXMethod('operator*', SharedPtrDerefWorker), 76836ac495dSmrg 'operator[]': LibStdCxxXMethod('operator[]', SharedPtrSubscriptWorker), 76936ac495dSmrg 'use_count': LibStdCxxXMethod('use_count', SharedPtrUseCountWorker), 77036ac495dSmrg 'unique': LibStdCxxXMethod('unique', SharedPtrUniqueWorker), 77136ac495dSmrg } 77236ac495dSmrg self.methods = [self._method_dict[m] for m in self._method_dict] 77336ac495dSmrg 77436ac495dSmrg def match(self, class_type, method_name): 77536ac495dSmrg if not re.match('^std::(__\d+::)?shared_ptr<.*>$', class_type.tag): 77636ac495dSmrg return None 77736ac495dSmrg method = self._method_dict.get(method_name) 77836ac495dSmrg if method is None or not method.enabled: 77936ac495dSmrg return None 78036ac495dSmrg worker = method.worker_class(class_type.template_argument(0)) 78136ac495dSmrg if worker._supports(method_name): 78236ac495dSmrg return worker 78336ac495dSmrg return None 78436ac495dSmrg 78536ac495dSmrgdef register_libstdcxx_xmethods(locus): 78636ac495dSmrg gdb.xmethod.register_xmethod_matcher(locus, ArrayMethodsMatcher()) 78736ac495dSmrg gdb.xmethod.register_xmethod_matcher(locus, ForwardListMethodsMatcher()) 78836ac495dSmrg gdb.xmethod.register_xmethod_matcher(locus, DequeMethodsMatcher()) 78936ac495dSmrg gdb.xmethod.register_xmethod_matcher(locus, ListMethodsMatcher()) 79036ac495dSmrg gdb.xmethod.register_xmethod_matcher(locus, VectorMethodsMatcher()) 79136ac495dSmrg gdb.xmethod.register_xmethod_matcher( 79236ac495dSmrg locus, AssociativeContainerMethodsMatcher('set')) 79336ac495dSmrg gdb.xmethod.register_xmethod_matcher( 79436ac495dSmrg locus, AssociativeContainerMethodsMatcher('map')) 79536ac495dSmrg gdb.xmethod.register_xmethod_matcher( 79636ac495dSmrg locus, AssociativeContainerMethodsMatcher('multiset')) 79736ac495dSmrg gdb.xmethod.register_xmethod_matcher( 79836ac495dSmrg locus, AssociativeContainerMethodsMatcher('multimap')) 79936ac495dSmrg gdb.xmethod.register_xmethod_matcher( 80036ac495dSmrg locus, AssociativeContainerMethodsMatcher('unordered_set')) 80136ac495dSmrg gdb.xmethod.register_xmethod_matcher( 80236ac495dSmrg locus, AssociativeContainerMethodsMatcher('unordered_map')) 80336ac495dSmrg gdb.xmethod.register_xmethod_matcher( 80436ac495dSmrg locus, AssociativeContainerMethodsMatcher('unordered_multiset')) 80536ac495dSmrg gdb.xmethod.register_xmethod_matcher( 80636ac495dSmrg locus, AssociativeContainerMethodsMatcher('unordered_multimap')) 80736ac495dSmrg gdb.xmethod.register_xmethod_matcher(locus, UniquePtrMethodsMatcher()) 80836ac495dSmrg gdb.xmethod.register_xmethod_matcher(locus, SharedPtrMethodsMatcher()) 809