| import lldb |
| |
| _map_capping_size = 255 |
| |
| |
| class libcxx_hash_table_SynthProvider: |
| |
| def __init__(self, valobj, dict): |
| self.valobj = valobj |
| self.num_elements = None |
| self.next_element = None |
| self.bucket_count = None |
| |
| def update(self): |
| logger = lldb.formatters.Logger.Logger() |
| self.num_elements = None |
| self.next_element = None |
| self.bucket_count = None |
| try: |
| # unordered_map is made up of a hash_map, which has 4 pieces in it: |
| # bucket list : |
| # array of buckets |
| # p1 (pair): |
| # first - pointer to first loaded element |
| # p2 (pair): |
| # first - number of elements |
| # second - hash function |
| # p3 (pair): |
| # first - max_load_factor |
| # second - equality operator function |
| # |
| # For display, we actually don't need to go inside the buckets, since 'p1' has a way to iterate over all |
| # the elements directly. |
| # |
| # We will calculate other values about the map because they will be useful for the summary. |
| # |
| table = self.valobj.GetChildMemberWithName('__table_') |
| |
| bl_ptr = table.GetChildMemberWithName( |
| '__bucket_list_').GetChildMemberWithName('__ptr_') |
| self.bucket_array_ptr = bl_ptr.GetChildMemberWithName( |
| '__first_').GetValueAsUnsigned(0) |
| self.bucket_count = bl_ptr.GetChildMemberWithName('__second_').GetChildMemberWithName( |
| '__data_').GetChildMemberWithName('__first_').GetValueAsUnsigned(0) |
| logger >> "Bucket count = %r" % self.bucket_count |
| |
| self.begin_ptr = table.GetChildMemberWithName('__p1_').GetChildMemberWithName( |
| '__first_').GetChildMemberWithName('__next_') |
| |
| self.num_elements = table.GetChildMemberWithName( |
| '__p2_').GetChildMemberWithName('__first_').GetValueAsUnsigned(0) |
| self.max_load_factor = table.GetChildMemberWithName( |
| '__p3_').GetChildMemberWithName('__first_').GetValueAsUnsigned(0) |
| logger >> "Num elements = %r" % self.num_elements |
| |
| # save the pointers as we get them |
| # -- don't access this first element if num_element==0! |
| self.elements_cache = [] |
| if self.num_elements: |
| self.next_element = self.begin_ptr |
| else: |
| self.next_element = None |
| except Exception as e: |
| logger >> "Caught exception: %r" % e |
| pass |
| |
| def num_children(self): |
| global _map_capping_size |
| num_elements = self.num_elements |
| if num_elements is not None: |
| if num_elements > _map_capping_size: |
| num_elements = _map_capping_size |
| return num_elements |
| |
| def has_children(self): |
| return True |
| |
| def get_child_index(self, name): |
| logger = lldb.formatters.Logger.Logger() |
| try: |
| return int(name.lstrip('[').rstrip(']')) |
| except: |
| return -1 |
| |
| def get_child_at_index(self, index): |
| logger = lldb.formatters.Logger.Logger() |
| logger >> "Retrieving child " + str(index) |
| if index < 0: |
| return None |
| if index >= self.num_children(): |
| return None |
| |
| # extend |
| logger >> " : cache size starts with %d elements" % len( |
| self.elements_cache) |
| while index >= len(self.elements_cache): |
| # if we hit the end before we get the index, give up: |
| if not self.next_element: |
| logger >> " : hit end of list" |
| return None |
| |
| node = self.next_element.Dereference() |
| |
| value = node.GetChildMemberWithName('__value_') |
| hash_value = node.GetChildMemberWithName( |
| '__hash_').GetValueAsUnsigned() |
| self.elements_cache.append((value, hash_value)) |
| |
| self.next_element = node.GetChildMemberWithName('__next_') |
| if not self.next_element.GetValueAsUnsigned(0): |
| self.next_element = None |
| |
| # hit the index! so we have the value |
| logger >> " : cache size ends with %d elements" % len( |
| self.elements_cache) |
| value, hash_value = self.elements_cache[index] |
| return self.valobj.CreateValueFromData( |
| '[%d] <hash %d>' % |
| (index, hash_value), value.GetData(), value.GetType()) |
| |
| |
| def __lldb_init_module(debugger, dict): |
| debugger.HandleCommand( |
| 'type synthetic add -l unordered_multi.libcxx_hash_table_SynthProvider -x "^(std::__1::)unordered_(multi)?(map|set)<.+> >$" -w libcxx') |