Skip to content

Commit b74f58a

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 0c2997c commit b74f58a

23 files changed

+424
-8
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"

lldb/bindings/interface/SBProcess.i

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,7 @@ public:
353353
%feature("autodoc", "
354354
Returns the implementation object of the process plugin if available. None
355355
otherwise.") GetScriptedImplementation;
356-
ScriptedObject
356+
lldb::SBScriptObject
357357
GetScriptedImplementation();
358358

359359
%feature("autodoc", "
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
//===-- SWIG Interface for SBScriptObject -----------------------*- 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+
namespace lldb {
10+
11+
class SBScriptObject
12+
{
13+
public:
14+
SBScriptObject(const ScriptObjectPtr ptr, lldb::ScriptLanguage lang);
15+
16+
SBScriptObject(const lldb::SBScriptObject &rhs);
17+
18+
~SBScriptObject();
19+
20+
const lldb::SBScriptObject &operator=(const lldb::SBScriptObject &rhs);
21+
22+
explicit operator bool() const;
23+
24+
bool operator!=(const SBScriptObject &rhs) const;
25+
26+
bool IsValid() const;
27+
28+
lldb::ScriptObjectPtr GetPointer() const;
29+
30+
lldb::ScriptLanguage GetLanguage() const;
31+
32+
#ifdef SWIGPYTHON
33+
// operator== is a free function, which swig does not handle, so we inject
34+
// our own equality operator here
35+
%pythoncode%{
36+
def __eq__(self, other):
37+
return not self.__ne__(other)
38+
%}
39+
#endif
40+
41+
42+
#ifdef SWIGPYTHON
43+
%pythoncode %{
44+
ptr = property(GetPointer, None, doc='''A read only property that returns the underlying script object.''')
45+
lang = property(GetLanguage, None, doc='''A read only property that returns the script language associated with with this script object.''')
46+
%}
47+
#endif
48+
49+
};
50+
51+
}

lldb/bindings/interface/SBStructuredData.i

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ This class wraps the event type generated by StructuredData features."
2222

2323
SBStructuredData(const lldb::EventSP &event_sp);
2424

25+
SBStructuredData(const lldb::SBScriptObject obj,
26+
const lldb::SBDebugger &debugger);
27+
2528
~SBStructuredData();
2629

2730
bool
@@ -50,6 +53,8 @@ This class wraps the event type generated by StructuredData features."
5053

5154
size_t GetStringValue(char *dst, size_t dst_len) const;
5255

56+
lldb::SBScriptObject GetGenericValue() const;
57+
5358
lldb::SBError
5459
GetAsJSON(lldb::SBStream &stream) const;
5560

lldb/bindings/interfaces.swig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
%include "./interface/SBQueue.i"
5454
%include "./interface/SBQueueItem.i"
5555
%include "./interface/SBReproducer.i"
56+
%include "./interface/SBScriptObject.i"
5657
%include "./interface/SBSection.i"
5758
%include "./interface/SBSourceManager.i"
5859
%include "./interface/SBStream.i"

lldb/bindings/python/python-typemaps.swig

Lines changed: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,78 @@
5454
free((char *) $1);
5555
}
5656

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

lldb/include/lldb/API/SBDebugger.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,7 @@ class LLDB_API SBDebugger {
430430
friend class SBListener;
431431
friend class SBProcess;
432432
friend class SBSourceManager;
433+
friend class SBStructuredData;
433434
friend class SBTarget;
434435
friend class SBTrace;
435436

lldb/include/lldb/API/SBDefines.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,12 @@ class LLDB_API SBMemoryRegionInfoList;
7373
class LLDB_API SBModule;
7474
class LLDB_API SBModuleSpec;
7575
class LLDB_API SBModuleSpecList;
76+
class LLDB_API SBPlatform;
7677
class LLDB_API SBProcess;
7778
class LLDB_API SBProcessInfo;
7879
class LLDB_API SBQueue;
7980
class LLDB_API SBQueueItem;
81+
class LLDB_API SBScriptObject;
8082
class LLDB_API SBSection;
8183
class LLDB_API SBSourceManager;
8284
class LLDB_API SBStream;
@@ -112,7 +114,6 @@ class LLDB_API SBUnixSignals;
112114
typedef bool (*SBBreakpointHitCallback)(void *baton, SBProcess &process,
113115
SBThread &thread,
114116
lldb::SBBreakpointLocation &location);
115-
typedef void *ScriptedObject;
116117
}
117118

118119
#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
@@ -431,7 +431,7 @@ class LLDB_API SBProcess {
431431
///
432432
lldb::SBError DeallocateMemory(lldb::addr_t ptr);
433433

434-
lldb::ScriptedObject GetScriptedImplementation();
434+
lldb::SBScriptObject GetScriptedImplementation();
435435

436436
protected:
437437
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

0 commit comments

Comments
 (0)