forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			125 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			125 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			Python
		
	
	
	
| 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')
 |