lldb::SBTypeSynthetic
GetSyntheticForType (lldb::SBTypeNameSpecifier);
+ SBStructuredData GetScriptInterpreterInfo(ScriptLanguage);
+
STRING_EXTENSION(SBDebugger)
%feature("docstring",
${CMAKE_CURRENT_BINARY_DIR}/lldb.py
)
+if (NOT WIN32)
+add_custom_command(
+ OUTPUT ${LLVM_RUNTIME_OUTPUT_INTDIR}/lldb-python
+ VERBATIM
+ COMMAND ${CMAKE_COMMAND} -E copy lldb-python ${LLVM_RUNTIME_OUTPUT_INTDIR}/lldb-python
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+)
+add_custom_target(lldb-python-wrapper ALL DEPENDS
+ ${LLVM_RUNTIME_OUTPUT_INTDIR}/lldb-python
+)
+endif()
+
function(create_python_package swig_target working_dir pkg_dir)
cmake_parse_arguments(ARG "NOINIT" "" "FILES" ${ARGN})
if(ARG_FILES)
create_relative_symlink(${swig_target} ${LIBLLDB_SYMLINK_DEST}
${lldb_python_target_dir} ${LIBLLDB_SYMLINK_OUTPUT_FILE})
+
+ if (NOT WIN32)
+ add_dependencies(${swig_target} lldb-python-wrapper)
+ endif()
+
if(NOT LLDB_BUILD_FRAMEWORK)
set(LLDB_ARGDUMPER_FILENAME "lldb-argdumper${CMAKE_EXECUTABLE_SUFFIX}")
create_relative_symlink(${swig_target} "${LLVM_RUNTIME_OUTPUT_INTDIR}/${LLDB_ARGDUMPER_FILENAME}"
--- /dev/null
+#!/usr/bin/env python3
+
+import subprocess
+import os
+import sys
+import json
+
+lldb = os.path.join(os.path.dirname(__file__), 'lldb')
+
+info_json = subprocess.run([lldb, "-l", "python", "-print-script-interpreter-info"],
+ check=True, stdout=subprocess.PIPE, encoding='utf8').stdout
+info = json.loads(info_json)
+
+os.environ["PYTHONPATH"] = (
+ info["lldb-pythonpath"] + os.path.pathsep + os.environ.get("PYTHONPATH", ""))
+
+os.execl(info["executable"], info["executable"], *sys.argv[1:])
Alias for --script-language
+.. option:: --print-script-interpreter-info
+
+ Prints out a json dictionary with information about the scripting language interpreter.
+
.. option:: --python-path
Prints out the path to the lldb.py file for this version of lldb.
lldb::ScriptLanguage GetScriptingLanguage(const char *script_language_name);
+ SBStructuredData GetScriptInterpreterInfo(ScriptLanguage);
+
static const char *GetVersionString();
static const char *StateAsCString(lldb::StateType state);
lldb::ScriptedProcessInterfaceUP scripted_process_interface_up =
std::make_unique<ScriptedProcessInterface>());
+ virtual StructuredData::DictionarySP GetInterpreterInfo();
+
~ScriptInterpreter() override = default;
virtual bool Interrupt() { return false; }
llvm::StringRef(script_language_name), eScriptLanguageDefault, nullptr);
}
+SBStructuredData
+SBDebugger::GetScriptInterpreterInfo(lldb::ScriptLanguage language) {
+ LLDB_RECORD_METHOD(SBStructuredData, SBDebugger, GetScriptInterpreterInfo,
+ (lldb::ScriptLanguage), language);
+ SBStructuredData data;
+ if (m_opaque_sp) {
+ lldb_private::ScriptInterpreter *interp =
+ m_opaque_sp->GetScriptInterpreter(language);
+ if (interp) {
+ data.m_impl_up->SetObjectSP(interp->GetInterpreterInfo());
+ }
+ }
+ return LLDB_RECORD_RESULT(data);
+}
+
const char *SBDebugger::GetVersionString() {
LLDB_RECORD_STATIC_METHOD_NO_ARGS(const char *, SBDebugger, GetVersionString);
(const char *));
LLDB_REGISTER_METHOD(lldb::ScriptLanguage, SBDebugger, GetScriptingLanguage,
(const char *));
+ LLDB_REGISTER_METHOD(SBStructuredData, SBDebugger, GetScriptInterpreterInfo,
+ (lldb::ScriptLanguage));
LLDB_REGISTER_STATIC_METHOD(const char *, SBDebugger, GetVersionString, ());
LLDB_REGISTER_STATIC_METHOD(const char *, SBDebugger, StateAsCString,
(lldb::StateType));
"This script interpreter does not support watchpoint callbacks.");
}
+StructuredData::DictionarySP ScriptInterpreter::GetInterpreterInfo() {
+ return nullptr;
+}
+
bool ScriptInterpreter::LoadScriptingModule(const char *filename,
const LoadScriptOptions &options,
lldb_private::Status &error,
ScriptInterpreterLua::~ScriptInterpreterLua() = default;
+StructuredData::DictionarySP ScriptInterpreterLua::GetInterpreterInfo() {
+ auto info = std::make_shared<StructuredData::Dictionary>();
+ info->AddStringItem("language", "lua");
+ return info;
+}
+
bool ScriptInterpreterLua::ExecuteOneLine(llvm::StringRef command,
CommandReturnObject *result,
const ExecuteScriptOptions &options) {
StructuredData::ObjectSP *module_sp = nullptr,
FileSpec extra_search_dir = {}) override;
+ StructuredData::DictionarySP GetInterpreterInfo() override;
+
// Static Functions
static void Initialize();
#endif
}
-namespace {
-class GIL {
-public:
- GIL() {
- m_state = PyGILState_Ensure();
- assert(!PyErr_Occurred());
- }
- ~GIL() { PyGILState_Release(m_state); }
-
-protected:
- PyGILState_STATE m_state;
-};
-} // namespace
-
const char *PythonException::toCString() const {
if (!m_repr_bytes)
return "unknown exception";
class PythonInteger;
class PythonException;
+class GIL {
+public:
+ GIL() {
+ m_state = PyGILState_Ensure();
+ assert(!PyErr_Occurred());
+ }
+ ~GIL() { PyGILState_Release(m_state); }
+
+protected:
+ PyGILState_STATE m_state;
+};
+
class StructuredPythonObject : public StructuredData::Generic {
public:
StructuredPythonObject() : StructuredData::Generic() {}
return g_spec;
}
+StructuredData::DictionarySP ScriptInterpreterPython::GetInterpreterInfo() {
+ GIL gil;
+ FileSpec python_dir_spec = GetPythonDir();
+ if (!python_dir_spec)
+ return nullptr;
+ PythonString python_dir(python_dir_spec.GetPath());
+ PythonDictionary info(PyInitialValue::Empty);
+ llvm::Error error = info.SetItem("lldb-pythonpath", python_dir);
+ if (error)
+ return nullptr;
+ static const char script[] = R"(
+def main(info):
+ import sys
+ import os
+ name = 'python' + str(sys.version_info.major)
+ info.update({
+ "language": "python",
+ "prefix": sys.prefix,
+ "executable": os.path.join(sys.prefix, "bin", name),
+ })
+ return info
+)";
+ PythonScript get_info(script);
+ auto info_json = unwrapIgnoringErrors(As<PythonDictionary>(get_info(info)));
+ if (!info_json)
+ return nullptr;
+ return info_json.CreateStructuredDictionary();
+}
+
void ScriptInterpreterPython::SharedLibraryDirectoryHelper(
FileSpec &this_file) {
// When we're loaded from python, this_file will point to the file inside the
: ScriptInterpreter(debugger, lldb::eScriptLanguagePython),
IOHandlerDelegateMultiline("DONE") {}
+ StructuredData::DictionarySP GetInterpreterInfo() override;
static void Initialize();
static void Terminate();
static llvm::StringRef GetPluginNameStatic() { return "script-python"; }
import lldb
import os
+import sys
+import json
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil
self.assertTrue(any([os.path.exists(os.path.join(shlib_dir, f)) for f in
filenames]), "shlib_dir = " + shlib_dir)
+ @no_debug_info_test
+ def test_interpreter_info(self):
+ info_sd = self.dbg.GetScriptInterpreterInfo(self.dbg.GetScriptingLanguage("python"))
+ self.assertTrue(info_sd.IsValid())
+ stream = lldb.SBStream()
+ self.assertTrue(info_sd.GetAsJSON(stream).Success())
+ info = json.loads(stream.GetData())
+ prefix = info['prefix']
+ self.assertEqual(os.path.realpath(sys.prefix), os.path.realpath(prefix))
+ self.assertEqual(
+ os.path.realpath(os.path.join(info['lldb-pythonpath'], 'lldb')),
+ os.path.realpath(os.path.dirname(lldb.__file__)))
+ self.assertTrue(os.path.exists(info['executable']))
+ self.assertEqual(info['language'], 'python')
+
@no_debug_info_test
def test_directory_doesnt_end_with_slash(self):
CHECK: SCRIPTING
CHECK: -l
+CHECK: --print-script-interpreter-info
CHECK: --python-path
CHECK: -P
CHECK: --script-language
#include "lldb/API/SBReproducer.h"
#include "lldb/API/SBStream.h"
#include "lldb/API/SBStringList.h"
+#include "lldb/API/SBStructuredData.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Format.h"
if (args.hasArg(OPT_python_path)) {
m_option_data.m_print_python_path = true;
}
+ if (args.hasArg(OPT_print_script_interpreter_info)) {
+ m_option_data.m_print_script_interpreter_info = true;
+ }
if (args.hasArg(OPT_batch)) {
m_option_data.m_batch = true;
return error;
}
+ if (m_option_data.m_print_script_interpreter_info) {
+ SBStructuredData info =
+ m_debugger.GetScriptInterpreterInfo(m_debugger.GetScriptLanguage());
+ if (!info) {
+ error.SetErrorString("no script interpreter.");
+ } else {
+ SBStream stream;
+ error = info.GetAsJSON(stream);
+ if (error.Success()) {
+ llvm::outs() << stream.GetData() << '\n';
+ }
+ }
+ exiting = true;
+ return error;
+ }
+
return error;
}
bool m_source_quietly = false;
bool m_print_version = false;
bool m_print_python_path = false;
+ bool m_print_script_interpreter_info = false;
bool m_wait_for = false;
bool m_repl = false;
bool m_batch = false;
HelpText<"Alias for --python-path">,
Group<grp_scripting>;
+def print_script_interpreter_info: F<"print-script-interpreter-info">,
+ HelpText<"Prints out a json dictionary with information about the scripting language interpreter.">,
+ Group<grp_scripting>;
+
def script_language: Separate<["--", "-"], "script-language">,
MetaVarName<"<language>">,
HelpText<"Tells the debugger to use the specified scripting language for user-defined scripts.">,