137 lines · python
1import lldb2 3_map_capping_size = 2554 5 6class libcxx_hash_table_SynthProvider:7 def __init__(self, valobj, dict):8 self.valobj = valobj9 self.num_elements = None10 self.next_element = None11 self.bucket_count = None12 13 def update(self):14 logger = lldb.formatters.Logger.Logger()15 self.num_elements = None16 self.next_element = None17 self.bucket_count = None18 try:19 # unordered_map is made up of a hash_map, which has 4 pieces in it:20 # bucket list :21 # array of buckets22 # p1 (pair):23 # first - pointer to first loaded element24 # p2 (pair):25 # first - number of elements26 # second - hash function27 # p3 (pair):28 # first - max_load_factor29 # second - equality operator function30 #31 # For display, we actually don't need to go inside the buckets, since 'p1' has a way to iterate over all32 # the elements directly.33 #34 # We will calculate other values about the map because they will be useful for the summary.35 #36 table = self.valobj.GetChildMemberWithName("__table_")37 38 bl_ptr = table.GetChildMemberWithName(39 "__bucket_list_"40 ).GetChildMemberWithName("__ptr_")41 self.bucket_array_ptr = bl_ptr.GetChildMemberWithName(42 "__first_"43 ).GetValueAsUnsigned(0)44 self.bucket_count = (45 bl_ptr.GetChildMemberWithName("__second_")46 .GetChildMemberWithName("__data_")47 .GetChildMemberWithName("__first_")48 .GetValueAsUnsigned(0)49 )50 logger >> "Bucket count = %r" % self.bucket_count51 52 self.begin_ptr = (53 table.GetChildMemberWithName("__p1_")54 .GetChildMemberWithName("__first_")55 .GetChildMemberWithName("__next_")56 )57 58 self.num_elements = (59 table.GetChildMemberWithName("__p2_")60 .GetChildMemberWithName("__first_")61 .GetValueAsUnsigned(0)62 )63 self.max_load_factor = (64 table.GetChildMemberWithName("__p3_")65 .GetChildMemberWithName("__first_")66 .GetValueAsUnsigned(0)67 )68 logger >> "Num elements = %r" % self.num_elements69 70 # save the pointers as we get them71 # -- don't access this first element if num_element==0!72 self.elements_cache = []73 if self.num_elements:74 self.next_element = self.begin_ptr75 else:76 self.next_element = None77 except Exception as e:78 logger >> "Caught exception: %r" % e79 pass80 81 def num_children(self):82 global _map_capping_size83 num_elements = self.num_elements84 if num_elements is not None:85 if num_elements > _map_capping_size:86 num_elements = _map_capping_size87 return num_elements88 89 def has_children(self):90 return True91 92 def get_child_index(self, name):93 logger = lldb.formatters.Logger.Logger()94 try:95 return int(name.lstrip("[").rstrip("]"))96 except:97 return -198 99 def get_child_at_index(self, index):100 logger = lldb.formatters.Logger.Logger()101 logger >> "Retrieving child " + str(index)102 if index < 0:103 return None104 if index >= self.num_children():105 return None106 107 # extend108 logger >> " : cache size starts with %d elements" % len(self.elements_cache)109 while index >= len(self.elements_cache):110 # if we hit the end before we get the index, give up:111 if not self.next_element:112 logger >> " : hit end of list"113 return None114 115 node = self.next_element.Dereference()116 117 value = node.GetChildMemberWithName("__value_")118 hash_value = node.GetChildMemberWithName("__hash_").GetValueAsUnsigned()119 self.elements_cache.append((value, hash_value))120 121 self.next_element = node.GetChildMemberWithName("__next_")122 if not self.next_element.GetValueAsUnsigned(0):123 self.next_element = None124 125 # hit the index! so we have the value126 logger >> " : cache size ends with %d elements" % len(self.elements_cache)127 value, hash_value = self.elements_cache[index]128 return self.valobj.CreateValueFromData(129 "[%d] <hash %d>" % (index, hash_value), value.GetData(), value.GetType()130 )131 132 133def __lldb_init_module(debugger, dict):134 debugger.HandleCommand(135 'type synthetic add -l unordered_multi.libcxx_hash_table_SynthProvider -x "^(std::__1::)unordered_(multi)?(map|set)<.+> >$" -w libcxx'136 )137