]> git.eshelyaron.com Git - emacs.git/commitdiff
; LLDB support cleanup and extension
authorGerd Möllmann <gerd.moellmann@gmail.com>
Mon, 16 Oct 2023 08:12:10 +0000 (10:12 +0200)
committerGerd Möllmann <gerd.moellmann@gmail.com>
Mon, 16 Oct 2023 08:14:19 +0000 (10:14 +0200)
etc/emacs_lldb.py

index 24b127a1fb9647440b99ebe7b04adf2f3015299d..a4f066b79decb8e92b8cb7f9a0c6b7880d57d369 100644 (file)
@@ -78,22 +78,22 @@ class Lisp_Object:
 
     # Object construction/initialization.
     def __init__(self, lisp_obj):
-        self.lisp_obj = lisp_obj
-        self.frame = lisp_obj.GetFrame()
+        self.tagged = lisp_obj
+        self.unsigned = None
         self.lisp_type = None
         self.pvec_type = None
-        self.value = None
+        self.untagged = None
         self.init_unsigned()
         self.init_lisp_types()
         self.init_values()
 
     def init_unsigned(self):
-        if self.lisp_obj.GetType().GetTypeClass() == lldb.eTypeClassStruct:
+        if self.tagged.GetType().GetTypeClass() == lldb.eTypeClassStruct:
             # Lisp_Object is actually a struct.
-            lisp_word = self.lisp_obj.GetValueForExpressionPath(".i")
+            lisp_word = self.tagged.GetValueForExpressionPath(".i")
             self.unsigned = lisp_word.GetValueAsUnsigned()
         else:
-            self.unsigned = self.lisp_obj.GetValueAsUnsigned()
+            self.unsigned = self.tagged.GetValueAsUnsigned()
 
     # Initialize self.lisp_type to the C Lisp_Type enumerator of the
     # Lisp_Object, as a string.  Initialize self.pvec_type likewise to
@@ -117,40 +117,38 @@ class Lisp_Object:
                     f">> More_Lisp_Bits::PSEUDOVECTOR_AREA_BITS)")
                 self.pvec_type = enumerator_name(typ)
 
-    # Initialize self.value according to lisp_type and pvec_type.
+    # Initialize self.untagged according to lisp_type and pvec_type.
     def init_values(self):
         if self.lisp_type == "Lisp_Symbol":
             offset = self.get_lisp_pointer("char").GetValueAsUnsigned()
-            self.value = self.eval(f"(struct Lisp_Symbol *)"
+            self.untagged = self.eval(f"(struct Lisp_Symbol *)"
                                    f" ((char *) &lispsym + {offset})",
                                    True)
         elif self.lisp_type == "Lisp_String":
-            self.value = self.get_lisp_pointer("struct Lisp_String", True)
+            self.untagged = self.get_lisp_pointer("struct Lisp_String", True)
         elif self.lisp_type == "Lisp_Vectorlike":
             c_type = Lisp_Object.pvec2type[self.pvec_type]
-            self.value = self.get_lisp_pointer(c_type, True)
+            self.untagged = self.get_lisp_pointer(c_type, True)
         elif self.lisp_type == "Lisp_Cons":
-            self.value = self.get_lisp_pointer("struct Lisp_Cons", True)
+            self.untagged = self.get_lisp_pointer("struct Lisp_Cons", True)
         elif self.lisp_type == "Lisp_Float":
-            self.value = self.get_lisp_pointer("struct Lisp_Float", True)
+            self.untagged = self.get_lisp_pointer("struct Lisp_Float", True)
         elif self.lisp_type in ("Lisp_Int0", "Lisp_Int1"):
-            self.value = self.eval(f"((EMACS_INT) {self.unsigned}) "
-                                   f">> (GCTYPEBITS - 1)",
-                                   True)
+            self.untagged = self.eval(f"((EMACS_INT) {self.unsigned}) "
+                                      f">> (GCTYPEBITS - 1)", True)
+        elif self.lisp_type == "Lisp_Type_Unused0":
+            self.untagged = self.unsigned
         else:
-            assert False, "Unknown Lisp type"
-
-    # Create an SBValue for EXPR with name NAME.
-    def create_value(self, name, expr):
-        return self.lisp_obj.CreateValueFromExpression(name, expr)
+            assert False, f"Unknown Lisp type {self.lisp_type}"
 
     # Evaluate EXPR in the context of the current frame.
     def eval(self, expr, make_var=False):
+        frame = self.tagged.GetFrame()
         if make_var:
-            return self.frame.EvaluateExpression(expr)
+            return frame.EvaluateExpression(expr)
         options = lldb.SBExpressionOptions()
         options.SetSuppressPersistentResult(True)
-        return self.frame.EvaluateExpression(expr, options)
+        return frame.EvaluateExpression(expr, options)
 
     # Return an SBValue for this object denoting a pointer of type
     # TYP*.
@@ -163,20 +161,20 @@ class Lisp_Object:
     # Return None otherwise.
     def get_string_data(self):
         if self.lisp_type == "Lisp_String":
-            return self.value.GetValueForExpressionPath("->u.s.data")
+            return self.untagged.GetValueForExpressionPath("->u.s.data")
         return None
 
     # if this is a Lisp_Symbol, return an SBBalue for its name.
     # Return None otherwise.
     def get_symbol_name(self):
         if self.lisp_type == "Lisp_Symbol":
-            name = self.value.GetValueForExpressionPath("->u.s.name")
+            name = self.untagged.GetValueForExpressionPath("->u.s.name")
             return Lisp_Object(name).get_string_data()
         return None
 
     # Return a summary string for this object.
     def summary(self):
-        return str(self.value)
+        return str(self.untagged)
 
 \f
 ########################################################################
@@ -205,6 +203,15 @@ def xdebug_print(debugger, command, result, internal_dict):
     """Print Lisp_Objects using safe_debug_print()"""
     debugger.HandleCommand(f"expr safe_debug_print({command})")
 
+def xcomplete(debugger, command, result, internal_dict):
+    """Print completions for COMMAND."""
+    interpreter = debugger.GetCommandInterpreter()
+    string_list = lldb.SBStringList()
+    interpreter.HandleCompletion(command, len(command), len(command),
+                                 -1, string_list)
+    for i in range(string_list.GetSize()):
+        result.AppendMessage(string_list.GetStringAtIndex(i))
+
 \f
 ########################################################################
 #                             Formatters
@@ -213,40 +220,49 @@ def xdebug_print(debugger, command, result, internal_dict):
 def type_summary_Lisp_Object(obj, internal_dict):
     return Lisp_Object(obj).summary()
 
-# Don't know at the moment how to use this outside of the LLDB gui
-# command.  And it's still incomplete.
 class Lisp_Object_Provider:
+    """Synthetic children provider for Lisp_Objects.
+    Supposedly only used by 'frame variable', where -P <n> can be used
+    to specify a printing depth. """
     def __init__(self, valobj, internal_dict):
         self.valobj = valobj
-        self.lisp_obj = Lisp_Object(valobj)
-        self.child = None
+        self.children = {}
 
     def update(self):
-        if self.lisp_obj.lisp_type == "Lisp_Symbol":
-            self.child = self.lisp_obj.get_symbol_name().Clone("name")
-            self.child.SetSyntheticChildGenerated(True)
-        elif self.lisp_obj.lisp_type == "Lisp_String":
-            self.child = self.lisp_obj.get_string_data().Clone("data")
-            self.child.SetSyntheticChildGenerated(True)
-        else:
-            self.child = self.lisp_obj.value.Clone("untagged")
-            self.child.SetSyntheticChildGenerated(True)
-
-    def has_children(self):
-        return True
+        lisp_obj = Lisp_Object(self.valobj)
+        lisp_type = lisp_obj.lisp_type
+        try:
+            if lisp_type == "Lisp_Symbol":
+                child = lisp_obj.get_symbol_name()
+                self.children["name"] = child
+            elif lisp_type == "Lisp_String":
+                child = lisp_obj.get_string_data()
+                self.children["data"] = child
+            elif lisp_type == "Lisp_Cons":
+                car = lisp_obj.untagged.GetValueForExpressionPath("->u.s.car")
+                cdr = lisp_obj.untagged.GetValueForExpressionPath("->u.s.u.cdr")
+                self.children["car"] = car
+                self.children["cdr"] = cdr
+            else:
+                self.children["untagged"] = lisp_obj.untagged
+        except:
+            print(f"*** exception in child provider update for {lisp_type}")
+            pass
 
     def num_children(self):
-        return 1
+        return len(self.children)
 
     def get_child_index(self, name):
-        return 0
+        index = 0
+        for child_name, child in self.children:
+            if child_name == name:
+                return index
+            index = index + 1
+        return -1
 
-    # This works insofar as struct frame * works, but it doesn't work
-    # Lisp_Symbol, for example.
     def get_child_at_index(self, index):
-        if index != 0:
-            return None
-        return self.child
+        key = list(self.children)[index]
+        return self.children[key]
 
 \f
 ########################################################################
@@ -300,6 +316,7 @@ def enable_type_category(debugger, category):
 def __lldb_init_module(debugger, internal_dict):
     define_command(debugger, xbacktrace)
     define_command(debugger, xdebug_print)
+    define_command(debugger, xcomplete)
     define_type_summary(debugger, "Lisp_Object", type_summary_Lisp_Object)
     define_type_synthetic(debugger, "Lisp_Object", Lisp_Object_Provider)
     enable_type_category(debugger, "Emacs")