2024-01-02 09:47:10 +08:00
|
|
|
|
# Copyright (C) 2022-2024 Free Software Foundation, Inc.
|
2022-07-10 13:35:32 +02:00
|
|
|
|
#
|
|
|
|
|
# This file is part of GNU Emacs.
|
|
|
|
|
#
|
|
|
|
|
# GNU Emacs is free software; you can redistribute it and/or modify
|
|
|
|
|
# it under the terms of the GNU General Public License as published by
|
|
|
|
|
# the Free Software Foundation; either version 3, or (at your option)
|
|
|
|
|
# any later version.
|
|
|
|
|
#
|
|
|
|
|
# GNU Emacs is distributed in the hope that it will be useful,
|
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
# GNU General Public License for more details.
|
|
|
|
|
#
|
|
|
|
|
# You should have received a copy of the GNU General Public License
|
|
|
|
|
# along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
|
|
# Load this module in LLDB with
|
|
|
|
|
#
|
|
|
|
|
# (lldb) command script import emacs_lldb
|
|
|
|
|
#
|
|
|
|
|
# Available commands start with 'x' and can be seen with
|
|
|
|
|
#
|
|
|
|
|
# (lldb) help
|
|
|
|
|
|
|
|
|
|
import lldb
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
########################################################################
|
2022-07-14 12:43:52 +02:00
|
|
|
|
# Utilities
|
2022-07-10 13:35:32 +02:00
|
|
|
|
########################################################################
|
|
|
|
|
|
2022-07-12 12:29:14 +02:00
|
|
|
|
# Return the name of enumerator ENUM as a string.
|
2022-07-10 13:35:32 +02:00
|
|
|
|
def enumerator_name(enum):
|
|
|
|
|
enumerators = enum.GetType().GetEnumMembers()
|
2022-08-22 11:18:30 +02:00
|
|
|
|
for enum_member in enumerators:
|
|
|
|
|
if enum.GetValueAsUnsigned() == enum_member.GetValueAsUnsigned():
|
|
|
|
|
return enum_member.GetName()
|
|
|
|
|
return None
|
2022-07-10 13:35:32 +02:00
|
|
|
|
|
2022-07-12 12:29:14 +02:00
|
|
|
|
# A class wrapping an SBValue for a Lisp_Object, providing convenience
|
|
|
|
|
# functions.
|
|
|
|
|
class Lisp_Object:
|
|
|
|
|
# Map pvec_type enumerators to corresponding C types.
|
|
|
|
|
pvec2type = {
|
|
|
|
|
"PVEC_FRAME": "struct frame",
|
|
|
|
|
"PVEC_WINDOW": "struct window",
|
|
|
|
|
"PVEC_BIGNUM": "struct Lisp_Bignum",
|
|
|
|
|
"PVEC_MARKER": "struct Lisp_Marker",
|
|
|
|
|
"PVEC_OVERLAY": "struct Lisp_Overlay",
|
|
|
|
|
"PVEC_FINALIZER": "struct Lisp_Finalizer",
|
|
|
|
|
"PVEC_SYMBOL_WITH_POS": "struct Lisp_Symbol_With_Pos",
|
|
|
|
|
"PVEC_MISC_PTR": "",
|
|
|
|
|
"PVEC_USER_PTR": "struct Lisp_User_Ptr",
|
|
|
|
|
"PVEC_PROCESS": "struct Lisp_Process",
|
|
|
|
|
"PVEC_BOOL_VECTOR": "struct Lisp_Bool_Vector",
|
|
|
|
|
"PVEC_BUFFER": "struct buffer",
|
|
|
|
|
"PVEC_HASH_TABLE": "struct Lisp_Hash_Table",
|
Add a proper type for obarrays
The new opaque type replaces the previous use of vectors for obarrays.
`obarray-make` now returns objects of this type. Functions that take
obarrays continue to accept vectors for compatibility, now just using
their first slot to store an actual obarray object.
obarray-size and obarray-default-size now obsolete.
* lisp/obarray.el (obarray-default-size, obarray-size):
Declare obsolete.
(obarray-make, obarrayp, obarray-clear): Remove from here.
* src/fns.c (reduce_emacs_uint_to_hash_hash): Remove from here.
* src/lisp.h (struct Lisp_Obarray, OBARRAYP, XOBARRAY, CHECK_OBARRAY)
(make_lisp_obarray, obarray_size, check_obarray)
(obarray_iter_t, make_obarray_iter, obarray_iter_at_end)
(obarray_iter_step, obarray_iter_symbol, DOOBARRAY, knuth_hash): New.
(reduce_emacs_uint_to_hash_hash): Moved here.
* src/lread.c (check_obarray): Renamed and reworked as...
(checked_obarray_slow): ...this.
(intern_sym, Funintern, oblookup, map_obarray)
(Finternal__obarray_buckets): Adapt to new type.
(obarray_index, allocate_obarray, make_obarray, grow_obarray)
(obarray_default_bits, Fobarray_make, Fobarrayp, Fobarray_clear): New.
* etc/emacs_lldb.py (Lisp_Object):
* lisp/emacs-lisp/cl-macs.el (`(,type . ,pred)):
* lisp/emacs-lisp/cl-preloaded.el (cl--typeof-types):
* lisp/emacs-lisp/comp-common.el (comp-known-type-specifiers):
* lisp/emacs-lisp/comp.el (comp-known-predicates):
* src/alloc.c (cleanup_vector, process_mark_stack):
* src/data.c (Ftype_of, syms_of_data):
* src/minibuf.c (Ftry_completion, Fall_completions, Ftest_completion):
* src/pdumper.c (dump_obarray_buckets, dump_obarray, dump_vectorlike):
* src/print.c (print_vectorlike_unreadable):
* test/lisp/abbrev-tests.el (abbrev-make-abbrev-table-test):
* test/lisp/obarray-tests.el (obarrayp-test)
(obarrayp-unchecked-content-test, obarray-make-default-test)
(obarray-make-with-size-test):
Adapt to new type.
2024-02-10 21:14:09 +01:00
|
|
|
|
"PVEC_OBARRAY": "struct Lisp_Obarray",
|
2022-07-12 12:29:14 +02:00
|
|
|
|
"PVEC_TERMINAL": "struct terminal",
|
|
|
|
|
"PVEC_WINDOW_CONFIGURATION": "struct save_window_data",
|
|
|
|
|
"PVEC_SUBR": "struct Lisp_Subr",
|
|
|
|
|
"PVEC_OTHER": "void",
|
|
|
|
|
"PVEC_XWIDGET": "void",
|
|
|
|
|
"PVEC_XWIDGET_VIEW": "void",
|
|
|
|
|
"PVEC_THREAD": "struct thread_state",
|
|
|
|
|
"PVEC_MUTEX": "Lisp_Mutex",
|
|
|
|
|
"PVEC_CONDVAR": "Lisp_CondVar",
|
|
|
|
|
"PVEC_MODULE_FUNCTION": "struct Lisp_Module_Function",
|
|
|
|
|
"PVEC_NATIVE_COMP_UNIT": "struct Lisp_Native_Comp_Unit",
|
|
|
|
|
"PVEC_SQLITE": "struct Lisp_Sqlite",
|
|
|
|
|
"PVEC_COMPILED": "struct Lisp_Vector",
|
|
|
|
|
"PVEC_CHAR_TABLE": "struct Lisp_Vector",
|
|
|
|
|
"PVEC_SUB_CHAR_TABLE": "void",
|
|
|
|
|
"PVEC_RECORD": "struct Lisp_Vector",
|
|
|
|
|
"PVEC_FONT": "struct font",
|
|
|
|
|
"PVEC_NORMAL_VECTOR": "struct Lisp_Vector"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Object construction/initialization.
|
|
|
|
|
def __init__(self, lisp_obj):
|
2023-10-16 10:12:10 +02:00
|
|
|
|
self.tagged = lisp_obj
|
|
|
|
|
self.unsigned = None
|
2022-07-12 12:29:14 +02:00
|
|
|
|
self.lisp_type = None
|
|
|
|
|
self.pvec_type = None
|
2023-10-16 10:12:10 +02:00
|
|
|
|
self.untagged = None
|
2022-07-15 09:36:10 +02:00
|
|
|
|
self.init_unsigned()
|
2022-07-12 12:29:14 +02:00
|
|
|
|
self.init_lisp_types()
|
|
|
|
|
self.init_values()
|
|
|
|
|
|
2022-07-15 09:36:10 +02:00
|
|
|
|
def init_unsigned(self):
|
2023-10-16 10:12:10 +02:00
|
|
|
|
if self.tagged.GetType().GetTypeClass() == lldb.eTypeClassStruct:
|
2022-07-15 09:36:10 +02:00
|
|
|
|
# Lisp_Object is actually a struct.
|
2023-10-16 10:12:10 +02:00
|
|
|
|
lisp_word = self.tagged.GetValueForExpressionPath(".i")
|
2022-07-15 09:36:10 +02:00
|
|
|
|
self.unsigned = lisp_word.GetValueAsUnsigned()
|
|
|
|
|
else:
|
2023-10-16 10:12:10 +02:00
|
|
|
|
self.unsigned = self.tagged.GetValueAsUnsigned()
|
2022-07-15 09:36:10 +02:00
|
|
|
|
|
2022-07-12 12:29:14 +02:00
|
|
|
|
# Initialize self.lisp_type to the C Lisp_Type enumerator of the
|
|
|
|
|
# Lisp_Object, as a string. Initialize self.pvec_type likewise to
|
|
|
|
|
# the pvec_type enumerator if the object is a vector-like, as a
|
|
|
|
|
# string.
|
|
|
|
|
def init_lisp_types(self):
|
|
|
|
|
t = self.eval(f"(enum Lisp_Type)"
|
|
|
|
|
f"((EMACS_INT) {self.unsigned} "
|
|
|
|
|
f"& (1 << GCTYPEBITS) - 1)")
|
|
|
|
|
self.lisp_type = enumerator_name(t)
|
|
|
|
|
if self.lisp_type == "Lisp_Vectorlike":
|
|
|
|
|
self.pvec_type = "PVEC_NORMAL_VECTOR"
|
|
|
|
|
vector = self.get_lisp_pointer("struct Lisp_Vector")
|
|
|
|
|
size = vector.GetValueForExpressionPath("->header.size")
|
|
|
|
|
size = size.GetValueAsUnsigned()
|
|
|
|
|
pseudo = self.eval(f"{size} & PSEUDOVECTOR_FLAG")
|
|
|
|
|
if pseudo.GetValueAsUnsigned() != 0:
|
|
|
|
|
typ = self.eval(
|
|
|
|
|
f"(enum pvec_type) (({size} "
|
|
|
|
|
f"& More_Lisp_Bits::PVEC_TYPE_MASK) "
|
|
|
|
|
f">> More_Lisp_Bits::PSEUDOVECTOR_AREA_BITS)")
|
|
|
|
|
self.pvec_type = enumerator_name(typ)
|
|
|
|
|
|
2023-10-16 10:12:10 +02:00
|
|
|
|
# Initialize self.untagged according to lisp_type and pvec_type.
|
2022-07-12 12:29:14 +02:00
|
|
|
|
def init_values(self):
|
|
|
|
|
if self.lisp_type == "Lisp_Symbol":
|
|
|
|
|
offset = self.get_lisp_pointer("char").GetValueAsUnsigned()
|
2023-10-16 10:12:10 +02:00
|
|
|
|
self.untagged = self.eval(f"(struct Lisp_Symbol *)"
|
2023-10-07 14:57:52 +02:00
|
|
|
|
f" ((char *) &lispsym + {offset})",
|
|
|
|
|
True)
|
2022-07-12 12:29:14 +02:00
|
|
|
|
elif self.lisp_type == "Lisp_String":
|
2023-10-16 10:12:10 +02:00
|
|
|
|
self.untagged = self.get_lisp_pointer("struct Lisp_String", True)
|
2022-07-12 12:29:14 +02:00
|
|
|
|
elif self.lisp_type == "Lisp_Vectorlike":
|
|
|
|
|
c_type = Lisp_Object.pvec2type[self.pvec_type]
|
2023-10-16 10:12:10 +02:00
|
|
|
|
self.untagged = self.get_lisp_pointer(c_type, True)
|
2022-07-12 12:29:14 +02:00
|
|
|
|
elif self.lisp_type == "Lisp_Cons":
|
2023-10-16 10:12:10 +02:00
|
|
|
|
self.untagged = self.get_lisp_pointer("struct Lisp_Cons", True)
|
2022-07-12 12:29:14 +02:00
|
|
|
|
elif self.lisp_type == "Lisp_Float":
|
2023-10-16 10:12:10 +02:00
|
|
|
|
self.untagged = self.get_lisp_pointer("struct Lisp_Float", True)
|
2022-07-12 12:29:14 +02:00
|
|
|
|
elif self.lisp_type in ("Lisp_Int0", "Lisp_Int1"):
|
2023-10-16 10:12:10 +02:00
|
|
|
|
self.untagged = self.eval(f"((EMACS_INT) {self.unsigned}) "
|
|
|
|
|
f">> (GCTYPEBITS - 1)", True)
|
|
|
|
|
elif self.lisp_type == "Lisp_Type_Unused0":
|
|
|
|
|
self.untagged = self.unsigned
|
2022-07-12 12:29:14 +02:00
|
|
|
|
else:
|
2023-10-16 10:12:10 +02:00
|
|
|
|
assert False, f"Unknown Lisp type {self.lisp_type}"
|
2022-07-12 12:29:14 +02:00
|
|
|
|
|
|
|
|
|
# Evaluate EXPR in the context of the current frame.
|
2023-10-07 14:57:52 +02:00
|
|
|
|
def eval(self, expr, make_var=False):
|
2023-10-16 10:12:10 +02:00
|
|
|
|
frame = self.tagged.GetFrame()
|
2023-10-07 14:57:52 +02:00
|
|
|
|
if make_var:
|
2023-10-16 10:12:10 +02:00
|
|
|
|
return frame.EvaluateExpression(expr)
|
2023-10-07 14:57:52 +02:00
|
|
|
|
options = lldb.SBExpressionOptions()
|
|
|
|
|
options.SetSuppressPersistentResult(True)
|
2023-10-16 10:12:10 +02:00
|
|
|
|
return frame.EvaluateExpression(expr, options)
|
2022-07-12 12:29:14 +02:00
|
|
|
|
|
|
|
|
|
# Return an SBValue for this object denoting a pointer of type
|
|
|
|
|
# TYP*.
|
2023-10-07 14:57:52 +02:00
|
|
|
|
def get_lisp_pointer(self, typ, make_var=False):
|
2022-07-12 12:29:14 +02:00
|
|
|
|
return self.eval(f"({typ}*) (((EMACS_INT) "
|
2023-10-07 14:57:52 +02:00
|
|
|
|
f"{self.unsigned}) & VALMASK)",
|
|
|
|
|
make_var)
|
2022-07-12 12:29:14 +02:00
|
|
|
|
|
|
|
|
|
# If this is a Lisp_String, return an SBValue for its string data.
|
|
|
|
|
# Return None otherwise.
|
|
|
|
|
def get_string_data(self):
|
|
|
|
|
if self.lisp_type == "Lisp_String":
|
2023-10-16 10:12:10 +02:00
|
|
|
|
return self.untagged.GetValueForExpressionPath("->u.s.data")
|
2022-07-12 12:29:14 +02:00
|
|
|
|
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":
|
2023-10-16 10:12:10 +02:00
|
|
|
|
name = self.untagged.GetValueForExpressionPath("->u.s.name")
|
2022-07-12 12:29:14 +02:00
|
|
|
|
return Lisp_Object(name).get_string_data()
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
# Return a summary string for this object.
|
|
|
|
|
def summary(self):
|
2023-10-16 10:12:10 +02:00
|
|
|
|
return str(self.untagged)
|
2022-07-12 12:29:14 +02:00
|
|
|
|
|
2022-07-10 13:35:32 +02:00
|
|
|
|
|
|
|
|
|
########################################################################
|
|
|
|
|
# LLDB Commands
|
|
|
|
|
########################################################################
|
|
|
|
|
|
|
|
|
|
def xbacktrace(debugger, command, ctx, result, internal_dict):
|
|
|
|
|
"""Print Emacs Lisp backtrace"""
|
|
|
|
|
frame = ctx.GetFrame()
|
|
|
|
|
n = frame.EvaluateExpression(
|
|
|
|
|
"current_thread->m_specpdl_ptr - current_thread->m_specpdl")
|
|
|
|
|
for i in reversed(range(0, n.GetValueAsUnsigned())):
|
|
|
|
|
s = frame.EvaluateExpression(f"current_thread->m_specpdl[{i}]")
|
|
|
|
|
kind = enumerator_name(s.GetChildMemberWithName("kind"))
|
|
|
|
|
if kind == "SPECPDL_BACKTRACE":
|
2022-07-12 12:29:14 +02:00
|
|
|
|
function = Lisp_Object(s.GetValueForExpressionPath(".bt.function"))
|
|
|
|
|
if function.lisp_type == "Lisp_Symbol":
|
|
|
|
|
sym_name = function.get_symbol_name()
|
2022-07-10 13:35:32 +02:00
|
|
|
|
result.AppendMessage(str(sym_name))
|
2022-07-12 12:29:14 +02:00
|
|
|
|
elif function.lisp_type == "Lisp_Vectorlike":
|
|
|
|
|
result.AppendMessage(function.pvec_type)
|
2022-07-10 13:35:32 +02:00
|
|
|
|
else:
|
2022-07-12 12:29:14 +02:00
|
|
|
|
result.AppendMessage(function.lisp_type)
|
2022-07-10 13:35:32 +02:00
|
|
|
|
|
|
|
|
|
def xdebug_print(debugger, command, result, internal_dict):
|
|
|
|
|
"""Print Lisp_Objects using safe_debug_print()"""
|
|
|
|
|
debugger.HandleCommand(f"expr safe_debug_print({command})")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
########################################################################
|
|
|
|
|
# Formatters
|
|
|
|
|
########################################################################
|
|
|
|
|
|
2022-07-12 12:29:14 +02:00
|
|
|
|
def type_summary_Lisp_Object(obj, internal_dict):
|
2022-08-02 09:12:47 +02:00
|
|
|
|
return Lisp_Object(obj).summary()
|
2022-07-10 13:35:32 +02:00
|
|
|
|
|
2023-10-09 15:20:37 +02:00
|
|
|
|
class Lisp_Object_Provider:
|
2023-10-16 10:12:10 +02:00
|
|
|
|
"""Synthetic children provider for Lisp_Objects.
|
|
|
|
|
Supposedly only used by 'frame variable', where -P <n> can be used
|
|
|
|
|
to specify a printing depth. """
|
2023-10-09 15:20:37 +02:00
|
|
|
|
def __init__(self, valobj, internal_dict):
|
|
|
|
|
self.valobj = valobj
|
2023-10-16 10:12:10 +02:00
|
|
|
|
self.children = {}
|
2023-10-09 15:20:37 +02:00
|
|
|
|
|
|
|
|
|
def update(self):
|
2023-10-16 10:12:10 +02:00
|
|
|
|
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
|
2023-10-09 15:20:37 +02:00
|
|
|
|
|
|
|
|
|
def num_children(self):
|
2023-10-16 10:12:10 +02:00
|
|
|
|
return len(self.children)
|
2023-10-09 15:20:37 +02:00
|
|
|
|
|
|
|
|
|
def get_child_index(self, name):
|
2023-10-16 10:12:10 +02:00
|
|
|
|
index = 0
|
|
|
|
|
for child_name, child in self.children:
|
|
|
|
|
if child_name == name:
|
|
|
|
|
return index
|
|
|
|
|
index = index + 1
|
|
|
|
|
return -1
|
2023-10-09 15:20:37 +02:00
|
|
|
|
|
|
|
|
|
def get_child_at_index(self, index):
|
2023-10-16 10:12:10 +02:00
|
|
|
|
key = list(self.children)[index]
|
|
|
|
|
return self.children[key]
|
2023-10-09 15:20:37 +02:00
|
|
|
|
|
2022-07-10 13:35:32 +02:00
|
|
|
|
|
|
|
|
|
########################################################################
|
|
|
|
|
# Initialization
|
|
|
|
|
########################################################################
|
|
|
|
|
|
|
|
|
|
# Define Python FUNCTION as an LLDB command.
|
|
|
|
|
def define_command (debugger, function):
|
|
|
|
|
lldb_command = function.__name__
|
|
|
|
|
python_function = __name__ + "." + function.__name__
|
|
|
|
|
interpreter = debugger.GetCommandInterpreter()
|
|
|
|
|
def define(overwrite):
|
|
|
|
|
res = lldb.SBCommandReturnObject()
|
|
|
|
|
interpreter.HandleCommand(f"command script add "
|
|
|
|
|
f"{overwrite} "
|
|
|
|
|
f"--function {python_function} "
|
|
|
|
|
f"{lldb_command}",
|
|
|
|
|
res)
|
|
|
|
|
return res.Succeeded()
|
|
|
|
|
if not define("--overwrite"):
|
|
|
|
|
define("")
|
|
|
|
|
|
2022-07-12 12:29:14 +02:00
|
|
|
|
# Define Python FUNCTION as an LLDB type summary provider for types
|
|
|
|
|
# matching REGEX. Type summaries defined here are defined in the
|
|
|
|
|
# category Emacs, and can be seen with 'type summary list -w Emacs',
|
|
|
|
|
# and deleted in a similar way.
|
|
|
|
|
def define_type_summary(debugger, regex, function):
|
2022-07-10 13:35:32 +02:00
|
|
|
|
python_function = __name__ + "." + function.__name__
|
2022-07-15 09:36:10 +02:00
|
|
|
|
debugger.HandleCommand(f"type summary add --expand "
|
2022-07-10 13:35:32 +02:00
|
|
|
|
f"--cascade true "
|
2022-07-12 12:29:14 +02:00
|
|
|
|
f"--category Emacs "
|
2022-07-15 09:36:10 +02:00
|
|
|
|
f"--python-function {python_function} "
|
|
|
|
|
+ regex)
|
|
|
|
|
|
2023-10-09 15:20:37 +02:00
|
|
|
|
# Define Python class CLS as a children provider for the types
|
|
|
|
|
# matching REFEXP. Providers are defined in the category Emacs, and
|
|
|
|
|
# can be seen with 'type synthetic list -w Emacs', and deleted in a
|
|
|
|
|
# similar way.
|
|
|
|
|
def define_type_synthetic(debugger, regex, cls):
|
|
|
|
|
python_class = __name__ + "." + cls.__name__
|
|
|
|
|
debugger.HandleCommand(f"type synthetic add "
|
|
|
|
|
f"--category Emacs "
|
|
|
|
|
f"--python-class {python_class} "
|
|
|
|
|
+ regex)
|
|
|
|
|
|
2022-07-15 09:36:10 +02:00
|
|
|
|
# Enable a given category of type summary providers.
|
|
|
|
|
def enable_type_category(debugger, category):
|
|
|
|
|
debugger.HandleCommand(f"type category enable {category}")
|
2022-07-10 13:35:32 +02:00
|
|
|
|
|
|
|
|
|
# This function is called by LLDB to initialize the module.
|
|
|
|
|
def __lldb_init_module(debugger, internal_dict):
|
|
|
|
|
define_command(debugger, xbacktrace)
|
|
|
|
|
define_command(debugger, xdebug_print)
|
2022-07-12 12:29:14 +02:00
|
|
|
|
define_type_summary(debugger, "Lisp_Object", type_summary_Lisp_Object)
|
2023-10-09 15:20:37 +02:00
|
|
|
|
define_type_synthetic(debugger, "Lisp_Object", Lisp_Object_Provider)
|
2022-07-15 09:36:10 +02:00
|
|
|
|
enable_type_category(debugger, "Emacs")
|
2022-07-10 13:35:32 +02:00
|
|
|
|
print('Emacs debugging support has been installed.')
|
|
|
|
|
|
|
|
|
|
# end.
|