JDevlieghere updated this revision to Diff 298034.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D89334/new/
https://reviews.llvm.org/D89334
Files:
lldb/include/lldb/Interpreter/CommandInterpreter.h
lldb/include/lldb/Interpreter/ScriptInterpreter.h
lldb/source/Commands/CommandObjectCommands.cpp
lldb/source/Interpreter/CommandInterpreter.cpp
lldb/source/Interpreter/ScriptInterpreter.cpp
lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp
lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.h
lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
lldb/test/Shell/ScriptInterpreter/Python/Inputs/hello.in
lldb/test/Shell/ScriptInterpreter/Python/Inputs/hello.py
lldb/test/Shell/ScriptInterpreter/Python/Inputs/zip.in
lldb/test/Shell/ScriptInterpreter/Python/Inputs/zip.py
lldb/test/Shell/ScriptInterpreter/Python/relative_import.test
Index: lldb/test/Shell/ScriptInterpreter/Python/relative_import.test
===================================================================
--- /dev/null
+++ lldb/test/Shell/ScriptInterpreter/Python/relative_import.test
@@ -0,0 +1,11 @@
+# REQUIRES: python
+
+# RUN: rm -rf %t && mkdir -p %t/foo/bar/baz
+# RUN: cp %S/Inputs/zip.py %t/foo
+# RUN: cp %S/Inputs/zip.in %t/foo
+# RUN: cp %S/Inputs/hello.py %t/foo/bar/baz
+# RUN: cp %S/Inputs/hello.in %t/foo/bar
+# RUN: echo 'command source %t/foo/bar/hello.in' >> %t/foo/zip.in
+# RUN: %lldb --script-language python -o 'command source %t/foo/zip.in' -o 'zip' -o 'hello' 2>&1 | FileCheck %s
+# CHECK: 95126
+# CHECK: Hello, World!
Index: lldb/test/Shell/ScriptInterpreter/Python/Inputs/zip.py
===================================================================
--- /dev/null
+++ lldb/test/Shell/ScriptInterpreter/Python/Inputs/zip.py
@@ -0,0 +1,7 @@
+import lldb
+
+def zip(debugger, command, result, internal_dict):
+ print("95126")
+
+def __lldb_init_module(debugger, internal_dict):
+ debugger.HandleCommand('command script add -f zip.zip zip')
Index: lldb/test/Shell/ScriptInterpreter/Python/Inputs/zip.in
===================================================================
--- /dev/null
+++ lldb/test/Shell/ScriptInterpreter/Python/Inputs/zip.in
@@ -0,0 +1 @@
+command script import zip
Index: lldb/test/Shell/ScriptInterpreter/Python/Inputs/hello.py
===================================================================
--- /dev/null
+++ lldb/test/Shell/ScriptInterpreter/Python/Inputs/hello.py
@@ -0,0 +1,7 @@
+import lldb
+
+def hello(debugger, command, result, internal_dict):
+ print("Hello, World!")
+
+def __lldb_init_module(debugger, internal_dict):
+ debugger.HandleCommand('command script add -f hello.hello hello')
Index: lldb/test/Shell/ScriptInterpreter/Python/Inputs/hello.in
===================================================================
--- /dev/null
+++ lldb/test/Shell/ScriptInterpreter/Python/Inputs/hello.in
@@ -0,0 +1 @@
+command script import baz/hello.py
Index: lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
===================================================================
--- lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
+++ lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
@@ -231,10 +231,10 @@
bool RunScriptFormatKeyword(const char *impl_function, ValueObject *value,
std::string &output, Status &error) override;
- bool
- LoadScriptingModule(const char *filename, bool init_session,
- lldb_private::Status &error,
- StructuredData::ObjectSP *module_sp = nullptr) override;
+ bool LoadScriptingModule(const char *filename, bool init_session,
+ lldb_private::Status &error,
+ StructuredData::ObjectSP *module_sp = nullptr,
+ FileSpec extra_search_dir = {}) override;
bool IsReservedWord(const char *word) override;
Index: lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
===================================================================
--- lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
+++ lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
@@ -2733,8 +2733,9 @@
bool ScriptInterpreterPythonImpl::LoadScriptingModule(
const char *pathname, bool init_session, lldb_private::Status &error,
- StructuredData::ObjectSP *module_sp) {
+ StructuredData::ObjectSP *module_sp, FileSpec extra_search_dir) {
namespace fs = llvm::sys::fs;
+ namespace path = llvm::sys::path;
if (!pathname || !pathname[0]) {
error.SetErrorString("invalid pathname");
@@ -2748,7 +2749,8 @@
FileSystem::Instance().Collect(target_file);
std::string basename(target_file.GetFilename().GetCString());
- StreamString command_stream;
+ fs::file_status st;
+ std::error_code ec = status(target_file.GetPath(), st);
// Before executing Python code, lock the GIL.
Locker py_lock(this,
@@ -2756,31 +2758,17 @@
(init_session ? Locker::InitSession : 0) | Locker::NoSTDIN,
Locker::FreeAcquiredLock |
(init_session ? Locker::TearDownSession : 0));
- fs::file_status st;
- std::error_code ec = status(target_file.GetPath(), st);
- if (ec || st.type() == fs::file_type::status_error ||
- st.type() == fs::file_type::type_unknown ||
- st.type() == fs::file_type::file_not_found) {
- // if not a valid file of any sort, check if it might be a filename still
- // dot can't be used but / and \ can, and if either is found, reject
- if (strchr(pathname, '\\') || strchr(pathname, '/')) {
- error.SetErrorString("invalid pathname");
- return false;
- }
- basename = pathname; // not a filename, probably a package of some sort,
- // let it go through
- } else if (is_directory(st) || is_regular_file(st)) {
- if (target_file.GetDirectory().IsEmpty()) {
- error.SetErrorString("invalid directory name");
- return false;
+ auto ExtendSysPath = [this](std::string directory) -> llvm::Error {
+ if (directory.empty()) {
+ return llvm::make_error<llvm::StringError>(
+ "invalid directory name", llvm::inconvertibleErrorCode());
}
- std::string directory = target_file.GetDirectory().GetCString();
replace_all(directory, "\\", "\\\\");
replace_all(directory, "'", "\\'");
- // now make sure that Python has "directory" in the search path
+ // Make sure that Python has "directory" in the search path.
StreamString command_stream;
command_stream.Printf("if not (sys.path.__contains__('%s')):\n "
"sys.path.insert(1,'%s');\n\n",
@@ -2792,13 +2780,50 @@
.SetSetLLDBGlobals(false))
.Success();
if (!syspath_retval) {
- error.SetErrorString("Python sys.path handling failed");
- return false;
+ return llvm::make_error<llvm::StringError>(
+ "Python sys.path handling failed", llvm::inconvertibleErrorCode());
}
- } else {
- error.SetErrorString("no known way to import this module specification");
- return false;
+ return llvm::Error::success();
+ };
+
+ if (ec || st.type() == fs::file_type::status_error ||
+ st.type() == fs::file_type::type_unknown ||
+ st.type() == fs::file_type::file_not_found) {
+ // The path name doesn't exists. It might be a relative import in which
+ // case we need to resolve it using to the extra search directory if
+ // provided. Python doesn't allow having directories in a module name. If
+ // the path name contains a path separator we need to add it to the system
+ // path. For example, if the pathname is `bar/baz` and the search path is
+ // `foo`, we need to add `foo/bar` to the system path and import `baz`.
+ //
+ // If no extra search path is given and the path name contains a path
+ // separator, we know it's invalid and can reject is immediately. If no
+ // path separators are found defer, to Python and let it deal with it.
+ if (extra_search_dir) {
+ FileSpec sys_path = extra_search_dir;
+ if (ConstString directory = target_file.GetDirectory()) {
+ llvm::SmallString<128> buffer;
+ extra_search_dir.GetPath(buffer);
+ path::append(buffer, directory.GetCString());
+ sys_path.SetPath(buffer);
+ }
+ if (llvm::Error e = ExtendSysPath(sys_path.GetPath())) {
+ error = std::move(e);
+ return false;
+ }
+ } else if (strchr(pathname, '\\') || strchr(pathname, '/')) {
+ error.SetErrorString("invalid pathname");
+ return false;
+ } else {
+ basename = pathname;
+ }
+ } else if (is_directory(st) || is_regular_file(st)) {
+ if (llvm::Error e =
+ ExtendSysPath(target_file.GetDirectory().GetCString())) {
+ error = std::move(e);
+ return false;
+ }
}
// Strip .py or .pyc extension
@@ -2811,6 +2836,7 @@
}
// check if the module is already import-ed
+ StreamString command_stream;
command_stream.Clear();
command_stream.Printf("sys.modules.__contains__('%s')", basename.c_str());
bool does_contain = false;
Index: lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.h
===================================================================
--- lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.h
+++ lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.h
@@ -25,10 +25,10 @@
void ExecuteInterpreterLoop() override;
- bool
- LoadScriptingModule(const char *filename, bool init_session,
- lldb_private::Status &error,
- StructuredData::ObjectSP *module_sp = nullptr) override;
+ bool LoadScriptingModule(const char *filename, bool init_session,
+ lldb_private::Status &error,
+ StructuredData::ObjectSP *module_sp = nullptr,
+ FileSpec extra_search_dir = {}) override;
// Static Functions
static void Initialize();
Index: lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp
===================================================================
--- lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp
+++ lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp
@@ -124,7 +124,7 @@
bool ScriptInterpreterLua::LoadScriptingModule(
const char *filename, bool init_session, lldb_private::Status &error,
- StructuredData::ObjectSP *module_sp) {
+ StructuredData::ObjectSP *module_sp, FileSpec extra_search_dir) {
FileSystem::Instance().Collect(filename);
if (llvm::Error e = m_lua->LoadModule(filename)) {
Index: lldb/source/Interpreter/ScriptInterpreter.cpp
===================================================================
--- lldb/source/Interpreter/ScriptInterpreter.cpp
+++ lldb/source/Interpreter/ScriptInterpreter.cpp
@@ -47,9 +47,11 @@
"This script interpreter does not support watchpoint callbacks.");
}
-bool ScriptInterpreter::LoadScriptingModule(
- const char *filename, bool init_session, lldb_private::Status &error,
- StructuredData::ObjectSP *module_sp) {
+bool ScriptInterpreter::LoadScriptingModule(const char *filename,
+ bool init_session,
+ lldb_private::Status &error,
+ StructuredData::ObjectSP *module_sp,
+ FileSpec extra_search_dir) {
error.SetErrorString(
"This script interpreter does not support importing modules.");
return false;
Index: lldb/source/Interpreter/CommandInterpreter.cpp
===================================================================
--- lldb/source/Interpreter/CommandInterpreter.cpp
+++ lldb/source/Interpreter/CommandInterpreter.cpp
@@ -2554,11 +2554,15 @@
debugger.SetAsyncExecution(false);
m_command_source_depth++;
+ m_command_source_dirs.push_back(cmd_file.CopyByRemovingLastPathComponent());
debugger.RunIOHandlerSync(io_handler_sp);
if (!m_command_source_flags.empty())
m_command_source_flags.pop_back();
+
+ m_command_source_dirs.pop_back();
m_command_source_depth--;
+
result.SetStatus(eReturnStatusSuccessFinishNoResult);
debugger.SetAsyncExecution(old_async_execution);
}
@@ -2964,6 +2968,12 @@
return true;
}
+FileSpec CommandInterpreter::GetCurrentSourceDir() {
+ if (m_command_source_dirs.empty())
+ return {};
+ return m_command_source_dirs.back();
+}
+
void CommandInterpreter::GetLLDBCommandsFromIOHandler(
const char *prompt, IOHandlerDelegate &delegate, void *baton) {
Debugger &debugger = GetDebugger();
Index: lldb/source/Commands/CommandObjectCommands.cpp
===================================================================
--- lldb/source/Commands/CommandObjectCommands.cpp
+++ lldb/source/Commands/CommandObjectCommands.cpp
@@ -1294,6 +1294,9 @@
return false;
}
+ FileSpec source_dir =
+ GetDebugger().GetCommandInterpreter().GetCurrentSourceDir();
+
for (auto &entry : command.entries()) {
Status error;
@@ -1308,7 +1311,7 @@
// more)
m_exe_ctx.Clear();
if (GetDebugger().GetScriptInterpreter()->LoadScriptingModule(
- entry.c_str(), init_session, error)) {
+ entry.c_str(), init_session, error, nullptr, source_dir)) {
result.SetStatus(eReturnStatusSuccessFinishNoResult);
} else {
result.AppendErrorWithFormat("module importing failed: %s",
Index: lldb/include/lldb/Interpreter/ScriptInterpreter.h
===================================================================
--- lldb/include/lldb/Interpreter/ScriptInterpreter.h
+++ lldb/include/lldb/Interpreter/ScriptInterpreter.h
@@ -507,7 +507,8 @@
virtual bool
LoadScriptingModule(const char *filename, bool init_session,
lldb_private::Status &error,
- StructuredData::ObjectSP *module_sp = nullptr);
+ StructuredData::ObjectSP *module_sp = nullptr,
+ FileSpec extra_search_dir = {});
virtual bool IsReservedWord(const char *word) { return false; }
Index: lldb/include/lldb/Interpreter/CommandInterpreter.h
===================================================================
--- lldb/include/lldb/Interpreter/CommandInterpreter.h
+++ lldb/include/lldb/Interpreter/CommandInterpreter.h
@@ -551,6 +551,8 @@
bool SaveTranscript(CommandReturnObject &result,
llvm::Optional<std::string> output_file = llvm::None);
+ FileSpec GetCurrentSourceDir();
+
protected:
friend class Debugger;
@@ -637,7 +639,13 @@
ChildrenTruncatedWarningStatus m_truncation_warning; // Whether we truncated
// children and whether
// the user has been told
+
+ // FIXME: Stop using this to control adding to the history and then replace
+ // this with m_command_source_dirs.size().
uint32_t m_command_source_depth;
+ /// A stack of directory paths. When not empty, the last one is the directory
+ /// of the file that's currently sourced.
+ std::vector<FileSpec> m_command_source_dirs;
std::vector<uint32_t> m_command_source_flags;
CommandInterpreterRunResult m_result;
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits