; LLDB support cleanup and extension
This commit is contained in:
parent
2071904d51
commit
c3038bf5e1
1 changed files with 65 additions and 48 deletions
|
|
@ -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)
|
||||
|
||||
|
||||
########################################################################
|
||||
|
|
@ -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))
|
||||
|
||||
|
||||
########################################################################
|
||||
# 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]
|
||||
|
||||
|
||||
########################################################################
|
||||
|
|
@ -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")
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue