Skip to content

Commit 182f0d1

Browse files
committed
[lldb/Interpreter] Add ScriptInterpreter Wrapper for ScriptedProcess
This patch adds a ScriptedProcess interface to the ScriptInterpreter and more specifically, to the ScriptInterpreterPython. This interface will be used in the C++ `ScriptProcess` Process Plugin to call the script methods. At the moment, not all methods are implemented, they will upstreamed in upcoming patches. This patch also adds helper methods to the ScriptInterpreter to convert `SBAPI` Types (SBData & SBError) to `lldb_private` types (DataExtractor & Status). rdar://65508855 Differential Revision: https://reviews.llvm.org/D95711 Signed-off-by: Med Ismail Bennani <[email protected]>
1 parent d62a53a commit 182f0d1

17 files changed

+697
-38
lines changed

lldb/bindings/python/python-wrapper.swig

+100
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,72 @@ LLDBSwigPythonCreateCommandObject
258258
Py_RETURN_NONE;
259259
}
260260

261+
SWIGEXPORT void*
262+
LLDBSwigPythonCreateScriptedProcess
263+
(
264+
const char *python_class_name,
265+
const char *session_dictionary_name,
266+
const lldb::TargetSP& target_sp,
267+
lldb_private::StructuredDataImpl *args_impl,
268+
std::string &error_string
269+
)
270+
{
271+
if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name)
272+
Py_RETURN_NONE;
273+
274+
275+
PyErr_Cleaner py_err_cleaner(true);
276+
277+
auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name);
278+
auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_class_name, dict);
279+
280+
if (!pfunc.IsAllocated()) {
281+
error_string.append("could not find script class: ");
282+
error_string.append(python_class_name);
283+
return nullptr;
284+
}
285+
286+
// I do not want the SBTarget to be deallocated when going out of scope
287+
// because python has ownership of it and will manage memory for this
288+
// object by itself
289+
PythonObject target_arg(PyRefType::Owned, SBTypeToSWIGWrapper(new lldb::SBTarget(target_sp)));
290+
291+
if (!target_arg.IsAllocated())
292+
Py_RETURN_NONE;
293+
294+
llvm::Expected<PythonCallable::ArgInfo> arg_info = pfunc.GetArgInfo();
295+
if (!arg_info) {
296+
llvm::handleAllErrors(
297+
arg_info.takeError(),
298+
[&](PythonException &E) {
299+
error_string.append(E.ReadBacktrace());
300+
},
301+
[&](const llvm::ErrorInfoBase &E) {
302+
error_string.append(E.message());
303+
});
304+
Py_RETURN_NONE;
305+
}
306+
307+
PythonObject result = {};
308+
if (arg_info.get().max_positional_args == 2) {
309+
if (args_impl != nullptr) {
310+
error_string.assign("args passed, but __init__ does not take an args dictionary");
311+
Py_RETURN_NONE;
312+
}
313+
result = pfunc(target_arg, dict);
314+
} else if (arg_info.get().max_positional_args >= 3) {
315+
PythonObject args_arg(PyRefType::Owned, SBTypeToSWIGWrapper(new lldb::SBStructuredData(args_impl)));
316+
result = pfunc(target_arg, args_arg, dict);
317+
} else {
318+
error_string.assign("wrong number of arguments in __init__, should be 2 or 3 (not including self)");
319+
Py_RETURN_NONE;
320+
}
321+
322+
if (result.IsAllocated())
323+
return result.release();
324+
Py_RETURN_NONE;
325+
}
326+
261327
SWIGEXPORT void*
262328
LLDBSwigPythonCreateScriptedThreadPlan
263329
(
@@ -785,6 +851,40 @@ LLDBSwigPython_GetValueSynthProviderInstance
785851
return ret_val;
786852
}
787853

