This repository has been archived on 2024-12-16. You can view files and clone it, but cannot push or open issues or pull requests.
CodeBlocksPortable/MinGW/share/gcc-6.3.0/python/libstdcxx/v6/xmethods.py

632 lines
21 KiB
Python
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Xmethods for libstdc++.
# Copyright (C) 2014-2016 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import gdb
import gdb.xmethod
import re
matcher_name_prefix = 'libstdc++::'
def get_bool_type():
return gdb.lookup_type('bool')
def get_std_size_type():
return gdb.lookup_type('std::size_t')
class LibStdCxxXMethod(gdb.xmethod.XMethod):
def __init__(self, name, worker_class):
gdb.xmethod.XMethod.__init__(self, name)
self.worker_class = worker_class
# Xmethods for std::array
class ArrayWorkerBase(gdb.xmethod.XMethodWorker):
def __init__(self, val_type, size):
self._val_type = val_type
self._size = size
def null_value(self):
nullptr = gdb.parse_and_eval('(void *) 0')
return nullptr.cast(self._val_type.pointer()).dereference()
class ArraySizeWorker(ArrayWorkerBase):
def __init__(self, val_type, size):
ArrayWorkerBase.__init__(self, val_type, size)
def get_arg_types(self):
return None
def get_result_type(self, obj):
return get_std_size_type()
def __call__(self, obj):
return self._size
class ArrayEmptyWorker(ArrayWorkerBase):
def __init__(self, val_type, size):
ArrayWorkerBase.__init__(self, val_type, size)
def get_arg_types(self):
return None
def get_result_type(self, obj):
return get_bool_type()
def __call__(self, obj):
return (int(self._size) == 0)
class ArrayFrontWorker(ArrayWorkerBase):
def __init__(self, val_type, size):
ArrayWorkerBase.__init__(self, val_type, size)
def get_arg_types(self):
return None
def get_result_type(self, obj):
return self._val_type
def __call__(self, obj):
if int(self._size) > 0:
return obj['_M_elems'][0]
else:
return self.null_value()
class ArrayBackWorker(ArrayWorkerBase):
def __init__(self, val_type, size):
ArrayWorkerBase.__init__(self, val_type, size)
def get_arg_types(self):
return None
def get_result_type(self, obj):
return self._val_type
def __call__(self, obj):
if int(self._size) > 0:
return obj['_M_elems'][self._size - 1]
else:
return self.null_value()
class ArrayAtWorker(ArrayWorkerBase):
def __init__(self, val_type, size):
ArrayWorkerBase.__init__(self, val_type, size)
def get_arg_types(self):
return get_std_size_type()
def get_result_type(self, obj, index):
return self._val_type
def __call__(self, obj, index):
if int(index) >= int(self._size):
raise IndexError('Array index "%d" should not be >= %d.' %
((int(index), self._size)))
return obj['_M_elems'][index]
class ArraySubscriptWorker(ArrayWorkerBase):
def __init__(self, val_type, size):
ArrayWorkerBase.__init__(self, val_type, size)
def get_arg_types(self):
return get_std_size_type()
def get_result_type(self, obj, index):
return self._val_type
def __call__(self, obj, index):
if int(self._size) > 0:
return obj['_M_elems'][index]
else:
return self.null_value()
class ArrayMethodsMatcher(gdb.xmethod.XMethodMatcher):
def __init__(self):
gdb.xmethod.XMethodMatcher.__init__(self,
matcher_name_prefix + 'array')
self._method_dict = {
'size': LibStdCxxXMethod('size', ArraySizeWorker),
'empty': LibStdCxxXMethod('empty', ArrayEmptyWorker),
'front': LibStdCxxXMethod('front', ArrayFrontWorker),
'back': LibStdCxxXMethod('back', ArrayBackWorker),
'at': LibStdCxxXMethod('at', ArrayAtWorker),
'operator[]': LibStdCxxXMethod('operator[]', ArraySubscriptWorker),
}
self.methods = [self._method_dict[m] for m in self._method_dict]
def match(self, class_type, method_name):
if not re.match('^std::array<.*>$', class_type.tag):
return None
method = self._method_dict.get(method_name)
if method is None or not method.enabled:
return None
try:
value_type = class_type.template_argument(0)
size = class_type.template_argument(1)
except:
return None
return method.worker_class(value_type, size)
# Xmethods for std::deque
class DequeWorkerBase(gdb.xmethod.XMethodWorker):
def __init__(self, val_type):
self._val_type = val_type
self._bufsize = 512 // val_type.sizeof or 1
def size(self, obj):
first_node = obj['_M_impl']['_M_start']['_M_node']
last_node = obj['_M_impl']['_M_finish']['_M_node']
cur = obj['_M_impl']['_M_finish']['_M_cur']
first = obj['_M_impl']['_M_finish']['_M_first']
return (last_node - first_node) * self._bufsize + (cur - first)
def index(self, obj, idx):
first_node = obj['_M_impl']['_M_start']['_M_node']
index_node = first_node + int(idx) // self._bufsize
return index_node[0][idx % self._bufsize]
class DequeEmptyWorker(DequeWorkerBase):
def get_arg_types(self):
return None
def get_result_type(self, obj):
return get_bool_type()
def __call__(self, obj):
return (obj['_M_impl']['_M_start']['_M_cur'] ==
obj['_M_impl']['_M_finish']['_M_cur'])
class DequeSizeWorker(DequeWorkerBase):
def get_arg_types(self):
return None
def get_result_type(self, obj):
return get_std_size_type()
def __call__(self, obj):
return self.size(obj)
class DequeFrontWorker(DequeWorkerBase):
def get_arg_types(self):
return None
def get_result_type(self, obj):
return self._val_type
def __call__(self, obj):
return obj['_M_impl']['_M_start']['_M_cur'][0]
class DequeBackWorker(DequeWorkerBase):
def get_arg_types(self):
return None
def get_result_type(self, obj):
return self._val_type
def __call__(self, obj):
if (obj['_M_impl']['_M_finish']['_M_cur'] ==
obj['_M_impl']['_M_finish']['_M_first']):
prev_node = obj['_M_impl']['_M_finish']['_M_node'] - 1
return prev_node[0][self._bufsize - 1]
else:
return obj['_M_impl']['_M_finish']['_M_cur'][-1]
class DequeSubscriptWorker(DequeWorkerBase):
def get_arg_types(self):
return get_std_size_type()
def get_result_type(self, obj, subscript):
return self._val_type
def __call__(self, obj, subscript):
return self.index(obj, subscript)
class DequeAtWorker(DequeWorkerBase):
def get_arg_types(self):
return get_std_size_type()
def get_result_type(self, obj, index):
return self._val_type
def __call__(self, obj, index):
deque_size = int(self.size(obj))
if int(index) >= deque_size:
raise IndexError('Deque index "%d" should not be >= %d.' %
(int(index), deque_size))
else:
return self.index(obj, index)
class DequeMethodsMatcher(gdb.xmethod.XMethodMatcher):
def __init__(self):
gdb.xmethod.XMethodMatcher.__init__(self,
matcher_name_prefix + 'deque')
self._method_dict = {
'empty': LibStdCxxXMethod('empty', DequeEmptyWorker),
'size': LibStdCxxXMethod('size', DequeSizeWorker),
'front': LibStdCxxXMethod('front', DequeFrontWorker),
'back': LibStdCxxXMethod('back', DequeBackWorker),
'operator[]': LibStdCxxXMethod('operator[]', DequeSubscriptWorker),
'at': LibStdCxxXMethod('at', DequeAtWorker)
}
self.methods = [self._method_dict[m] for m in self._method_dict]
def match(self, class_type, method_name):
if not re.match('^std::deque<.*>$', class_type.tag):
return None
method = self._method_dict.get(method_name)
if method is None or not method.enabled:
return None
return method.worker_class(class_type.template_argument(0))
# Xmethods for std::forward_list
class ForwardListWorkerBase(gdb.xmethod.XMethodMatcher):
def __init__(self, val_type, node_type):
self._val_type = val_type
self._node_type = node_type
def get_arg_types(self):
return None
class ForwardListEmptyWorker(ForwardListWorkerBase):
def get_result_type(self, obj):
return get_bool_type()
def __call__(self, obj):
return obj['_M_impl']['_M_head']['_M_next'] == 0
class ForwardListFrontWorker(ForwardListWorkerBase):
def get_result_type(self, obj):
return self._val_type
def __call__(self, obj):
node = obj['_M_impl']['_M_head']['_M_next'].cast(self._node_type)
val_address = node['_M_storage']['_M_storage'].address
return val_address.cast(self._val_type.pointer()).dereference()
class ForwardListMethodsMatcher(gdb.xmethod.XMethodMatcher):
def __init__(self):
matcher_name = matcher_name_prefix + 'forward_list'
gdb.xmethod.XMethodMatcher.__init__(self, matcher_name)
self._method_dict = {
'empty': LibStdCxxXMethod('empty', ForwardListEmptyWorker),
'front': LibStdCxxXMethod('front', ForwardListFrontWorker)
}
self.methods = [self._method_dict[m] for m in self._method_dict]
def match(self, class_type, method_name):
if not re.match('^std::forward_list<.*>$', class_type.tag):
return None
method = self._method_dict.get(method_name)
if method is None or not method.enabled:
return None
val_type = class_type.template_argument(0)
node_type = gdb.lookup_type(str(class_type) + '::_Node').pointer()
return method.worker_class(val_type, node_type)
# Xmethods for std::list
class ListWorkerBase(gdb.xmethod.XMethodWorker):
def __init__(self, val_type, node_type):
self._val_type = val_type
self._node_type = node_type
def get_arg_types(self):
return None
def get_value_from_node(self, node):
node = node.dereference()
if node.type.fields()[1].name == '_M_data':
# C++03 implementation, node contains the value as a member
return node['_M_data']
# C++11 implementation, node stores value in __aligned_membuf
addr = node['_M_storage'].address
return addr.cast(self._val_type.pointer()).dereference()
class ListEmptyWorker(ListWorkerBase):
def get_result_type(self, obj):
return get_bool_type()
def __call__(self, obj):
base_node = obj['_M_impl']['_M_node']
if base_node['_M_next'] == base_node.address:
return True
else:
return False
class ListSizeWorker(ListWorkerBase):
def get_result_type(self, obj):
return get_std_size_type()
def __call__(self, obj):
begin_node = obj['_M_impl']['_M_node']['_M_next']
end_node = obj['_M_impl']['_M_node'].address
size = 0
while begin_node != end_node:
begin_node = begin_node['_M_next']
size += 1
return size
class ListFrontWorker(ListWorkerBase):
def get_result_type(self, obj):
return self._val_type
def __call__(self, obj):
node = obj['_M_impl']['_M_node']['_M_next'].cast(self._node_type)
return self.get_value_from_node(node)
class ListBackWorker(ListWorkerBase):
def get_result_type(self, obj):
return self._val_type
def __call__(self, obj):
prev_node = obj['_M_impl']['_M_node']['_M_prev'].cast(self._node_type)
return self.get_value_from_node(prev_node)
class ListMethodsMatcher(gdb.xmethod.XMethodMatcher):
def __init__(self):
gdb.xmethod.XMethodMatcher.__init__(self,
matcher_name_prefix + 'list')
self._method_dict = {
'empty': LibStdCxxXMethod('empty', ListEmptyWorker),
'size': LibStdCxxXMethod('size', ListSizeWorker),
'front': LibStdCxxXMethod('front', ListFrontWorker),
'back': LibStdCxxXMethod('back', ListBackWorker)
}
self.methods = [self._method_dict[m] for m in self._method_dict]
def match(self, class_type, method_name):
if not re.match('^std::(__cxx11::)?list<.*>$', class_type.tag):
return None
method = self._method_dict.get(method_name)
if method is None or not method.enabled:
return None
val_type = class_type.template_argument(0)
node_type = gdb.lookup_type(str(class_type) + '::_Node').pointer()
return method.worker_class(val_type, node_type)
# Xmethods for std::vector
class VectorWorkerBase(gdb.xmethod.XMethodWorker):
def __init__(self, val_type):
self._val_type = val_type
def size(self, obj):
if self._val_type.code == gdb.TYPE_CODE_BOOL:
start = obj['_M_impl']['_M_start']['_M_p']
finish = obj['_M_impl']['_M_finish']['_M_p']
finish_offset = obj['_M_impl']['_M_finish']['_M_offset']
bit_size = start.dereference().type.sizeof * 8
return (finish - start) * bit_size + finish_offset
else:
return obj['_M_impl']['_M_finish'] - obj['_M_impl']['_M_start']
def get(self, obj, index):
if self._val_type.code == gdb.TYPE_CODE_BOOL:
start = obj['_M_impl']['_M_start']['_M_p']
bit_size = start.dereference().type.sizeof * 8
valp = start + index // bit_size
offset = index % bit_size
return (valp.dereference() & (1 << offset)) > 0
else:
return obj['_M_impl']['_M_start'][index]
class VectorEmptyWorker(VectorWorkerBase):
def get_arg_types(self):
return None
def get_result_type(self, obj):
return get_bool_type()
def __call__(self, obj):
return int(self.size(obj)) == 0
class VectorSizeWorker(VectorWorkerBase):
def get_arg_types(self):
return None
def get_result_type(self, obj):
return get_std_size_type()
def __call__(self, obj):
return self.size(obj)
class VectorFrontWorker(VectorWorkerBase):
def get_arg_types(self):
return None
def get_result_type(self, obj):
return self._val_type
def __call__(self, obj):
return self.get(obj, 0)
class VectorBackWorker(VectorWorkerBase):
def get_arg_types(self):
return None
def get_result_type(self, obj):
return self._val_type
def __call__(self, obj):
return self.get(obj, int(self.size(obj)) - 1)
class VectorAtWorker(VectorWorkerBase):
def get_arg_types(self):
return get_std_size_type()
def get_result_type(self, obj, index):
return self._val_type
def __call__(self, obj, index):
size = int(self.size(obj))
if int(index) >= size:
raise IndexError('Vector index "%d" should not be >= %d.' %
((int(index), size)))
return self.get(obj, int(index))
class VectorSubscriptWorker(VectorWorkerBase):
def get_arg_types(self):
return get_std_size_type()
def get_result_type(self, obj, subscript):
return self._val_type
def __call__(self, obj, subscript):
return self.get(obj, int(subscript))
class VectorMethodsMatcher(gdb.xmethod.XMethodMatcher):
def __init__(self):
gdb.xmethod.XMethodMatcher.__init__(self,
matcher_name_prefix + 'vector')
self._method_dict = {
'size': LibStdCxxXMethod('size', VectorSizeWorker),
'empty': LibStdCxxXMethod('empty', VectorEmptyWorker),
'front': LibStdCxxXMethod('front', VectorFrontWorker),
'back': LibStdCxxXMethod('back', VectorBackWorker),
'at': LibStdCxxXMethod('at', VectorAtWorker),
'operator[]': LibStdCxxXMethod('operator[]',
VectorSubscriptWorker),
}
self.methods = [self._method_dict[m] for m in self._method_dict]
def match(self, class_type, method_name):
if not re.match('^std::vector<.*>$', class_type.tag):
return None
method = self._method_dict.get(method_name)
if method is None or not method.enabled:
return None
return method.worker_class(class_type.template_argument(0))
# Xmethods for associative containers
class AssociativeContainerWorkerBase(gdb.xmethod.XMethodWorker):
def __init__(self, unordered):
self._unordered = unordered
def node_count(self, obj):
if self._unordered:
return obj['_M_h']['_M_element_count']
else:
return obj['_M_t']['_M_impl']['_M_node_count']
def get_arg_types(self):
return None
class AssociativeContainerEmptyWorker(AssociativeContainerWorkerBase):
def get_result_type(self, obj):
return get_bool_type()
def __call__(self, obj):
return int(self.node_count(obj)) == 0
class AssociativeContainerSizeWorker(AssociativeContainerWorkerBase):
def get_result_type(self, obj):
return get_std_size_type()
def __call__(self, obj):
return self.node_count(obj)
class AssociativeContainerMethodsMatcher(gdb.xmethod.XMethodMatcher):
def __init__(self, name):
gdb.xmethod.XMethodMatcher.__init__(self,
matcher_name_prefix + name)
self._name = name
self._method_dict = {
'size': LibStdCxxXMethod('size', AssociativeContainerSizeWorker),
'empty': LibStdCxxXMethod('empty',
AssociativeContainerEmptyWorker),
}
self.methods = [self._method_dict[m] for m in self._method_dict]
def match(self, class_type, method_name):
if not re.match('^std::%s<.*>$' % self._name, class_type.tag):
return None
method = self._method_dict.get(method_name)
if method is None or not method.enabled:
return None
unordered = 'unordered' in self._name
return method.worker_class(unordered)
# Xmethods for std::unique_ptr
class UniquePtrGetWorker(gdb.xmethod.XMethodWorker):
def __init__(self, elem_type):
self._elem_type = elem_type
def get_arg_types(self):
return None
def get_result_type(self, obj):
return self._elem_type.pointer()
def __call__(self, obj):
return obj['_M_t']['_M_head_impl']
class UniquePtrDerefWorker(UniquePtrGetWorker):
def __init__(self, elem_type):
UniquePtrGetWorker.__init__(self, elem_type)
def get_result_type(self, obj):
return self._elem_type
def __call__(self, obj):
return UniquePtrGetWorker.__call__(self, obj).dereference()
class UniquePtrMethodsMatcher(gdb.xmethod.XMethodMatcher):
def __init__(self):
gdb.xmethod.XMethodMatcher.__init__(self,
matcher_name_prefix + 'unique_ptr')
self._method_dict = {
'get': LibStdCxxXMethod('get', UniquePtrGetWorker),
'operator->': LibStdCxxXMethod('operator->', UniquePtrGetWorker),
'operator*': LibStdCxxXMethod('operator*', UniquePtrDerefWorker),
}
self.methods = [self._method_dict[m] for m in self._method_dict]
def match(self, class_type, method_name):
if not re.match('^std::unique_ptr<.*>$', class_type.tag):
return None
method = self._method_dict.get(method_name)
if method is None or not method.enabled:
return None
return method.worker_class(class_type.template_argument(0))
def register_libstdcxx_xmethods(locus):
gdb.xmethod.register_xmethod_matcher(locus, ArrayMethodsMatcher())
gdb.xmethod.register_xmethod_matcher(locus, ForwardListMethodsMatcher())
gdb.xmethod.register_xmethod_matcher(locus, DequeMethodsMatcher())
gdb.xmethod.register_xmethod_matcher(locus, ListMethodsMatcher())
gdb.xmethod.register_xmethod_matcher(locus, VectorMethodsMatcher())
gdb.xmethod.register_xmethod_matcher(
locus, AssociativeContainerMethodsMatcher('set'))
gdb.xmethod.register_xmethod_matcher(
locus, AssociativeContainerMethodsMatcher('map'))
gdb.xmethod.register_xmethod_matcher(
locus, AssociativeContainerMethodsMatcher('multiset'))
gdb.xmethod.register_xmethod_matcher(
locus, AssociativeContainerMethodsMatcher('multimap'))
gdb.xmethod.register_xmethod_matcher(
locus, AssociativeContainerMethodsMatcher('unordered_set'))
gdb.xmethod.register_xmethod_matcher(
locus, AssociativeContainerMethodsMatcher('unordered_map'))
gdb.xmethod.register_xmethod_matcher(
locus, AssociativeContainerMethodsMatcher('unordered_multiset'))
gdb.xmethod.register_xmethod_matcher(
locus, AssociativeContainerMethodsMatcher('unordered_multimap'))
gdb.xmethod.register_xmethod_matcher(locus, UniquePtrMethodsMatcher())