Skip to content

Commit 73daaea

Browse files
Merge pull request #10462 from jimingham/loaded-into-target
Add a new affordance that the Python module in a dSYM
2 parents 7965a49 + fdd9045 commit 73daaea

File tree

15 files changed

+180
-11
lines changed

15 files changed

+180
-11
lines changed

lldb/bindings/python/python-wrapper.swig

+22
Original file line numberDiff line numberDiff line change
@@ -1051,6 +1051,28 @@ bool lldb_private::python::SWIGBridge::LLDBSWIGPythonRunScriptKeywordValue(
10511051
return true;
10521052
}
10531053

1054+
bool lldb_private::python::SWIGBridge::LLDBSwigPythonCallModuleNewTarget(
1055+
const char *python_module_name, const char *session_dictionary_name,
1056+
lldb::TargetSP target_sp) {
1057+
std::string python_function_name_string = python_module_name;
1058+
python_function_name_string += ".__lldb_module_added_to_target";
1059+
const char *python_function_name = python_function_name_string.c_str();
1060+
1061+
PyErr_Cleaner py_err_cleaner(true);
1062+
1063+
auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(
1064+
session_dictionary_name);
1065+
auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(
1066+
python_function_name, dict);
1067+
1068+
if (!pfunc.IsAllocated())
1069+
return true;
1070+
1071+
pfunc(SWIGBridge::ToSWIGWrapper(std::move(target_sp)), dict);
1072+
1073+
return true;
1074+
}
1075+
10541076
bool lldb_private::python::SWIGBridge::LLDBSwigPythonCallModuleInit(
10551077
const char *python_module_name, const char *session_dictionary_name,
10561078
lldb::DebuggerSP debugger) {

lldb/bindings/python/static-binding/LLDBWrapPython.cpp

+22
Original file line numberDiff line numberDiff line change
@@ -5863,6 +5863,28 @@ bool lldb_private::python::SWIGBridge::LLDBSWIGPythonRunScriptKeywordValue(
58635863
return true;
58645864
}
58655865

5866+
bool lldb_private::python::SWIGBridge::LLDBSwigPythonCallModuleNewTarget(
5867+
const char *python_module_name, const char *session_dictionary_name,
5868+
lldb::TargetSP target_sp) {
5869+
std::string python_function_name_string = python_module_name;
5870+
python_function_name_string += ".__lldb_module_added_to_target";
5871+
const char *python_function_name = python_function_name_string.c_str();
5872+
5873+
PyErr_Cleaner py_err_cleaner(true);
5874+
5875+
auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(
5876+
session_dictionary_name);
5877+
auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(
5878+
python_function_name, dict);
5879+
5880+
if (!pfunc.IsAllocated())
5881+
return true;
5882+
5883+
pfunc(SWIGBridge::ToSWIGWrapper(std::move(target_sp)), dict);
5884+
5885+
return true;
5886+
}
5887+
58665888
bool lldb_private::python::SWIGBridge::LLDBSwigPythonCallModuleInit(
58675889
const char *python_module_name, const char *session_dictionary_name,
58685890
lldb::DebuggerSP debugger) {

lldb/include/lldb/Interpreter/ScriptInterpreter.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -539,7 +539,8 @@ class ScriptInterpreter : public PluginInterface {
539539
LoadScriptingModule(const char *filename, const LoadScriptOptions &options,
540540
lldb_private::Status &error,
541541
StructuredData::ObjectSP *module_sp = nullptr,
542-
FileSpec extra_search_dir = {});
542+
FileSpec extra_search_dir = {},
543+
lldb::TargetSP loaded_into_target_sp = {});
543544

544545
virtual bool IsReservedWord(const char *word) { return false; }
545546

lldb/source/Core/Module.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -1624,7 +1624,9 @@ bool Module::LoadScriptingResourceInTarget(Target *target, Status &error,
16241624
scripting_fspec.Dump(scripting_stream.AsRawOstream());
16251625
LoadScriptOptions options;
16261626
bool did_load = script_interpreter->LoadScriptingModule(
1627-
scripting_stream.GetData(), options, error);
1627+
scripting_stream.GetData(), options, error,
1628+
/*module_sp*/ nullptr, /*extra_path*/ {},
1629+
target->shared_from_this());
16281630
if (!did_load)
16291631
return false;
16301632
}

lldb/source/Interpreter/ScriptInterpreter.cpp

+4-5
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,10 @@ StructuredData::DictionarySP ScriptInterpreter::GetInterpreterInfo() {
4848
return nullptr;
4949
}
5050

51-
bool ScriptInterpreter::LoadScriptingModule(const char *filename,
52-
const LoadScriptOptions &options,
53-
lldb_private::Status &error,
54-
StructuredData::ObjectSP *module_sp,
55-
FileSpec extra_search_dir) {
51+
bool ScriptInterpreter::LoadScriptingModule(
52+
const char *filename, const LoadScriptOptions &options,
53+
lldb_private::Status &error, StructuredData::ObjectSP *module_sp,
54+
FileSpec extra_search_dir, lldb::TargetSP loaded_into_target_sp) {
5655
error = Status::FromErrorString(
5756
"This script interpreter does not support importing modules.");
5857
return false;

lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ void ScriptInterpreterLua::ExecuteInterpreterLoop() {
228228
bool ScriptInterpreterLua::LoadScriptingModule(
229229
const char *filename, const LoadScriptOptions &options,
230230
lldb_private::Status &error, StructuredData::ObjectSP *module_sp,
231-
FileSpec extra_search_dir) {
231+
FileSpec extra_search_dir, lldb::TargetSP loaded_into_target_sp) {
232232

233233
if (llvm::Error e = m_lua->LoadModule(filename)) {
234234
error = Status::FromErrorStringWithFormatv(

lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ class ScriptInterpreterLua : public ScriptInterpreter {
4747
const LoadScriptOptions &options,
4848
lldb_private::Status &error,
4949
StructuredData::ObjectSP *module_sp = nullptr,
50-
FileSpec extra_search_dir = {}) override;
50+
FileSpec extra_search_dir = {},
51+
lldb::TargetSP loaded_into_target_sp = {}) override;
5152

5253
StructuredData::DictionarySP GetInterpreterInfo() override;
5354

lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h

+5
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,11 @@ class SWIGBridge {
224224
const char *session_dictionary_name,
225225
lldb::DebuggerSP debugger);
226226

227+
static bool
228+
LLDBSwigPythonCallModuleNewTarget(const char *python_module_name,
229+
const char *session_dictionary_name,
230+
lldb::TargetSP target);
231+
227232
static python::PythonObject
228233
LLDBSWIGPythonCreateOSPlugin(const char *python_class_name,
229234
const char *session_dictionary_name,

lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp

+7-1
Original file line numberDiff line numberDiff line change
@@ -2381,7 +2381,7 @@ uint64_t replace_all(std::string &str, const std::string &oldStr,
23812381
bool ScriptInterpreterPythonImpl::LoadScriptingModule(
23822382
const char *pathname, const LoadScriptOptions &options,
23832383
lldb_private::Status &error, StructuredData::ObjectSP *module_sp,
2384-
FileSpec extra_search_dir) {
2384+
FileSpec extra_search_dir, lldb::TargetSP target_sp) {
23852385
namespace fs = llvm::sys::fs;
23862386
namespace path = llvm::sys::path;
23872387

@@ -2559,6 +2559,12 @@ bool ScriptInterpreterPythonImpl::LoadScriptingModule(
25592559
PyRefType::Owned, static_cast<PyObject *>(module_pyobj)));
25602560
}
25612561

2562+
// Finally, if we got a target passed in, then we should tell the new module
2563+
// about this target:
2564+
if (target_sp)
2565+
return SWIGBridge::LLDBSwigPythonCallModuleNewTarget(
2566+
module_name.c_str(), m_dictionary_name.c_str(), target_sp);
2567+
25622568
return true;
25632569
}
25642570

lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,8 @@ class ScriptInterpreterPythonImpl : public ScriptInterpreterPython {
252252
const LoadScriptOptions &options,
253253
lldb_private::Status &error,
254254
StructuredData::ObjectSP *module_sp = nullptr,
255-
FileSpec extra_search_dir = {}) override;
255+
FileSpec extra_search_dir = {},
256+
lldb::TargetSP loaded_into_target_sp = {}) override;
256257

257258
bool IsReservedWord(const char *word) override;
258259

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
C_SOURCES := main.c
2+
CFLAGS_EXTRAS := -std=c99
3+
4+
include Makefile.rules
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
"""
2+
Test that we read in the Python module from a dSYM, and run the
3+
init in debugger and the init in target routines.
4+
"""
5+
6+
import os, shutil
7+
8+
import lldb
9+
import lldbsuite.test.lldbutil as lldbutil
10+
from lldbsuite.test.lldbtest import *
11+
from lldbsuite.test.decorators import *
12+
13+
14+
@skipUnlessDarwin
15+
class TestdSYMModuleInit(TestBase):
16+
@no_debug_info_test
17+
def test_add_module(self):
18+
"""This loads a file into a target and ensures that the python module was
19+
correctly added and the two intialization functions are called."""
20+
self.exe_name = "has_dsym"
21+
self.py_name = self.exe_name + ".py"
22+
23+
# Now load the target the first time into the debugger:
24+
self.runCmd("settings set target.load-script-from-symbol-file true")
25+
self.interp = self.dbg.GetCommandInterpreter()
26+
27+
executable = self.build_dsym(self.exe_name + "_1")
28+
target = self.createTestTarget(file_path=executable)
29+
self.check_answers(executable, ["1", "1", "has_dsym_1"])
30+
31+
# Now make a second target and make sure both get called:
32+
executable_2 = self.build_dsym(self.exe_name + "_2")
33+
target_2 = self.createTestTarget(file_path=executable_2)
34+
self.check_answers(executable_2, ["2", "2", "has_dsym_2"])
35+
36+
def check_answers(self, name, answers):
37+
result = lldb.SBCommandReturnObject()
38+
self.interp.HandleCommand("report_command", result)
39+
self.assertTrue(
40+
result.Succeeded(), f"report_command succeeded {result.GetError()}"
41+
)
42+
43+
cmd_results = result.GetOutput().split()
44+
self.assertEqual(answers[0], cmd_results[0], "Right number of module imports")
45+
self.assertEqual(answers[1], cmd_results[1], "Right number of target notices")
46+
self.assertIn(answers[2], name, "Right target name")
47+
48+
def build_dsym(self, name):
49+
self.build(debug_info="dsym", dictionary={"EXE": name})
50+
executable = self.getBuildArtifact(name)
51+
dsym_path = self.getBuildArtifact(name + ".dSYM")
52+
python_dir_path = dsym_path
53+
python_dir_path = os.path.join(dsym_path, "Contents", "Resources", "Python")
54+
if not os.path.exists(python_dir_path):
55+
os.mkdir(python_dir_path)
56+
57+
python_file_name = name + ".py"
58+
59+
module_dest_path = os.path.join(python_dir_path, python_file_name)
60+
module_origin_path = os.path.join(self.getSourceDir(), self.py_name)
61+
shutil.copy(module_origin_path, module_dest_path)
62+
63+
return executable
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import lldb
2+
3+
4+
def report_command(debugger, command, exe_ctx, result, internal_dict):
5+
result.AppendMessage(
6+
f'{lldb.num_module_inits} {lldb.num_target_inits} "{lldb.target_name}"'
7+
)
8+
result.SetStatus(lldb.eReturnStatusSuccessFinishResult)
9+
10+
11+
def __lldb_init_module(debugger, internal_dict):
12+
# We only want to make one copy of the report command so it will be shared
13+
if "has_dsym_1" in __name__:
14+
# lldb is a convenient place to store our counters.
15+
lldb.num_module_inits = 0
16+
lldb.num_target_inits = 0
17+
lldb.target_name = "<unknown>"
18+
19+
debugger.HandleCommand(
20+
f"command script add -o -f '{__name__}.report_command' report_command"
21+
)
22+
23+
lldb.num_module_inits += 1
24+
25+
26+
def __lldb_module_added_to_target(target, internal_dict):
27+
lldb.num_target_inits += 1
28+
target_name = target.executable.fullpath
+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#include <stdio.h>
2+
3+
int global_test_var = 10;
4+
5+
int main() {
6+
int test_var = 10;
7+
printf("Set a breakpoint here: %d.\n", test_var);
8+
return global_test_var;
9+
}

lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,12 @@ bool lldb_private::python::SWIGBridge::LLDBSwigPythonCallModuleInit(
225225
return false;
226226
}
227227

228+
bool lldb_private::python::SWIGBridge::LLDBSwigPythonCallModuleNewTarget(
229+
const char *python_module_name, const char *session_dictionary_name,
230+
lldb::TargetSP target) {
231+
return false;
232+
}
233+
228234
python::PythonObject
229235
lldb_private::python::SWIGBridge::LLDBSWIGPythonCreateOSPlugin(
230236
const char *python_class_name, const char *session_dictionary_name,

0 commit comments

Comments
 (0)