xref: /netbsd-src/external/gpl3/gcc.old/dist/libstdc++-v3/python/libstdcxx/v6/xmethods.py (revision 23f5f46327e37e7811da3520f4bb933f9489322f)
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