Skip to content

Commit 57bd882

Browse files
committed
[lldb] Convert script native types to StructuredData counterpart
This patch adds the ability to pass native types from the script interpreter to methods that use a {SB,}StructuredData argument. To do so, this patch changes the `ScriptedObject` struture that holds the pointer to the script object as well as the originating script interpreter language. It also exposes that to the SB API via a new class called `SBScriptObject`. This structure allows the debugger to parse the script object and convert it to a StructuredData object. If the type is not compatible with the StructuredData types, we will store its pointer in a `StructuredData::Generic` object. This patch also adds some SWIG typemaps that checks the input argument to ensure it's either an SBStructuredData object, in which case it just passes it throught, or a python object that is NOT another SB type, to provide some guardrails for the user. rdar://111467140 Differential Revision: https://reviews.llvm.org/D155161 Signed-off-by: Med Ismail Bennani <[email protected]>
1 parent aa34b34 commit 57bd882

21 files changed

+376
-9
lines changed

lldb/bindings/headers.swig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
#include "lldb/API/SBQueue.h"
5050
#include "lldb/API/SBQueueItem.h"
5151
#include "lldb/API/SBReproducer.h"
52+
#include "lldb/API/SBScriptObject.h"
5253
#include "lldb/API/SBSection.h"
5354
#include "lldb/API/SBSourceManager.h"
5455
#include "lldb/API/SBStream.h"
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
%extend lldb::SBScriptObject {
2+
#ifdef SWIGPYTHON
3+
%pythoncode %{
4+
ptr = property(GetPointer, None, doc='''A read only property that returns the underlying script object.''')
5+
lang = property(GetLanguage, None, doc='''A read only property that returns the script language associated with with this script object.''')
6+
%}
7+
#endif
8+
}

lldb/bindings/interfaces.swig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@
124124
%include "lldb/API/SBQueue.h"
125125
%include "lldb/API/SBQueueItem.h"
126126
%include "lldb/API/SBReproducer.h"
127+
%include "lldb/API/SBScriptObject.h"
127128
%include "lldb/API/SBSection.h"
128129
%include "lldb/API/SBSourceManager.h"
129130
%include "lldb/API/SBStream.h"
@@ -176,6 +177,7 @@
176177
%include "./interface/SBModuleExtensions.i"
177178
%include "./interface/SBModuleSpecExtensions.i"
178179
%include "./interface/SBProcessExtensions.i"
180+
%include "./interface/SBScriptObjectExtensions.i"
179181
%include "./interface/SBSectionExtensions.i"
180182
%include "./interface/SBStreamExtensions.i"
181183
%include "./interface/SBStringListExtensions.i"

lldb/bindings/python/python-typemaps.swig

Lines changed: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,78 @@ AND call SWIG_fail at the same time, because it will result in a double free.
5959
free((char *) $1);
6060
}
6161

