Skip to content

Add the new "parsed cmd" from llvm mainline to 2030725 #8204

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Feb 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions lldb/bindings/python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -97,22 +97,24 @@ function(finish_swig_python swig_target lldb_python_bindings_dir lldb_python_tar
${lldb_python_target_dir}
"utils"
FILES "${LLDB_SOURCE_DIR}/examples/python/in_call_stack.py"
"${LLDB_SOURCE_DIR}/examples/python/symbolication.py")
"${LLDB_SOURCE_DIR}/examples/python/symbolication.py"
)

create_python_package(
${swig_target}
${lldb_python_target_dir}
"plugins"
FILES
"${LLDB_SOURCE_DIR}/examples/python/scripted_process/scripted_process.py"
"${LLDB_SOURCE_DIR}/examples/python/scripted_process/scripted_platform.py")
"${LLDB_SOURCE_DIR}/examples/python/templates/parsed_cmd.py"
"${LLDB_SOURCE_DIR}/examples/python/templates/scripted_process.py"
"${LLDB_SOURCE_DIR}/examples/python/templates/scripted_platform.py")

if(APPLE)
create_python_package(
${swig_target}
${lldb_python_target_dir} "macosx"
FILES "${LLDB_SOURCE_DIR}/examples/python/crashlog.py"
"${LLDB_SOURCE_DIR}/examples/python/scripted_process/crashlog_scripted_process.py"
"${LLDB_SOURCE_DIR}/examples/python/crashlog_scripted_process.py"
"${LLDB_SOURCE_DIR}/examples/darwin/heap_find/heap.py")

create_python_package(
Expand Down
31 changes: 27 additions & 4 deletions lldb/bindings/python/python-wrapper.swig
Original file line number Diff line number Diff line change
Expand Up @@ -330,12 +330,12 @@ PythonObject lldb_private::python::SWIGBridge::LLDBSwigPythonCreateScriptedThrea
}

