diff lldb/examples/synthetic/unordered_multi.py @ 150:1d019706d866

LLVM10
author anatofuz
date Thu, 13 Feb 2020 15:10:13 +0900
parents
children 1f2b6ac9f198
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lldb/examples/synthetic/unordered_multi.py	Thu Feb 13 15:10:13 2020 +0900
@@ -0,0 +1,124 @@
+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')