62-
%typemap(out) lldb::ScriptedObject {
62+
%typecheck(SWIG_TYPECHECK_POINTER) lldb::ScriptObjectPtr {
63+
PythonObject obj(PyRefType::Borrowed, $input);
64+
if (!obj.IsValid()) {
65+
PyErr_Clear();
66+
$1 = 0;
67+
} else {
68+
$1 = 1;
69+
}
70+
}
71+
72+
%typemap(in) lldb::ScriptObjectPtr {
73+
if ($input == Py_None) {
74+
$1 = nullptr;
75+
} else {
76+
PythonObject obj(PyRefType::Borrowed, $input);
77+
if (!obj.IsValid()) {
78+
PyErr_SetString(PyExc_TypeError, "Script object is not valid");
79+
SWIG_fail;
80+
}
81+
82+
auto lldb_module = PythonModule::Import("lldb");
83+
if (!lldb_module) {
84+
std::string err_msg = llvm::toString(lldb_module.takeError());
85+
PyErr_SetString(PyExc_TypeError, err_msg.c_str());
86+
SWIG_fail;
87+
}
88+
89+
auto sb_structured_data_class = lldb_module.get().Get("SBStructuredData");
90+
if (!sb_structured_data_class) {
91+
std::string err_msg = llvm::toString(sb_structured_data_class.takeError());
92+
PyErr_SetString(PyExc_TypeError, err_msg.c_str());
93+
SWIG_fail;
94+
}
95+
96+
if (obj.IsInstance(sb_structured_data_class.get())) {
97+
$1 = obj.get();
98+
} else {
99+
auto type = obj.GetType();
100+
if (!type) {
101+
std::string err_msg = llvm::toString(type.takeError());
102+
PyErr_SetString(PyExc_TypeError, err_msg.c_str());
103+
SWIG_fail;
104+
}
105+
106+
auto type_name = As<std::string>(type.get().GetAttribute("__name__"));
107+
if (!type_name) {
108+
std::string err_msg = llvm::toString(type_name.takeError());
109+
PyErr_SetString(PyExc_TypeError, err_msg.c_str());
110+
SWIG_fail;
111+
}
112+
113+
if (llvm::StringRef(type_name.get()).startswith("SB")) {
114+
std::string error_msg = "Input type is invalid: " + type_name.get();
115+
PyErr_SetString(PyExc_TypeError, error_msg.c_str());
116+
SWIG_fail;
117+
} else {
118+
$1 = obj.get();
119+
}
120+
}
121+
}
122+
}
123+
124+
%typemap(out) lldb::ScriptObjectPtr {
125+
$result = (PyObject*) $1;
126+
if (!$result)
127+
$result = Py_None;
128+
Py_INCREF($result);
129+
}
130+
131+
%typemap(out) lldb::SBScriptObject {
63132
$result = nullptr;
64-
if (const void* impl = $1)
133+
if (const void* impl = $1.GetPointer())
65134
$result = (PyObject*) impl;
66135
if (!$result) {
67136
$result = Py_None;

lldb/include/lldb/API/SBDebugger.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,7 @@ class LLDB_API SBDebugger {
484484
friend class SBListener;
485485
friend class SBProcess;
486486
friend class SBSourceManager;
487+
friend class SBStructuredData;
487488
friend class SBTarget;
488489
friend class SBTrace;
489490

lldb/include/lldb/API/SBDefines.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ class LLDB_API SBProcess;
8888
class LLDB_API SBProcessInfo;
8989
class LLDB_API SBQueue;
9090
class LLDB_API SBQueueItem;
91+
class LLDB_API SBScriptObject;
9192
class LLDB_API SBSection;
9293
class LLDB_API SBSourceManager;
9394
class LLDB_API SBStream;
@@ -131,8 +132,6 @@ typedef void (*SBDebuggerDestroyCallback)(lldb::user_id_t debugger_id,
131132
typedef SBError (*SBPlatformLocateModuleCallback)(
132133
void *baton, const SBModuleSpec &module_spec, SBFileSpec &module_file_spec,
133134
SBFileSpec &symbol_file_spec);
134-
135-
typedef void *ScriptedObject;
136135
}
137136

138137
#endif // LLDB_API_SBDEFINES_H

lldb/include/lldb/API/SBProcess.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -437,7 +437,7 @@ class LLDB_API SBProcess {
437437
///
438438
lldb::SBError DeallocateMemory(lldb::addr_t ptr);
439439

440-
lldb::ScriptedObject GetScriptedImplementation();
440+
lldb::SBScriptObject GetScriptedImplementation();
441441

442442
protected:
443443
friend class SBAddress;
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
//===-- SBScriptObject.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_API_SBSCRIPTOBJECT_H
10+
#define LLDB_API_SBSCRIPTOBJECT_H
11+
12+
#include "lldb/API/SBDefines.h"
13+
14+
namespace lldb_private {
15+
class ScriptObject;
16+
}
17+
18+
namespace lldb {
19+
20+
class LLDB_API SBScriptObject {
21+
public:
22+
SBScriptObject(const ScriptObjectPtr ptr, lldb::ScriptLanguage lang);
23+
24+
SBScriptObject(const lldb::SBScriptObject &rhs);
25+
26+
~SBScriptObject();
27+
28+
const lldb::SBScriptObject &operator=(const lldb::SBScriptObject &rhs);
29+
30+
explicit operator bool() const;
31+
32+
bool operator!=(const SBScriptObject &rhs) const;
33+
34+
bool IsValid() const;
35+
36+
lldb::ScriptObjectPtr GetPointer() const;
37+
38+
lldb::ScriptLanguage GetLanguage() const;
39+
40+
protected:
41+
friend class SBStructuredData;
42+
43+
lldb_private::ScriptObject *get();
44+
45+
lldb_private::ScriptObject &ref();
46+
47+
const lldb_private::ScriptObject &ref() const;
48+
49+
private:
50+
std::unique_ptr<lldb_private::ScriptObject> m_opaque_up;
51+
};
52+
53+
} // namespace lldb
54+
55+
#endif // LLDB_API_SBSCRIPTOBJECT_H

lldb/include/lldb/API/SBStructuredData.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
#include "lldb/API/SBDefines.h"
1313
#include "lldb/API/SBModule.h"
14+
#include "lldb/API/SBScriptObject.h"
1415

1516
namespace lldb_private {
1617
namespace python {
@@ -29,6 +30,9 @@ class SBStructuredData {
2930

3031
SBStructuredData(const lldb::SBStructuredData &rhs);
3132

33+
SBStructuredData(const lldb::SBScriptObject obj,
34+
const lldb::SBDebugger &debugger);
35+
3236
~SBStructuredData();
3337

3438
lldb::SBStructuredData &operator=(const lldb::SBStructuredData &rhs);
@@ -101,6 +105,9 @@ class SBStructuredData {
101105
/// \a dst in all cases.
102106
size_t GetStringValue(char *dst, size_t dst_len) const;
103107

108+
/// Return the generic pointer if this data structure is a generic type.
109+
lldb::SBScriptObject GetGenericValue() const;
110+
104111
protected:
105112
friend class SBAttachInfo;
106113
friend class SBLaunchInfo;

lldb/include/lldb/Core/StructuredDataImpl.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,17 @@ class StructuredDataImpl {
161161
return (::snprintf(dst, dst_len, "%s", result.data()));
162162
}
163163

164+
void *GetGenericValue() const {
165+
if (!m_data_sp)
166+
return nullptr;
167+
168+
StructuredData::Generic *generic_data = m_data_sp->GetAsGeneric();
169+
if (!generic_data)
170+
return nullptr;
171+
172+
return generic_data->GetValue();
173+
}
174+
164175
StructuredData::ObjectSP GetObjectSP() const { return m_data_sp; }
165176

166177
private:

lldb/include/lldb/Interpreter/ScriptInterpreter.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "lldb/Core/StreamFile.h"
2222
#include "lldb/Core/ThreadedCommunication.h"
2323
#include "lldb/Host/PseudoTerminal.h"
24+
#include "lldb/Interpreter/ScriptObject.h"
2425
#include "lldb/Interpreter/ScriptedPlatformInterface.h"
2526
#include "lldb/Interpreter/ScriptedProcessInterface.h"
2627
#include "lldb/Utility/Broadcaster.h"
@@ -591,6 +592,11 @@ class ScriptInterpreter : public PluginInterface {
591592
return *m_scripted_platform_interface_up;
592593
}
593594

595+
virtual StructuredData::ObjectSP
596+
CreateStructuredDataFromScriptObject(ScriptObject obj) {
597+
return {};
598+
}
599+
594600
lldb::DataExtractorSP
595601
GetDataExtractorFromSBData(const lldb::SBData &data) const;
596602

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//===-- ScriptObject.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_SCRIPTOBJECT_H
10+
#define LLDB_INTERPRETER_SCRIPTOBJECT_H
11+
12+
#include "lldb/lldb-types.h"
13+
14+
namespace lldb_private {
15+
class ScriptObject {
16+
public:
17+
ScriptObject(lldb::ScriptObjectPtr ptr, lldb::ScriptLanguage lang)
18+
: m_ptr(ptr), m_language(lang) {}
19+
20+
operator bool() const { return m_ptr != nullptr; }
21+
22+
const void *GetPointer() const { return m_ptr; }
23+
24+
lldb::ScriptLanguage GetLanguage() const { return m_language; }
25+
26+
private:
27+
const void *m_ptr;
28+
lldb::ScriptLanguage m_language;
29+
};
30+
} // namespace lldb_private
31+
32+
#endif // LLDB_INTERPRETER_SCRIPTOBJECT_H

lldb/include/lldb/lldb-types.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ typedef bool (*CommandOverrideCallback)(void *baton, const char **argv);
7474
typedef bool (*ExpressionCancelCallback)(ExpressionEvaluationPhase phase,
7575
void *baton);
7676

77+
typedef void *ScriptObjectPtr;
78+
7779
typedef uint64_t addr_t;
7880
typedef uint64_t user_id_t;
7981
typedef uint64_t pid_t;

lldb/source/API/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ add_lldb_library(liblldb SHARED ${option_framework}
6464
SBQueue.cpp
6565
SBQueueItem.cpp
6666
SBReproducer.cpp
67+
SBScriptObject.cpp
6768
SBSection.cpp
6869
SBSourceManager.cpp
6970
SBStream.cpp

lldb/source/API/SBProcess.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "lldb/API/SBFileSpec.h"
3939
#include "lldb/API/SBMemoryRegionInfo.h"
4040
#include "lldb/API/SBMemoryRegionInfoList.h"
41+
#include "lldb/API/SBScriptObject.h"
4142
#include "lldb/API/SBStream.h"
4243
#include "lldb/API/SBStringList.h"
4344
#include "lldb/API/SBStructuredData.h"
@@ -1285,8 +1286,10 @@ lldb::SBError SBProcess::DeallocateMemory(lldb::addr_t ptr) {
12851286
return sb_error;
12861287
}
12871288

1288-
ScriptedObject SBProcess::GetScriptedImplementation() {
1289+
lldb::SBScriptObject SBProcess::GetScriptedImplementation() {
12891290
LLDB_INSTRUMENT_VA(this);
12901291
ProcessSP process_sp(GetSP());
1291-
return (process_sp) ? process_sp->GetImplementation() : nullptr;
1292+
return lldb::SBScriptObject((process_sp) ? process_sp->GetImplementation()
1293+
: nullptr,
1294+
eScriptLanguageDefault);
12921295
}

0 commit comments

Comments
 (0)