854+
SWIGEXPORT void*
855+
LLDBSWIGPython_CastPyObjectToSBData
856+
(
857+
PyObject* data
858+
)
859+
{
860+
lldb::SBData* sb_ptr = nullptr;
861+
862+
int valid_cast = SWIG_ConvertPtr(data, (void**)&sb_ptr, SWIGTYPE_p_lldb__SBData, 0);
863+
864+
if (valid_cast == -1)
865+
return NULL;
866+
867+
return sb_ptr;
868+
}
869+
870+
871+
SWIGEXPORT void*
872+
LLDBSWIGPython_CastPyObjectToSBError
873+
(
874+
PyObject* data
875+
)
876+
{
877+
lldb::SBError* sb_ptr = nullptr;
878+
879+
int valid_cast = SWIG_ConvertPtr(data, (void**)&sb_ptr, SWIGTYPE_p_lldb__SBError, 0);
880+
881+
if (valid_cast == -1)
882+
return NULL;
883+
884+
return sb_ptr;
885+
}
886+
887+
788888
SWIGEXPORT void*
789889
LLDBSWIGPython_CastPyObjectToSBValue
790890
(

lldb/include/lldb/API/SBData.h

+6
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111

1212
#include "lldb/API/SBDefines.h"
1313

14+
namespace lldb_private {
15+
class ScriptInterpreter;
16+
} // namespace lldb_private
17+
1418
namespace lldb {
1519

1620
class LLDB_API SBData {
@@ -147,6 +151,8 @@ class LLDB_API SBData {
147151
friend class SBTarget;
148152
friend class SBValue;
149153

154+
friend class lldb_private::ScriptInterpreter;
155+
150156
lldb::DataExtractorSP m_opaque_sp;
151157
};
152158

lldb/include/lldb/API/SBError.h

+6
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111

1212
#include "lldb/API/SBDefines.h"
1313

14+
namespace lldb_private {
15+
class ScriptInterpreter;
16+
} // namespace lldb_private
17+
1418
namespace lldb {
1519

1620
class LLDB_API SBError {
@@ -72,6 +76,8 @@ class LLDB_API SBError {
7276
friend class SBWatchpoint;
7377
friend class SBFile;
7478

79+
friend class lldb_private::ScriptInterpreter;
80+
7581
lldb_private::Status *get();
7682

7783
lldb_private::Status *operator->();

lldb/include/lldb/API/SBThreadPlan.h

-2
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@ namespace lldb {
1717

1818
class LLDB_API SBThreadPlan {
1919

20-
friend class lldb_private::ThreadPlan;
21-
2220
public:
2321
SBThreadPlan();
2422

lldb/include/lldb/Interpreter/ScriptInterpreter.h

+16-1
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,15 @@
99
#ifndef LLDB_INTERPRETER_SCRIPTINTERPRETER_H
1010
#define LLDB_INTERPRETER_SCRIPTINTERPRETER_H
1111

12+
#include "lldb/API/SBData.h"
13+
#include "lldb/API/SBError.h"
1214
#include "lldb/Breakpoint/BreakpointOptions.h"
1315
#include "lldb/Core/Communication.h"
1416
#include "lldb/Core/PluginInterface.h"
1517
#include "lldb/Core/SearchFilter.h"
1618
#include "lldb/Core/StreamFile.h"
1719
#include "lldb/Host/PseudoTerminal.h"
20+
#include "lldb/Interpreter/ScriptedProcessInterface.h"
1821
#include "lldb/Utility/Broadcaster.h"
1922
#include "lldb/Utility/Status.h"
2023
#include "lldb/Utility/StructuredData.h"
@@ -83,7 +86,9 @@ class ScriptInterpreter : public PluginInterface {
8386
eScriptReturnTypeOpaqueObject
8487
};
8588

86-
ScriptInterpreter(Debugger &debugger, lldb::ScriptLanguage script_lang);
89+
ScriptInterpreter(
90+
Debugger &debugger, lldb::ScriptLanguage script_lang,
91+
lldb::ScriptedProcessInterfaceUP scripted_process_interface_up = {});
8792

8893
~ScriptInterpreter() override = default;
8994

@@ -528,9 +533,19 @@ class ScriptInterpreter : public PluginInterface {
528533

529534
lldb::ScriptLanguage GetLanguage() { return m_script_lang; }
530535

536+
ScriptedProcessInterface &GetScriptedProcessInterface() {
537+
return *m_scripted_process_interface_up;
538+
}
539+
540+
lldb::DataExtractorSP
541+
GetDataExtractorFromSBData(const lldb::SBData &data) const;
542+
543+
Status GetStatusFromSBError(const lldb::SBError &error) const;
544+
531545
protected:
532546
Debugger &m_debugger;
533547
lldb::ScriptLanguage m_script_lang;
548+
lldb::ScriptedProcessInterfaceUP m_scripted_process_interface_up;
534549
};
535550

536551
} // namespace lldb_private
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
//===-- ScriptedProcessInterface.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_SCRIPTEDPROCESSINTERFACE_H
10+
#define LLDB_INTERPRETER_SCRIPTEDPROCESSINTERFACE_H
11+
12+
#include "lldb/Core/StructuredDataImpl.h"
13+
#include "lldb/Interpreter/ScriptInterpreter.h"
14+
#include "lldb/lldb-private.h"
15+
16+
#include <string>
17+
18+
namespace lldb_private {
19+
class ScriptedProcessInterface {
20+
public:
21+
ScriptedProcessInterface() : m_object_instance_sp(nullptr) {}
22+
23+
virtual ~ScriptedProcessInterface() = default;
24+
25+
virtual StructuredData::GenericSP
26+
CreatePluginObject(const llvm::StringRef class_name, lldb::TargetSP target_sp,
27+
StructuredData::DictionarySP args_sp) {
28+
return nullptr;
29+
}
30+
31+
virtual Status Launch() { return Status("ScriptedProcess did not launch"); }
32+
33+
virtual Status Resume() { return Status("ScriptedProcess did not resume"); }
34+
35+
virtual lldb::MemoryRegionInfoSP
36+
GetMemoryRegionContainingAddress(lldb::addr_t address) {
37+
return nullptr;
38+
}
39+
40+
virtual StructuredData::DictionarySP GetThreadWithID(lldb::tid_t tid) {
41+
return nullptr;
42+
}
43+
44+
virtual StructuredData::DictionarySP GetRegistersForThread(lldb::tid_t tid) {
45+
return nullptr;
46+
}
47+
48+
virtual lldb::DataExtractorSP
49+
ReadMemoryAtAddress(lldb::addr_t address, size_t size, Status &error) {
50+
return nullptr;
51+
}
52+
53+
virtual StructuredData::DictionarySP GetLoadedImages() { return nullptr; }
54+
55+
virtual lldb::pid_t GetProcessID() { return LLDB_INVALID_PROCESS_ID; }
56+
57+
virtual bool IsAlive() { return true; }
58+
59+
private:
60+
StructuredData::ObjectSP m_object_instance_sp;
61+
};
62+
} // namespace lldb_private
63+
64+
#endif // LLDB_INTERPRETER_SCRIPTEDPROCESSINTERFACE_H

lldb/include/lldb/lldb-forward.h

+4
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ class RichManglingContext;
174174
class Scalar;
175175
class ScriptInterpreter;
176176
class ScriptInterpreterLocker;
177+
class ScriptedProcessInterface;
177178
class ScriptedSyntheticChildren;
178179
class SearchFilter;
179180
class Section;
@@ -341,6 +342,7 @@ typedef std::shared_ptr<lldb_private::Listener> ListenerSP;
341342
typedef std::weak_ptr<lldb_private::Listener> ListenerWP;
342343
typedef std::shared_ptr<lldb_private::MemoryHistory> MemoryHistorySP;
343344
typedef std::unique_ptr<lldb_private::MemoryRegionInfo> MemoryRegionInfoUP;
345+
typedef std::shared_ptr<lldb_private::MemoryRegionInfo> MemoryRegionInfoSP;
344346
typedef std::shared_ptr<lldb_private::Module> ModuleSP;
345347
typedef std::weak_ptr<lldb_private::Module> ModuleWP;
346348
typedef std::shared_ptr<lldb_private::ObjectFile> ObjectFileSP;
@@ -391,6 +393,8 @@ typedef std::shared_ptr<lldb_private::ScriptSummaryFormat>
391393
ScriptSummaryFormatSP;
392394
typedef std::shared_ptr<lldb_private::ScriptInterpreter> ScriptInterpreterSP;
393395
typedef std::unique_ptr<lldb_private::ScriptInterpreter> ScriptInterpreterUP;
396+
typedef std::unique_ptr<lldb_private::ScriptedProcessInterface>
397+
ScriptedProcessInterfaceUP;
394398
typedef std::shared_ptr<lldb_private::Section> SectionSP;
395399
typedef std::unique_ptr<lldb_private::SectionList> SectionListUP;
396400
typedef std::weak_ptr<lldb_private::Section> SectionWP;

lldb/source/Interpreter/ScriptInterpreter.cpp

+19-3
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,12 @@
2626
using namespace lldb;
2727
using namespace lldb_private;
2828

29-
ScriptInterpreter::ScriptInterpreter(Debugger &debugger,
30-
lldb::ScriptLanguage script_lang)
31-
: m_debugger(debugger), m_script_lang(script_lang) {}
29+
ScriptInterpreter::ScriptInterpreter(
30+
Debugger &debugger, lldb::ScriptLanguage script_lang,
31+
lldb::ScriptedProcessInterfaceUP scripted_process_interface_up)
32+
: m_debugger(debugger), m_script_lang(script_lang),
33+
m_scripted_process_interface_up(
34+
std::move(scripted_process_interface_up)) {}
3235

3336
void ScriptInterpreter::CollectDataForBreakpointCommandCallback(
3437
std::vector<BreakpointOptions *> &bp_options_vec,
@@ -69,6 +72,19 @@ std::string ScriptInterpreter::LanguageToString(lldb::ScriptLanguage language) {
6972
llvm_unreachable("Unhandled ScriptInterpreter!");
7073
}
7174

75+
lldb::DataExtractorSP
76+
ScriptInterpreter::GetDataExtractorFromSBData(const lldb::SBData &data) const {
77+
return data.m_opaque_sp;
78+
}
79+
80+
Status
81+
ScriptInterpreter::GetStatusFromSBError(const lldb::SBError &error) const {
82+
if (error.m_opaque_up)
83+
return *error.m_opaque_up.get();
84+
85+
return Status();
86+
}
87+
7288
lldb::ScriptLanguage
7389
ScriptInterpreter::StringToLanguage(const llvm::StringRef &language) {
7490
if (language.equals_lower(LanguageToString(eScriptLanguageNone)))

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

+2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ add_lldb_library(lldbPluginScriptInterpreterPython PLUGIN
1111
PythonDataObjects.cpp
1212
PythonReadline.cpp
1313
ScriptInterpreterPython.cpp
14+
ScriptedProcessPythonInterface.cpp
15+
SWIGPythonBridge.cpp
1416

1517
LINK_LIBS
1618
lldbBreakpoint
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
//===-- SWIGPythonBridge.cpp ----------------------------------------------===//
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+
#include "lldb/Host/Config.h"
10+
#include "lldb/lldb-enumerations.h"
11+
12+
#if LLDB_ENABLE_PYTHON
13+
14+
// LLDB Python header must be included first
15+
#include "lldb-python.h"
16+
17+
#include "SWIGPythonBridge.h"
18+
19+
using namespace lldb;
20+
21+
namespace lldb_private {
22+
23+
template <typename T> const char *GetPythonValueFormatString(T t);
24+
template <> const char *GetPythonValueFormatString(char *) { return "s"; }
25+
template <> const char *GetPythonValueFormatString(char) { return "b"; }
26+
template <> const char *GetPythonValueFormatString(unsigned char) {
27+
return "B";
28+
}
29+
template <> const char *GetPythonValueFormatString(short) { return "h"; }
30+
template <> const char *GetPythonValueFormatString(unsigned short) {
31+
return "H";
32+
}
33+
template <> const char *GetPythonValueFormatString(int) { return "i"; }
34+
template <> const char *GetPythonValueFormatString(unsigned int) { return "I"; }
35+
template <> const char *GetPythonValueFormatString(long) { return "l"; }
36+
template <> const char *GetPythonValueFormatString(unsigned long) {
37+
return "k";
38+
}
39+
template <> const char *GetPythonValueFormatString(long long) { return "L"; }
40+
template <> const char *GetPythonValueFormatString(unsigned long long) {
41+
return "K";
42+
}
43+
template <> const char *GetPythonValueFormatString(float) { return "f"; }
44+
template <> const char *GetPythonValueFormatString(double) { return "d"; }
45+
46+
} // namespace lldb_private
47+
48+
#endif // LLDB_ENABLE_PYTHON

0 commit comments

Comments
 (0)