zeek/auxil/zeek-aux/devel-tools/zeek_lldb_utils.py
Patrick Kelley 8fd444092b initial
2025-05-07 15:35:15 -04:00

58 lines
2.4 KiB
Python

import lldb
from ansi.color import fg
from ansi.color.fx import reset
from linereader import getline
# Cache script lines and files so that we don't have to load files repeatedly
script_lines = {}
# TODO: make this check that the thread is actually stopped and return an error if not
@lldb.command("btz")
def backtrace_zeek(debugger, command, exe_ctx, result, d):
selected_thread = exe_ctx.GetProcess().GetSelectedThread()
thread = exe_ctx.GetThread()
# I'd prefer to retrieve this from LLDB somehow, but the earlier versions
# don't have SDDebugger.GetSetting(), and I'm not really sure we could use
# the output from that anyways.
thread_format = f"{'*' if selected_thread.idx == thread.idx else ' '} thread #{thread.idx}, name = '{thread.name}', queue = {fg.green}'{thread.queue}'{reset}, stop reason = {fg.red}{thread.GetStopDescription(100)}{reset}"
print(thread_format)
selected_frame = thread.GetSelectedFrame().idx
for frame in thread.get_thread_frames():
frame_output = f" {'*' if frame.idx == selected_frame else ' '} "
frame_output += f"{frame}"
this = frame.FindVariable("this")
if this:
loc_ptr = this.GetChildMemberWithName("location")
if loc_ptr and loc_ptr.GetType().GetName() == "zeek::detail::Location *":
if loc_ptr.GetValueAsUnsigned() != 0:
loc = frame.EvaluateExpression("*(this->location)")
fname = (
loc.GetChildMemberWithName("filename").GetSummary().strip('"')
)
line_no = loc.GetChildMemberWithName(
"first_line"
).GetValueAsUnsigned()
frame_output += f"\n {fg.green}zeek script:{reset} {fname}"
fileinfo = f"{fname}:{line_no}"
if fileinfo in script_lines:
line = script_lines[fileinfo]
else:
line = getline(fname, line_no)
line = line.strip()
script_lines[fileinfo] = line
if line:
line_hdr = f"line {line_no}"
frame_output += (
f"\n {fg.green}{line_hdr: >11}:{reset} {line}"
)
print(frame_output)