Skip to content

Commit 7a1e878

Browse files
committed
[lldb] Introduce OperatingSystem{,Python}Interface and make use it
This patch aims to consolidate the OperatingSystem scripting affordance by introducing a stable interface that conforms to the Scripted{,Python}Interface. This unify the way we call into python methods from lldb while also improving its capabilities by allowing us to pass lldb_private objects are arguments. Differential Revision: https://reviews.llvm.org/D159314 Signed-off-by: Med Ismail Bennani <[email protected]>
1 parent d808d92 commit 7a1e878

File tree

12 files changed

+253
-287
lines changed

12 files changed

+253
-287
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//===-- OperatingSystemInterface.h ------------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLDB_INTERPRETER_INTERFACES_OPERATINGSYSTEMINTERFACE_H
10+
#define LLDB_INTERPRETER_INTERFACES_OPERATINGSYSTEMINTERFACE_H
11+
12+
#include "ScriptedThreadInterface.h"
13+
#include "lldb/Core/StructuredDataImpl.h"
14+
15+
#include "lldb/lldb-private.h"
16+
17+
namespace lldb_private {
18+
class OperatingSystemInterface : virtual public ScriptedThreadInterface {
19+
public:
20+
virtual StructuredData::DictionarySP CreateThread(lldb::tid_t tid,
21+
lldb::addr_t context) {
22+
return {};
23+
}
24+
25+
virtual StructuredData::ArraySP GetThreadInfo() { return {}; }
26+
27+
virtual std::optional<std::string> GetRegisterContextForTID(lldb::tid_t tid) {
28+
return std::nullopt;
29+
}
30+
};
31+
} // namespace lldb_private
32+
33+
#endif // LLDB_INTERPRETER_INTERFACES_OPERATINGSYSTEMINTERFACE_H

lldb/include/lldb/Interpreter/ScriptInterpreter.h

Lines changed: 5 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "lldb/Core/ThreadedCommunication.h"
2222
#include "lldb/Host/PseudoTerminal.h"
2323
#include "lldb/Host/StreamFile.h"
24+
#include "lldb/Interpreter/Interfaces/OperatingSystemInterface.h"
2425
#include "lldb/Interpreter/Interfaces/ScriptedPlatformInterface.h"
2526
#include "lldb/Interpreter/Interfaces/ScriptedProcessInterface.h"
2627
#include "lldb/Interpreter/Interfaces/ScriptedThreadInterface.h"
@@ -252,34 +253,6 @@ class ScriptInterpreter : public PluginInterface {
252253
return lldb::ValueObjectListSP();
253254
}
254255