bool lldb_private::python::SWIGBridge::LLDBSWIGPythonCallThreadPlan(
void *implementor, const char *method_name, lldb_private::Event *event,
void *implementer, const char *method_name, lldb_private::Event *event,
bool &got_error) {
got_error = false;

PyErr_Cleaner py_err_cleaner(false);
PythonObject self(PyRefType::Borrowed, static_cast<PyObject *>(implementor));
PythonObject self(PyRefType::Borrowed, static_cast<PyObject *>(implementer));
auto pfunc = self.ResolveName<PythonCallable>(method_name);

if (!pfunc.IsAllocated())
Expand Down Expand Up @@ -368,12 +368,12 @@ bool lldb_private::python::SWIGBridge::LLDBSWIGPythonCallThreadPlan(
}

bool lldb_private::python::SWIGBridge::LLDBSWIGPythonCallThreadPlan(
void *implementor, const char *method_name, lldb_private::Stream *stream,
void *implementer, const char *method_name, lldb_private::Stream *stream,
bool &got_error) {
got_error = false;

PyErr_Cleaner py_err_cleaner(false);
PythonObject self(PyRefType::Borrowed, static_cast<PyObject *>(implementor));
PythonObject self(PyRefType::Borrowed, static_cast<PyObject *>(implementer));
auto pfunc = self.ResolveName<PythonCallable>(method_name);

if (!pfunc.IsAllocated())
Expand Down Expand Up @@ -874,6 +874,29 @@ bool lldb_private::python::SWIGBridge::LLDBSwigPythonCallCommandObject(
return true;
}

#include "lldb/Interpreter/CommandReturnObject.h"

bool lldb_private::python::SWIGBridge::LLDBSwigPythonCallParsedCommandObject(
PyObject *implementor, lldb::DebuggerSP debugger, lldb_private::StructuredDataImpl &args_impl,
lldb_private::CommandReturnObject &cmd_retobj,
lldb::ExecutionContextRefSP exe_ctx_ref_sp) {

PyErr_Cleaner py_err_cleaner(true);

PythonObject self(PyRefType::Borrowed, implementor);
auto pfunc = self.ResolveName<PythonCallable>("__call__");

if (!pfunc.IsAllocated()) {
cmd_retobj.AppendError("Could not find '__call__' method in implementation class");
return false;
}

pfunc(SWIGBridge::ToSWIGWrapper(std::move(debugger)), SWIGBridge::ToSWIGWrapper(args_impl),
SWIGBridge::ToSWIGWrapper(exe_ctx_ref_sp), SWIGBridge::ToSWIGWrapper(cmd_retobj).obj());

return true;
}

PythonObject lldb_private::python::SWIGBridge::LLDBSWIGPythonCreateOSPlugin(
const char *python_class_name, const char *session_dictionary_name,
const lldb::ProcessSP &process_sp) {
Expand Down
31 changes: 27 additions & 4 deletions lldb/bindings/python/static-binding/LLDBWrapPython.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4968,12 +4968,12 @@ PythonObject lldb_private::python::SWIGBridge::LLDBSwigPythonCreateScriptedThrea
}

bool lldb_private::python::SWIGBridge::LLDBSWIGPythonCallThreadPlan(
void *implementor, const char *method_name, lldb_private::Event *event,
void *implementer, const char *method_name, lldb_private::Event *event,
bool &got_error) {
got_error = false;

PyErr_Cleaner py_err_cleaner(false);
PythonObject self(PyRefType::Borrowed, static_cast<PyObject *>(implementor));
PythonObject self(PyRefType::Borrowed, static_cast<PyObject *>(implementer));
auto pfunc = self.ResolveName<PythonCallable>(method_name);

if (!pfunc.IsAllocated())
Expand Down Expand Up @@ -5006,12 +5006,12 @@ bool lldb_private::python::SWIGBridge::LLDBSWIGPythonCallThreadPlan(
}

bool lldb_private::python::SWIGBridge::LLDBSWIGPythonCallThreadPlan(
void *implementor, const char *method_name, lldb_private::Stream *stream,
void *implementer, const char *method_name, lldb_private::Stream *stream,
bool &got_error) {
got_error = false;

PyErr_Cleaner py_err_cleaner(false);
PythonObject self(PyRefType::Borrowed, static_cast<PyObject *>(implementor));
PythonObject self(PyRefType::Borrowed, static_cast<PyObject *>(implementer));
auto pfunc = self.ResolveName<PythonCallable>(method_name);

if (!pfunc.IsAllocated())
Expand Down Expand Up @@ -5512,6 +5512,29 @@ bool lldb_private::python::SWIGBridge::LLDBSwigPythonCallCommandObject(
return true;
}

#include "lldb/Interpreter/CommandReturnObject.h"

bool lldb_private::python::SWIGBridge::LLDBSwigPythonCallParsedCommandObject(
PyObject *implementor, lldb::DebuggerSP debugger, lldb_private::StructuredDataImpl &args_impl,
lldb_private::CommandReturnObject &cmd_retobj,
lldb::ExecutionContextRefSP exe_ctx_ref_sp) {

PyErr_Cleaner py_err_cleaner(true);

PythonObject self(PyRefType::Borrowed, implementor);
auto pfunc = self.ResolveName<PythonCallable>("__call__");

if (!pfunc.IsAllocated()) {
cmd_retobj.AppendError("Could not find '__call__' method in implementation class");
return false;
}

pfunc(SWIGBridge::ToSWIGWrapper(std::move(debugger)), SWIGBridge::ToSWIGWrapper(args_impl),
SWIGBridge::ToSWIGWrapper(exe_ctx_ref_sp), SWIGBridge::ToSWIGWrapper(cmd_retobj).obj());

return true;
}

PythonObject lldb_private::python::SWIGBridge::LLDBSWIGPythonCreateOSPlugin(
const char *python_class_name, const char *session_dictionary_name,
const lldb::ProcessSP &process_sp) {
Expand Down
129 changes: 49 additions & 80 deletions lldb/examples/python/cmdtemplate.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,115 +11,84 @@

import inspect
import lldb
import optparse
import shlex
import sys
from lldb.plugins.parsed_cmd import ParsedCommand


class FrameStatCommand:
class FrameStatCommand(ParsedCommand):
program = "framestats"

@classmethod
def register_lldb_command(cls, debugger, module_name):
parser = cls.create_options()
cls.__doc__ = parser.format_help()
# Add any commands contained in this module to LLDB
command = "command script add -o -c %s.%s %s" % (
module_name,
cls.__name__,
cls.program,
)
debugger.HandleCommand(command)
ParsedCommandBase.do_register_cmd(cls, debugger, module_name)
print(
'The "{0}" command has been installed, type "help {0}" or "{0} '
'--help" for detailed help.'.format(cls.program)
)

@classmethod
def create_options(cls):
usage = "usage: %prog [options]"
description = (
"This command is meant to be an example of how to make "
"an LLDB command that does something useful, follows "
"best practices, and exploits the SB API. "
"Specifically, this command computes the aggregate "
"and average size of the variables in the current "
"frame and allows you to tweak exactly which variables "
"are to be accounted in the computation."
)
def setup_command_definition(self):

# Pass add_help_option = False, since this keeps the command in line
# with lldb commands, and we wire up "help command" to work by
# providing the long & short help methods below.
parser = optparse.OptionParser(
description=description,
prog=cls.program,
usage=usage,
add_help_option=False,
self.ov_parser.add_option(
"i",
"in-scope",
help = "in_scope_only = True",
value_type = lldb.eArgTypeBoolean,
dest = "bool_arg",
default = True,
)

parser.add_option(
"-i",
"--in-scope",
action="store_true",
dest="inscope",
help="in_scope_only = True",
self.ov_parser.add_option(
"i",
"in-scope",
help = "in_scope_only = True",
value_type = lldb.eArgTypeBoolean,
dest = "inscope",
default=True,
)

parser.add_option(
"-a",
"--arguments",
action="store_true",
dest="arguments",
help="arguments = True",
default=True,
self.ov_parser.add_option(
"a",
"arguments",
help = "arguments = True",
value_type = lldb.eArgTypeBoolean,
dest = "arguments",
default = True,
)

parser.add_option(
"-l",
"--locals",
action="store_true",
dest="locals",
help="locals = True",
default=True,
self.ov_parser.add_option(
"l",
"locals",
help = "locals = True",
value_type = lldb.eArgTypeBoolean,
dest = "locals",
default = True,
)

parser.add_option(
"-s",
"--statics",
action="store_true",
dest="statics",
help="statics = True",
default=True,
self.ov_parser.add_option(
"s",
"statics",
help = "statics = True",
value_type = lldb.eArgTypeBoolean,
dest = "statics",
default = True,
)

return parser

def get_short_help(self):
return "Example command for use in debugging"

def get_long_help(self):
return self.help_string
return ("This command is meant to be an example of how to make "
"an LLDB command that does something useful, follows "
"best practices, and exploits the SB API. "
"Specifically, this command computes the aggregate "
"and average size of the variables in the current "
"frame and allows you to tweak exactly which variables "
"are to be accounted in the computation.")


def __init__(self, debugger, unused):
self.parser = self.create_options()
self.help_string = self.parser.format_help()
super().__init__(debugger, unused)

def __call__(self, debugger, command, exe_ctx, result):
# Use the Shell Lexer to properly parse up command options just like a
# shell would
command_args = shlex.split(command)

try:
(options, args) = self.parser.parse_args(command_args)
except:
# if you don't handle exceptions, passing an incorrect argument to
# the OptionParser will cause LLDB to exit (courtesy of OptParse
# dealing with argument errors by throwing SystemExit)
result.SetError("option parsing failed")
return

# Always get program state from the lldb.SBExecutionContext passed
# in as exe_ctx
frame = exe_ctx.GetFrame()
Expand All @@ -128,7 +97,7 @@ def __call__(self, debugger, command, exe_ctx, result):
return

variables_list = frame.GetVariables(
options.arguments, options.locals, options.statics, options.inscope
self.ov_parser.arguments, self.ov_parser.locals, self.ov_parser.statics, self.ov_parser.inscope
)
variables_count = variables_list.GetSize()
if variables_count == 0:
Expand Down
Loading