Skip to content

Commit f732157

Browse files
authored
[lldb/Interpreter] Introduce ScriptedStopHook{,Python}Interface & make use of it (llvm#109498)
This patch re-lands llvm#105449 and fixes the various test failures. --------- Signed-off-by: Med Ismail Bennani <[email protected]>
1 parent cdf2970 commit f732157

22 files changed

+304
-224
lines changed

lldb/bindings/python/python-swigsafecast.swig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ PythonObject SWIGBridge::ToSWIGWrapper(lldb::BreakpointSP breakpoint_sp) {
3333
SWIGTYPE_p_lldb__SBBreakpoint);
3434
}
3535

36-
PythonObject SWIGBridge::ToSWIGWrapper(Status status) {
36+
PythonObject SWIGBridge::ToSWIGWrapper(Status&& status) {
3737
return ToSWIGHelper(new lldb::SBError(std::move(status)), SWIGTYPE_p_lldb__SBError);
3838
}
3939

lldb/bindings/python/python-wrapper.swig

Lines changed: 13 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -301,104 +301,6 @@ unsigned int lldb_private::python::SWIGBridge::LLDBSwigPythonCallBreakpointResol
301301
return ret_val;
302302
}
303303

304-
PythonObject lldb_private::python::SWIGBridge::LLDBSwigPythonCreateScriptedStopHook(
305-
lldb::TargetSP target_sp, const char *python_class_name,
306-
const char *session_dictionary_name, const StructuredDataImpl &args_impl,
307-
Status &error) {
308-
if (python_class_name == NULL || python_class_name[0] == '\0') {
309-
error = Status::FromErrorString("Empty class name.");
310-
return PythonObject();
311-
}
312-
if (!session_dictionary_name) {
313-
error = Status::FromErrorString("No session dictionary");
314-
return PythonObject();
315-
}
316-
317-
PyErr_Cleaner py_err_cleaner(true);
318-
319-
auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(
320-
session_dictionary_name);
321-
auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(
322-
python_class_name, dict);
323-
324-
if (!pfunc.IsAllocated()) {
325-
error = Status::FromErrorStringWithFormat("Could not find class: %s.",
326-
python_class_name);
327-
return PythonObject();
328-
}
329-
330-
PythonObject result =
331-
pfunc(SWIGBridge::ToSWIGWrapper(target_sp), SWIGBridge::ToSWIGWrapper(args_impl), dict);
332-
333-
if (result.IsAllocated()) {
334-
// Check that the handle_stop callback is defined:
335-
auto callback_func = result.ResolveName<PythonCallable>("handle_stop");
336-
if (callback_func.IsAllocated()) {
337-
if (auto args_info = callback_func.GetArgInfo()) {
338-
size_t num_args = (*args_info).max_positional_args;
339-
if (num_args != 2) {
340-
error = Status::FromErrorStringWithFormat(
341-
"Wrong number of args for "
342-
"handle_stop callback, should be 2 (excluding self), got: %zu",
343-
num_args);
344-
return PythonObject();
345-
} else
346-
return result;
347-
} else {
348-
error = Status::FromErrorString(
349-
"Couldn't get num arguments for handle_stop "
350-
"callback.");
351-
return PythonObject();
352-
}
353-
return result;
354-
} else {
355-
error = Status::FromErrorStringWithFormat(
356-
"Class \"%s\" is missing the required "
357-
"handle_stop callback.",
358-
python_class_name);
359-
}
360-
}
361-
return PythonObject();
362-
}
363-
364-
bool lldb_private::python::SWIGBridge::LLDBSwigPythonStopHookCallHandleStop(
365-
void *implementor, lldb::ExecutionContextRefSP exc_ctx_sp,
366-
lldb::StreamSP stream) {
367-
// handle_stop will return a bool with the meaning "should_stop"...
368-
// If you return nothing we'll assume we are going to stop.
369-
// Also any errors should return true, since we should stop on error.
370-
371-
PyErr_Cleaner py_err_cleaner(false);
372-
PythonObject self(PyRefType::Borrowed, static_cast<PyObject *>(implementor));
373-
auto pfunc = self.ResolveName<PythonCallable>("handle_stop");
374-
375-
if (!pfunc.IsAllocated())
376-
return true;
377-
378-
std::shared_ptr<lldb::SBStream> sb_stream = std::make_shared<lldb::SBStream>();
379-
PythonObject sb_stream_arg = SWIGBridge::ToSWIGWrapper(sb_stream);
380-
PythonObject result =
381-
pfunc(SWIGBridge::ToSWIGWrapper(std::move(exc_ctx_sp)), sb_stream_arg);
382-
383-
if (PyErr_Occurred()) {
384-
stream->PutCString("Python error occurred handling stop-hook.");
385-
PyErr_Print();
386-
PyErr_Clear();
387-
return true;
388-
}
389-
390-
// Now add the result to the output stream. SBStream only
391-
// makes an internally help StreamString which I can't interpose, so I
392-
// have to copy it over here.
393-
stream->PutCString(sb_stream->GetData());
394-
sb_stream_arg.release();
395-
396-
if (result.get() == Py_False)
397-
return false;
398-
else
399-
return true;
400-
}
401-
402304
// wrapper that calls an optional instance member of an object taking no
403305
// arguments
404306
static PyObject *LLDBSwigPython_CallOptionalMember(
@@ -677,6 +579,19 @@ void *lldb_private::python::LLDBSWIGPython_CastPyObjectToSBMemoryRegionInfo(PyOb
677579
return sb_ptr;
678580
}
679581

582+
void *lldb_private::python::LLDBSWIGPython_CastPyObjectToSBExecutionContext(PyObject *
583+
data) {
584+
lldb::SBExecutionContext *sb_ptr = NULL;
585+
586+
int valid_cast = SWIG_ConvertPtr(data, (void **)&sb_ptr,
587+
SWIGTYPE_p_lldb__SBExecutionContext, 0);
588+
589+
if (valid_cast == -1)
590+
return NULL;
591+
592+
return sb_ptr;
593+
}
594+
680595
bool lldb_private::python::SWIGBridge::LLDBSwigPythonCallCommand(
681596
const char *python_function_name, const char *session_dictionary_name,
682597
lldb::DebuggerSP debugger, const char *args,

lldb/include/lldb/API/SBExecutionContext.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <vector>
1717

1818
namespace lldb_private {
19+
class ScriptInterpreter;
1920
namespace python {
2021
class SWIGBridge;
2122
}
@@ -55,6 +56,7 @@ class LLDB_API SBExecutionContext {
5556

5657
protected:
5758
friend class lldb_private::python::SWIGBridge;
59+
friend class lldb_private::ScriptInterpreter;
5860

5961
lldb_private::ExecutionContextRef *get() const;
6062

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//===-- ScriptedStopHookInterface.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_SCRIPTEDSTOPHOOKINTERFACE_H
10+
#define LLDB_INTERPRETER_INTERFACES_SCRIPTEDSTOPHOOKINTERFACE_H
11+
12+
#include "lldb/lldb-private.h"
13+
14+
#include "ScriptedInterface.h"
15+
16+
namespace lldb_private {
17+
class ScriptedStopHookInterface : public ScriptedInterface {
18+
public:
19+
virtual llvm::Expected<StructuredData::GenericSP>
20+
CreatePluginObject(llvm::StringRef class_name, lldb::TargetSP target_sp,
21+
const StructuredDataImpl &args_sp) = 0;
22+
23+
/// "handle_stop" will return a bool with the meaning "should_stop"...
24+
/// If nothing is returned, we'll assume we are going to stop.
25+
/// Also any errors should return true, since we should stop on error.
26+
virtual llvm::Expected<bool> HandleStop(ExecutionContext &exe_ctx,
27+
lldb::StreamSP &output_sp) {
28+
return true;
29+
}
30+
};
31+
} // namespace lldb_private
32+
33+
#endif // LLDB_INTERPRETER_INTERFACES_SCRIPTEDSTOPHOOKINTERFACE_H

lldb/include/lldb/Interpreter/ScriptInterpreter.h

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "lldb/API/SBData.h"
1515
#include "lldb/API/SBError.h"
1616
#include "lldb/API/SBEvent.h"
17+
#include "lldb/API/SBExecutionContext.h"
1718
#include "lldb/API/SBLaunchInfo.h"
1819
#include "lldb/API/SBMemoryRegionInfo.h"
1920
#include "lldb/API/SBStream.h"
@@ -271,24 +272,6 @@ class ScriptInterpreter : public PluginInterface {
271272
return lldb::eSearchDepthModule;
272273
}
273274

274-
virtual StructuredData::GenericSP
275-
CreateScriptedStopHook(lldb::TargetSP target_sp, const char *class_name,
276-
const StructuredDataImpl &args_data, Status &error) {
277-
error =
278-
Status::FromErrorString("Creating scripted stop-hooks with the current "
279-
"script interpreter is not supported.");
280-
return StructuredData::GenericSP();
281-
}
282-
283-
// This dispatches to the handle_stop method of the stop-hook class. It
284-
// returns a "should_stop" bool.
285-
virtual bool
286-
ScriptedStopHookHandleStop(StructuredData::GenericSP implementor_sp,
287-
ExecutionContext &exc_ctx,
288-
lldb::StreamSP stream_sp) {
289-
return true;
290-
}
291-
292275
virtual StructuredData::ObjectSP
293276
LoadPluginModule(const FileSpec &file_spec, lldb_private::Status &error) {
294277
return StructuredData::ObjectSP();
@@ -561,6 +544,10 @@ class ScriptInterpreter : public PluginInterface {
561544
return {};
562545
}
563546

547+
virtual lldb::ScriptedStopHookInterfaceSP CreateScriptedStopHookInterface() {
548+
return {};
549+
}
550+
564551
virtual StructuredData::ObjectSP
565552
CreateStructuredDataFromScriptObject(ScriptObject obj) {
566553
return {};
@@ -587,6 +574,9 @@ class ScriptInterpreter : public PluginInterface {
587574
std::optional<MemoryRegionInfo> GetOpaqueTypeFromSBMemoryRegionInfo(
588575
const lldb::SBMemoryRegionInfo &mem_region) const;
589576

577+
lldb::ExecutionContextRefSP GetOpaqueTypeFromSBExecutionContext(
578+
const lldb::SBExecutionContext &exe_ctx) const;
579+
590580
protected:
591581
Debugger &m_debugger;
592582
lldb::ScriptLanguage m_script_lang;

lldb/include/lldb/Target/Target.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1391,8 +1391,7 @@ class Target : public std::enable_shared_from_this<Target>,
13911391
/// This holds the dictionary of keys & values that can be used to
13921392
/// parametrize any given callback's behavior.
13931393
StructuredDataImpl m_extra_args;
1394-
/// This holds the python callback object.
1395-
StructuredData::GenericSP m_implementation_sp;
1394+
lldb::ScriptedStopHookInterfaceSP m_interface_sp;
13961395

13971396
/// Use CreateStopHook to make a new empty stop hook. The GetCommandPointer
13981397
/// and fill it with commands, and SetSpecifier to set the specifier shared

lldb/include/lldb/lldb-forward.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ class ScriptInterpreterLocker;
190190
class ScriptedMetadata;
191191
class ScriptedPlatformInterface;
192192
class ScriptedProcessInterface;
193+
class ScriptedStopHookInterface;
193194
class ScriptedThreadInterface;
194195
class ScriptedThreadPlanInterface;
195196
class ScriptedSyntheticChildren;
@@ -408,6 +409,8 @@ typedef std::unique_ptr<lldb_private::ScriptedPlatformInterface>
408409
ScriptedPlatformInterfaceUP;
409410
typedef std::unique_ptr<lldb_private::ScriptedProcessInterface>
410411
ScriptedProcessInterfaceUP;
412+
typedef std::shared_ptr<lldb_private::ScriptedStopHookInterface>
413+
ScriptedStopHookInterfaceSP;
411414
typedef std::shared_ptr<lldb_private::ScriptedThreadInterface>
412415
ScriptedThreadInterfaceSP;
413416
typedef std::shared_ptr<lldb_private::ScriptedThreadPlanInterface>

lldb/source/Interpreter/ScriptInterpreter.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,12 @@ ScriptInterpreter::GetOpaqueTypeFromSBMemoryRegionInfo(
125125
return *mem_region.m_opaque_up.get();
126126
}
127127

128+
lldb::ExecutionContextRefSP
129+
ScriptInterpreter::GetOpaqueTypeFromSBExecutionContext(
130+
const lldb::SBExecutionContext &exe_ctx) const {
131+
return exe_ctx.m_exe_ctx_sp;
132+
}
133+
128134
lldb::ScriptLanguage
129135
ScriptInterpreter::StringToLanguage(const llvm::StringRef &language) {
130136
if (language.equals_insensitive(LanguageToString(eScriptLanguageNone)))

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ add_lldb_library(lldbPluginScriptInterpreterPythonInterfaces PLUGIN
2525
ScriptedPlatformPythonInterface.cpp
2626
ScriptedProcessPythonInterface.cpp
2727
ScriptedPythonInterface.cpp
28+
ScriptedStopHookPythonInterface.cpp
2829
ScriptedThreadPlanPythonInterface.cpp
2930
ScriptedThreadPythonInterface.cpp
3031

lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,15 @@ void ScriptInterpreterPythonInterfaces::Initialize() {
2828
OperatingSystemPythonInterface::Initialize();
2929
ScriptedPlatformPythonInterface::Initialize();
3030
ScriptedProcessPythonInterface::Initialize();
31+
ScriptedStopHookPythonInterface::Initialize();
3132
ScriptedThreadPlanPythonInterface::Initialize();
3233
}
3334

3435
void ScriptInterpreterPythonInterfaces::Terminate() {
3536
OperatingSystemPythonInterface::Terminate();
3637
ScriptedPlatformPythonInterface::Terminate();
3738
ScriptedProcessPythonInterface::Terminate();
39+
ScriptedStopHookPythonInterface::Terminate();
3840
ScriptedThreadPlanPythonInterface::Terminate();
3941
}
4042

lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "OperatingSystemPythonInterface.h"
1919
#include "ScriptedPlatformPythonInterface.h"
2020
#include "ScriptedProcessPythonInterface.h"
21+
#include "ScriptedStopHookPythonInterface.h"
2122
#include "ScriptedThreadPlanPythonInterface.h"
2223

2324
namespace lldb_private {

lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,4 +159,23 @@ ScriptedPythonInterface::ExtractValueFromPythonObject<
159159
return m_interpreter.GetOpaqueTypeFromSBMemoryRegionInfo(*sb_mem_reg_info);
160160
}
161161

162+
template <>
163+
lldb::ExecutionContextRefSP
164+
ScriptedPythonInterface::ExtractValueFromPythonObject<
165+
lldb::ExecutionContextRefSP>(python::PythonObject &p, Status &error) {
166+
167+
lldb::SBExecutionContext *sb_exe_ctx =
168+
reinterpret_cast<lldb::SBExecutionContext *>(
169+
python::LLDBSWIGPython_CastPyObjectToSBExecutionContext(p.get()));
170+
171+
if (!sb_exe_ctx) {
172+
error = Status::FromErrorStringWithFormat(
173+
"Couldn't cast lldb::SBExecutionContext to "
174+
"lldb::ExecutionContextRefSP.");
175+
return {};
176+
}
177+
178+
return m_interpreter.GetOpaqueTypeFromSBExecutionContext(*sb_exe_ctx);
179+
}
180+
162181
#endif

lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -180,12 +180,35 @@ class ScriptedPythonInterface : virtual public ScriptedInterface {
180180
llvm::Expected<PythonObject> expected_return_object =
181181
create_error("Resulting object is not initialized.");
182182

183-
std::apply(
184-
[&init, &expected_return_object](auto &&...args) {
185-
llvm::consumeError(expected_return_object.takeError());
186-
expected_return_object = init(args...);
187-
},
188-
transformed_args);
183+
// This relax the requirement on the number of argument for
184+
// initializing scripting extension if the size of the interface
185+
// parameter pack contains 1 less element than the extension maximum
186+
// number of positional arguments for this initializer.
187+
//
188+
// This addresses the cases where the embedded interpreter session
189+
// dictionary is passed to the extension initializer which is not used
190+
// most of the time.
191+
size_t num_args = sizeof...(Args);
192+
if (num_args != arg_info->max_positional_args) {
193+
if (num_args != arg_info->max_positional_args - 1)
194+
return create_error("Passed arguments ({0}) doesn't match the number "
195+
"of expected arguments ({1}).",
196+
num_args, arg_info->max_positional_args);
197+
198+
std::apply(
199+
[&init, &expected_return_object](auto &&...args) {
200+
llvm::consumeError(expected_return_object.takeError());
201+
expected_return_object = init(args...);
202+
},
203+
std::tuple_cat(transformed_args, std::make_tuple(dict)));
204+
} else {
205+
std::apply(
206+
[&init, &expected_return_object](auto &&...args) {
207+
llvm::consumeError(expected_return_object.takeError());
208+
expected_return_object = init(args...);
209+
},
210+
transformed_args);
211+
}
189212

190213
if (!expected_return_object)
191214
return expected_return_object.takeError();
@@ -405,6 +428,10 @@ class ScriptedPythonInterface : virtual public ScriptedInterface {
405428
return python::SWIGBridge::ToSWIGWrapper(arg);
406429
}
407430

431+
python::PythonObject Transform(lldb::TargetSP arg) {
432+
return python::SWIGBridge::ToSWIGWrapper(arg);
433+
}
434+
408435
python::PythonObject Transform(lldb::ProcessSP arg) {
409436
return python::SWIGBridge::ToSWIGWrapper(arg);
410437
}
@@ -557,6 +584,11 @@ std::optional<MemoryRegionInfo>
557584
ScriptedPythonInterface::ExtractValueFromPythonObject<
558585
std::optional<MemoryRegionInfo>>(python::PythonObject &p, Status &error);
559586

587+
template <>
588+
lldb::ExecutionContextRefSP
589+
ScriptedPythonInterface::ExtractValueFromPythonObject<
590+
lldb::ExecutionContextRefSP>(python::PythonObject &p, Status &error);
591+
560592
} // namespace lldb_private
561593

562594
#endif // LLDB_ENABLE_PYTHON

0 commit comments

Comments
 (0)