255-
virtual StructuredData::GenericSP
256-
OSPlugin_CreatePluginObject(const char *class_name,
257-
lldb::ProcessSP process_sp) {
258-
return StructuredData::GenericSP();
259-
}
260-
261-
virtual StructuredData::DictionarySP
262-
OSPlugin_RegisterInfo(StructuredData::ObjectSP os_plugin_object_sp) {
263-
return StructuredData::DictionarySP();
264-
}
265-
266-
virtual StructuredData::ArraySP
267-
OSPlugin_ThreadsInfo(StructuredData::ObjectSP os_plugin_object_sp) {
268-
return StructuredData::ArraySP();
269-
}
270-
271-
virtual StructuredData::StringSP
272-
OSPlugin_RegisterContextData(StructuredData::ObjectSP os_plugin_object_sp,
273-
lldb::tid_t thread_id) {
274-
return StructuredData::StringSP();
275-
}
276-
277-
virtual StructuredData::DictionarySP
278-
OSPlugin_CreateThread(StructuredData::ObjectSP os_plugin_object_sp,
279-
lldb::tid_t tid, lldb::addr_t context) {
280-
return StructuredData::DictionarySP();
281-
}
282-
283256
virtual StructuredData::ObjectSP
284257
CreateScriptedThreadPlan(const char *class_name,
285258
const StructuredDataImpl &args_data,
@@ -593,6 +566,10 @@ class ScriptInterpreter : public PluginInterface {
593566
return std::make_shared<ScriptedThreadInterface>();
594567
}
595568

569+
virtual lldb::OperatingSystemInterfaceSP CreateOperatingSystemInterface() {
570+
return std::make_shared<OperatingSystemInterface>();
571+
}
572+
596573
ScriptedPlatformInterface &GetScriptedPlatformInterface() {
597574
return *m_scripted_platform_interface_up;
598575
}

lldb/include/lldb/lldb-forward.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ class ObjectContainer;
130130
class ObjectFile;
131131
class ObjectFileJITDelegate;
132132
class OperatingSystem;
133+
class OperatingSystemInterface;
133134
class OptionGroup;
134135
class OptionGroupOptions;
135136
class OptionGroupPlatform;
@@ -360,6 +361,8 @@ typedef std::shared_ptr<lldb_private::ObjectFileJITDelegate>
360361
typedef std::weak_ptr<lldb_private::ObjectFileJITDelegate>
361362
ObjectFileJITDelegateWP;
362363
typedef std::unique_ptr<lldb_private::OperatingSystem> OperatingSystemUP;
364+
typedef std::shared_ptr<lldb_private::OperatingSystemInterface>
365+
OperatingSystemInterfaceSP;
363366
typedef std::shared_ptr<lldb_private::OptionValue> OptionValueSP;
364367
typedef std::weak_ptr<lldb_private::OptionValue> OptionValueWP;
365368
typedef std::shared_ptr<lldb_private::OptionValueProperties>

lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp

Lines changed: 64 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -74,47 +74,71 @@ llvm::StringRef OperatingSystemPython::GetPluginDescriptionStatic() {
7474
OperatingSystemPython::OperatingSystemPython(lldb_private::Process *process,
7575
const FileSpec &python_module_path)
7676
: OperatingSystem(process), m_thread_list_valobj_sp(), m_register_info_up(),
77-
m_interpreter(nullptr), m_python_object_sp() {
77+
m_interpreter(nullptr), m_script_object_sp() {
7878
if (!process)
7979
return;
8080
TargetSP target_sp = process->CalculateTarget();
8181
if (!target_sp)
8282
return;
8383
m_interpreter = target_sp->GetDebugger().GetScriptInterpreter();
84-
if (m_interpreter) {
85-
86-
std::string os_plugin_class_name(
87-
python_module_path.GetFilename().AsCString(""));
88-
if (!os_plugin_class_name.empty()) {
89-
LoadScriptOptions options;
90-
char python_module_path_cstr[PATH_MAX];
91-
python_module_path.GetPath(python_module_path_cstr,
92-
sizeof(python_module_path_cstr));
93-
Status error;
94-
if (m_interpreter->LoadScriptingModule(python_module_path_cstr, options,
95-
error)) {
96-
// Strip the ".py" extension if there is one
97-
size_t py_extension_pos = os_plugin_class_name.rfind(".py");
98-
if (py_extension_pos != std::string::npos)
99-
os_plugin_class_name.erase(py_extension_pos);
100-
// Add ".OperatingSystemPlugIn" to the module name to get a string like
101-
// "modulename.OperatingSystemPlugIn"
102-
os_plugin_class_name += ".OperatingSystemPlugIn";
103-
StructuredData::ObjectSP object_sp =
104-
m_interpreter->OSPlugin_CreatePluginObject(
105-
os_plugin_class_name.c_str(), process->CalculateProcess());
106-
if (object_sp && object_sp->IsValid())
107-
m_python_object_sp = object_sp;
108-
}
109-
}
84+
if (!m_interpreter)
85+
return;
86+
87+
std::string os_plugin_class_name(
88+
python_module_path.GetFilename().AsCString(""));
89+
if (os_plugin_class_name.empty())
90+
return;
91+
92+
LoadScriptOptions options;
93+
char python_module_path_cstr[PATH_MAX];
94+
python_module_path.GetPath(python_module_path_cstr,
95+
sizeof(python_module_path_cstr));
96+
Status error;
97+
if (!m_interpreter->LoadScriptingModule(python_module_path_cstr, options,
98+
error))
99+
return;
100+
101+
// Strip the ".py" extension if there is one
102+
size_t py_extension_pos = os_plugin_class_name.rfind(".py");
103+
if (py_extension_pos != std::string::npos)
104+
os_plugin_class_name.erase(py_extension_pos);
105+
// Add ".OperatingSystemPlugIn" to the module name to get a string like
106+
// "modulename.OperatingSystemPlugIn"
107+
os_plugin_class_name += ".OperatingSystemPlugIn";
108+
109+
auto operating_system_interface =
110+
m_interpreter->CreateOperatingSystemInterface();
111+
if (!operating_system_interface)
112+
// FIXME: We should pass an Status& to raise the error to the user.
113+
// return llvm::createStringError(
114+
// llvm::inconvertibleErrorCode(),
115+
// "Failed to create scripted thread interface.");
116+
return;
117+
118+
ExecutionContext exe_ctx(process);
119+
auto obj_or_err = operating_system_interface->CreatePluginObject(
120+
os_plugin_class_name, exe_ctx, nullptr);
121+
122+
if (!obj_or_err) {
123+
llvm::consumeError(obj_or_err.takeError());
124+
return;
110125
}
126+
127+
StructuredData::GenericSP owned_script_object_sp = *obj_or_err;
128+
if (!owned_script_object_sp->IsValid())
129+
// return llvm::createStringError(llvm::inconvertibleErrorCode(),
130+
// "Created script object is invalid.");
131+
return;
132+
133+
m_script_object_sp = owned_script_object_sp;
134+
m_operating_system_interface_sp = operating_system_interface;
111135
}
112136

113137
OperatingSystemPython::~OperatingSystemPython() = default;
114138

115139
DynamicRegisterInfo *OperatingSystemPython::GetDynamicRegisterInfo() {
116140
if (m_register_info_up == nullptr) {
117-
if (!m_interpreter || !m_python_object_sp)
141+
if (!m_interpreter || !m_operating_system_interface_sp)
118142
return nullptr;
119143
Log *log = GetLog(LLDBLog::OS);
120144

@@ -124,7 +148,7 @@ DynamicRegisterInfo *OperatingSystemPython::GetDynamicRegisterInfo() {
124148
m_process->GetID());
125149

126150
StructuredData::DictionarySP dictionary =
127-
m_interpreter->OSPlugin_RegisterInfo(m_python_object_sp);
151+
m_operating_system_interface_sp->GetRegisterInfo();
128152
if (!dictionary)
129153
return nullptr;
130154

@@ -140,27 +164,11 @@ DynamicRegisterInfo *OperatingSystemPython::GetDynamicRegisterInfo() {
140164
bool OperatingSystemPython::UpdateThreadList(ThreadList &old_thread_list,
141165
ThreadList &core_thread_list,
142166
ThreadList &new_thread_list) {
143-
if (!m_interpreter || !m_python_object_sp)
167+
if (!m_interpreter || !m_operating_system_interface_sp)
144168
return false;
145169

146170
Log *log = GetLog(LLDBLog::OS);
147171

148-
// First thing we have to do is to try to get the API lock, and the
149-
// interpreter lock. We're going to change the thread content of the process,
150-
// and we're going to use python, which requires the API lock to do it. We
151-
// need the interpreter lock to make sure thread_info_dict stays alive.
152-
//
153-
// If someone already has the API lock, that is ok, we just want to avoid
154-
// external code from making new API calls while this call is happening.
155-
//
156-
// This is a recursive lock so we can grant it to any Python code called on
157-
// the stack below us.
158-
Target &target = m_process->GetTarget();
159-
std::unique_lock<std::recursive_mutex> api_lock(target.GetAPIMutex(),
160-
std::defer_lock);
161-
(void)api_lock.try_lock(); // See above.
162-
auto interpreter_lock = m_interpreter->AcquireInterpreterLock();
163-
164172
LLDB_LOGF(log,
165173
"OperatingSystemPython::UpdateThreadList() fetching thread "
166174
"data from python for pid %" PRIu64,
@@ -170,7 +178,7 @@ bool OperatingSystemPython::UpdateThreadList(ThreadList &old_thread_list,
170178
// the lldb_private::Process subclass, no memory threads will be in this
171179
// list.
172180
StructuredData::ArraySP threads_list =
173-
m_interpreter->OSPlugin_ThreadsInfo(m_python_object_sp);
181+
m_operating_system_interface_sp->GetThreadInfo();
174182

175183
const uint32_t num_cores = core_thread_list.GetSize(false);
176184

@@ -281,28 +289,12 @@ RegisterContextSP
281289
OperatingSystemPython::CreateRegisterContextForThread(Thread *thread,
282290
addr_t reg_data_addr) {
283291
RegisterContextSP reg_ctx_sp;
284-
if (!m_interpreter || !m_python_object_sp || !thread)
292+
if (!m_interpreter || !m_script_object_sp || !thread)
285293
return reg_ctx_sp;
286294

287295
if (!IsOperatingSystemPluginThread(thread->shared_from_this()))
288296
return reg_ctx_sp;
289297

290-
// First thing we have to do is to try to get the API lock, and the
291-
// interpreter lock. We're going to change the thread content of the process,
292-
// and we're going to use python, which requires the API lock to do it. We
293-
// need the interpreter lock to make sure thread_info_dict stays alive.
294-
//
295-
// If someone already has the API lock, that is ok, we just want to avoid
296-
// external code from making new API calls while this call is happening.
297-
//
298-
// This is a recursive lock so we can grant it to any Python code called on
299-
// the stack below us.
300-
Target &target = m_process->GetTarget();
301-
std::unique_lock<std::recursive_mutex> api_lock(target.GetAPIMutex(),
302-
std::defer_lock);
303-
(void)api_lock.try_lock(); // See above.
304-
auto interpreter_lock = m_interpreter->AcquireInterpreterLock();
305-
306298
Log *log = GetLog(LLDBLog::Thread);
307299

308300
if (reg_data_addr != LLDB_INVALID_ADDRESS) {
@@ -324,11 +316,11 @@ OperatingSystemPython::CreateRegisterContextForThread(Thread *thread,
324316
") fetching register data from python",
325317
thread->GetID(), thread->GetProtocolID());
326318

327-
StructuredData::StringSP reg_context_data =
328-
m_interpreter->OSPlugin_RegisterContextData(m_python_object_sp,
329-
thread->GetID());
319+
std::optional<std::string> reg_context_data =
320+
m_operating_system_interface_sp->GetRegisterContextForTID(
321+
thread->GetID());
330322
if (reg_context_data) {
331-
std::string value = std::string(reg_context_data->GetValue());
323+
std::string value = *reg_context_data;
332324
DataBufferSP data_sp(new DataBufferHeap(value.c_str(), value.length()));
333325
if (data_sp->GetByteSize()) {
334326
RegisterContextMemory *reg_ctx_memory = new RegisterContextMemory(
@@ -347,6 +339,7 @@ OperatingSystemPython::CreateRegisterContextForThread(Thread *thread,
347339
"OperatingSystemPython::CreateRegisterContextForThread (tid "
348340
"= 0x%" PRIx64 ") forcing a dummy register context",
349341
thread->GetID());
342+
Target &target = m_process->GetTarget();
350343
reg_ctx_sp = std::make_shared<RegisterContextDummy>(
351344
*thread, 0, target.GetArchitecture().GetAddressByteSize());
352345
}
@@ -372,26 +365,11 @@ lldb::ThreadSP OperatingSystemPython::CreateThread(lldb::tid_t tid,
372365
", context = 0x%" PRIx64 ") fetching register data from python",
373366
tid, context);
374367

375-
if (m_interpreter && m_python_object_sp) {
376-
// First thing we have to do is to try to get the API lock, and the
377-
// interpreter lock. We're going to change the thread content of the
378-
// process, and we're going to use python, which requires the API lock to
379-
// do it. We need the interpreter lock to make sure thread_info_dict stays
380-
// alive.
381-
//
382-
// If someone already has the API lock, that is ok, we just want to avoid
383-
// external code from making new API calls while this call is happening.
384-
//
385-
// This is a recursive lock so we can grant it to any Python code called on
386-
// the stack below us.
387-
Target &target = m_process->GetTarget();
388-
std::unique_lock<std::recursive_mutex> api_lock(target.GetAPIMutex(),
389-
std::defer_lock);
390-
(void)api_lock.try_lock(); // See above.
391-
auto interpreter_lock = m_interpreter->AcquireInterpreterLock();
368+
if (m_interpreter && m_script_object_sp) {
392369

393370
StructuredData::DictionarySP thread_info_dict =
394-
m_interpreter->OSPlugin_CreateThread(m_python_object_sp, tid, context);
371+
m_operating_system_interface_sp->CreateThread(tid, context);
372+
395373
std::vector<bool> core_used_map;
396374
if (thread_info_dict) {
397375
ThreadList core_threads(m_process);

lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ class OperatingSystemPython : public lldb_private::OperatingSystem {
6262

6363
protected:
6464
bool IsValid() const {
65-
return m_python_object_sp && m_python_object_sp->IsValid();
65+
return m_script_object_sp && m_script_object_sp->IsValid();
6666
}
6767

6868
lldb::ThreadSP CreateThreadFromThreadInfo(
@@ -75,8 +75,9 @@ class OperatingSystemPython : public lldb_private::OperatingSystem {
7575

7676
lldb::ValueObjectSP m_thread_list_valobj_sp;
7777
std::unique_ptr<lldb_private::DynamicRegisterInfo> m_register_info_up;
78-
lldb_private::ScriptInterpreter *m_interpreter;
79-
lldb_private::StructuredData::ObjectSP m_python_object_sp;
78+
lldb_private::ScriptInterpreter *m_interpreter = nullptr;
79+
lldb::OperatingSystemInterfaceSP m_operating_system_interface_sp = nullptr;
80+
lldb_private::StructuredData::GenericSP m_script_object_sp = nullptr;
8081
};
8182

8283
#endif // LLDB_ENABLE_PYTHON

lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ if (LLDB_ENABLE_LIBEDIT)
2020
endif()
2121

2222
add_lldb_library(lldbPluginScriptInterpreterPythonInterfaces
23+
OperatingSystemPythonInterface.cpp
2324
ScriptedPythonInterface.cpp
2425
ScriptedProcessPythonInterface.cpp
2526
ScriptedThreadPythonInterface.cpp

0 commit comments

Comments
 (0)