LLDB mainline
ScriptedPythonInterface.cpp
Go to the documentation of this file.
1//===-- ScriptedPythonInterface.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-python.h"
10
12#include "lldb/API/SBValue.h"
14#include "lldb/Host/Config.h"
15#include "lldb/Utility/Log.h"
17
22#include <optional>
23
24using namespace lldb;
25using namespace lldb_private;
26
28 ScriptInterpreterPythonImpl &interpreter)
29 : ScriptedInterface(), m_interpreter(interpreter) {}
30
31template <>
32llvm::Expected<StructuredData::ArraySP>
36 return result_list.CreateStructuredArray();
37}
38
39template <>
40llvm::Expected<StructuredData::DictionarySP>
44 return result_dict.CreateStructuredDictionary();
45}
46
47template <>
48llvm::Expected<Status>
51 if (lldb::SBError *sb_error = reinterpret_cast<lldb::SBError *>(
53 return ScriptInterpreterBridge::GetStatus(*sb_error);
54 return llvm::createStringError("couldn't cast lldb::SBError to lldb::Status");
55}
56
57template <>
58llvm::Expected<Event *>
61 if (lldb::SBEvent *sb_event = reinterpret_cast<lldb::SBEvent *>(
63 return ScriptInterpreterBridge::GetEvent(*sb_event);
64 return llvm::createStringError(
65 "couldn't cast lldb::SBEvent to lldb_private::Event");
66}
67
68template <>
69llvm::Expected<CommandReturnObject *>
72 if (lldb::SBCommandReturnObject *sb_cmd_retobj =
73 reinterpret_cast<lldb::SBCommandReturnObject *>(
75 p.get())))
77 return llvm::createStringError("couldn't cast lldb::SBCommandReturnObject to "
78 "lldb_private::CommandReturnObject");
79}
80
81template <>
82llvm::Expected<lldb::StreamSP>
85 if (lldb::SBStream *sb_stream = reinterpret_cast<lldb::SBStream *>(
87 return ScriptInterpreterBridge::GetStream(*sb_stream);
88 return llvm::createStringError(
89 "couldn't cast lldb::SBStream to lldb_private::Stream");
90}
91
92template <>
93llvm::Expected<lldb::StackFrameSP>
96 if (lldb::SBFrame *sb_frame = reinterpret_cast<lldb::SBFrame *>(
99 return llvm::createStringError(
100 "couldn't cast lldb::SBFrame to lldb_private::StackFrame");
101}
102
103template <>
104llvm::Expected<lldb::ThreadSP>
107 if (lldb::SBThread *sb_thread = reinterpret_cast<lldb::SBThread *>(
109 return ScriptInterpreterBridge::GetThread(*sb_thread);
110 return llvm::createStringError(
111 "couldn't cast lldb::SBThread to lldb_private::Thread");
112}
113
114template <>
115llvm::Expected<SymbolContext>
118 if (lldb::SBSymbolContext *sb_symbol_context =
119 reinterpret_cast<lldb::SBSymbolContext *>(
121 return ScriptInterpreterBridge::GetSymbolContext(*sb_symbol_context);
122 return llvm::createStringError(
123 "couldn't cast lldb::SBSymbolContext to lldb_private::SymbolContext");
124}
125
126template <>
127llvm::Expected<lldb::DataExtractorSP>
130 lldb::SBData *sb_data = reinterpret_cast<lldb::SBData *>(
132
133 if (!sb_data) {
134 return llvm::createStringError(
135 "couldn't cast lldb::SBData to lldb::DataExtractorSP");
136 }
137
139}
140
141template <>
142llvm::Expected<lldb::BreakpointSP>
145 lldb::SBBreakpoint *sb_breakpoint = reinterpret_cast<lldb::SBBreakpoint *>(
147
148 if (!sb_breakpoint) {
149 return llvm::createStringError(
150 "couldn't cast lldb::SBBreakpoint to lldb::BreakpointSP");
151 }
152
153 return ScriptInterpreterBridge::GetBreakpoint(*sb_breakpoint);
154}
155
156template <>
157llvm::Expected<lldb::BreakpointLocationSP>
160 lldb::SBBreakpointLocation *sb_break_loc =
161 reinterpret_cast<lldb::SBBreakpointLocation *>(
163
164 if (!sb_break_loc) {
165 return llvm::createStringError(
166 "couldn't cast lldb::SBBreakpointLocation to "
167 "lldb::BreakpointLocationSP");
168 }
169
171}
172
173template <>
174llvm::Expected<lldb::ProcessAttachInfoSP>
177 lldb::SBAttachInfo *sb_attach_info = reinterpret_cast<lldb::SBAttachInfo *>(
179
180 if (!sb_attach_info) {
181 return llvm::createStringError(
182 "couldn't cast lldb::SBAttachInfo to lldb::ProcessAttachInfoSP");
183 }
184
185 return ScriptInterpreterBridge::GetProcessAttachInfo(*sb_attach_info);
186}
187
188template <>
189llvm::Expected<lldb::ProcessLaunchInfoSP>
192 lldb::SBLaunchInfo *sb_launch_info = reinterpret_cast<lldb::SBLaunchInfo *>(
194
195 if (!sb_launch_info) {
196 return llvm::createStringError(
197 "couldn't cast lldb::SBLaunchInfo to lldb::ProcessLaunchInfoSP");
198 }
199
200 return ScriptInterpreterBridge::GetProcessLaunchInfo(*sb_launch_info);
201}
202
203template <>
204llvm::Expected<lldb::ThreadPlanSP>
207 lldb::SBThreadPlan *sb_thread_plan = reinterpret_cast<lldb::SBThreadPlan *>(
209
210 if (!sb_thread_plan) {
211 return llvm::createStringError(
212 "couldn't cast lldb::SBThreadPlan to lldb::ThreadPlanSP");
213 }
214
215 return ScriptInterpreterBridge::GetThreadPlan(*sb_thread_plan);
216}
217
218template <>
219llvm::Expected<std::optional<MemoryRegionInfo>>
221 std::optional<MemoryRegionInfo>>(python::PythonObject &p) {
222
223 lldb::SBMemoryRegionInfo *sb_mem_reg_info =
224 reinterpret_cast<lldb::SBMemoryRegionInfo *>(
226
227 if (!sb_mem_reg_info) {
228 return llvm::createStringError("couldn't cast lldb::SBMemoryRegionInfo to "
229 "lldb_private::MemoryRegionInfo");
230 }
231
232 return ScriptInterpreterBridge::GetMemoryRegionInfo(*sb_mem_reg_info);
233}
234
235template <>
236llvm::Expected<lldb::ExecutionContextRefSP>
239
240 lldb::SBExecutionContext *sb_exe_ctx =
241 reinterpret_cast<lldb::SBExecutionContext *>(
243
244 if (!sb_exe_ctx) {
245 return llvm::createStringError("couldn't cast lldb::SBExecutionContext to "
246 "lldb::ExecutionContextRefSP");
247 }
248
250}
251
252template <>
253llvm::Expected<lldb::DescriptionLevel>
256 llvm::Expected<unsigned long long> unsigned_or_err = p.AsUnsignedLongLong();
257 if (!unsigned_or_err)
258 return unsigned_or_err.takeError();
259 unsigned long long unsigned_val = *unsigned_or_err;
261 return llvm::createStringError(
262 "value too large for lldb::DescriptionLevel");
263 return static_cast<lldb::DescriptionLevel>(unsigned_val);
264}
265
266template <>
267llvm::Expected<lldb::StepType>
270 llvm::Expected<unsigned long long> unsigned_or_err = p.AsUnsignedLongLong();
271 if (!unsigned_or_err)
272 return unsigned_or_err.takeError();
273 unsigned long long unsigned_val = *unsigned_or_err;
274 if (unsigned_val >= lldb::eStepTypeScripted)
275 return llvm::createStringError("value too large for lldb::StepType");
276 return static_cast<lldb::StepType>(unsigned_val);
277}
278
279template <>
280llvm::Expected<lldb::StackFrameListSP>
283
284 lldb::SBFrameList *sb_frame_list = reinterpret_cast<lldb::SBFrameList *>(
286
287 if (!sb_frame_list) {
288 return llvm::createStringError(
289 "couldn't cast lldb::SBFrameList to lldb::StackFrameListSP");
290 }
291
292 return ScriptInterpreterBridge::GetStackFrameList(*sb_frame_list);
293}
294
295template <>
296llvm::Expected<lldb::ValueObjectSP>
299 lldb::SBValue *sb_value = reinterpret_cast<lldb::SBValue *>(
301 if (!sb_value) {
302 return llvm::createStringError(
303 "couldn't cast lldb::SBValue to lldb::ValueObjectSP");
304 }
305
307}
308
309template <>
310llvm::Expected<lldb::TargetSP>
313 lldb::SBTarget *sb_target = reinterpret_cast<lldb::SBTarget *>(
315 if (!sb_target) {
316 return llvm::createStringError(
317 "couldn't cast lldb::SBTarget to lldb::TargetSP");
318 }
319
320 return ScriptInterpreterBridge::GetTarget(*sb_target);
321}
322
323template <>
324llvm::Expected<lldb::ValueObjectListSP>
327 // Two Python return shapes are accepted here so callers can go through
328 // Dispatch<ValueObjectListSP>() uniformly: an `SBValueList` wrapper
329 // (what most extension methods return) and a plain Python `list` of
330 // `SBValue` (what `get_recognized_arguments` is documented to return).
331 lldb::ValueObjectListSP out = std::make_shared<ValueObjectList>();
332 if (auto *sb_value_list = reinterpret_cast<lldb::SBValueList *>(
334 for (uint32_t i = 0, e = sb_value_list->GetSize(); i < e; ++i) {
335 SBValue value = sb_value_list->GetValueAtIndex(i);
336 out->Append(ScriptInterpreterBridge::GetValueObject(value));
337 }
338 return out;
339 }
340
341 // Fallback: a plain Python `list` of `SBValue`. Round-trip through
342 // `CreateStructuredObject` so we don't touch the `PyList_*` C API
343 // directly; unknown-shape items surface as `StructuredData::Generic`
344 // holding their opaque `PyObject*`, which we hand back to SWIG to
345 // recover the SBValue wrapper.
347 StructuredData::Array *arr = structured ? structured->GetAsArray() : nullptr;
348 if (arr) {
349 size_t index = 0;
350 llvm::Error extract_error = llvm::Error::success();
351 arr->ForEach([&](StructuredData::Object *item) {
352 const size_t item_index = index++;
353 StructuredData::Generic *generic = item ? item->GetAsGeneric() : nullptr;
354 if (!generic) {
355 // Keep walking the list so a malformed one names every bad item
356 // rather than only the first.
357 extract_error =
358 llvm::joinErrors(std::move(extract_error),
359 llvm::createStringError(llvm::formatv(
360 "ValueObjectList item at index {0} is not a "
361 "StructuredData::Generic",
362 item_index)));
363 return true;
364 }
365 auto *sb_value = reinterpret_cast<lldb::SBValue *>(
367 static_cast<PyObject *>(generic->GetValue())));
368 if (sb_value)
369 if (auto valobj_sp = ScriptInterpreterBridge::GetValueObject(*sb_value))
370 out->Append(valobj_sp);
371 return true;
372 });
373 if (extract_error)
374 return std::move(extract_error);
375 return out;
376 }
377
378 return llvm::createStringError(
379 "couldn't extract ValueObjectList from Python return value");
380}
381
382template <>
383llvm::Expected<std::optional<lldb::ValueType>>
385 std::optional<lldb::ValueType>>(python::PythonObject &p) {
386 if (p.IsNone())
387 return std::nullopt;
388
389 llvm::Expected<unsigned long long> val = p.AsUnsignedLongLong();
390 if (!val)
391 return val.takeError();
392 unsigned long long unmasked = *val & ~kValueTypeFlagsMask;
393 unsigned long long flags = *val & kValueTypeFlagsMask;
394 if (unmasked == eValueTypeInvalid || unmasked > kLastValueType)
395 return llvm::createStringError(llvm::formatv(
396 "value type invalid or too large (got {0} | {1:x})", unmasked, flags));
397
398 return static_cast<ValueType>(unmasked | flags);
399}
400
401template <>
402llvm::Expected<lldb::DebuggerSP>
405 if (lldb::SBDebugger *sb_dbg = reinterpret_cast<lldb::SBDebugger *>(
408 return llvm::createStringError(
409 "couldn't cast lldb::SBDebugger to lldb::DebuggerSP");
410}
411
412template <>
413llvm::Expected<std::vector<std::string>>
416 std::vector<std::string> result;
418 if (!list.IsValid()) {
419 return llvm::createStringError(
420 "couldn't extract std::vector<std::string>: not a Python list");
421 }
422
423 const uint32_t size = list.GetSize();
424 result.reserve(size);
425 for (uint32_t i = 0; i < size; ++i) {
427 list.GetItemAtIndex(i).get());
428 if (!item.IsValid())
429 continue;
430 result.push_back(item.GetString().str());
431 }
432 return result;
433}
static SymbolContext GetSymbolContext(const lldb::SBSymbolContext &sym_ctx)
static lldb::DataExtractorSP GetDataExtractor(const lldb::SBData &data)
static lldb::BreakpointLocationSP GetBreakpointLocation(const lldb::SBBreakpointLocation &break_loc)
static lldb::ProcessLaunchInfoSP GetProcessLaunchInfo(const lldb::SBLaunchInfo &launch_info)
static CommandReturnObject * GetCommandReturnObject(const lldb::SBCommandReturnObject &cmd_retobj)
static lldb::BreakpointSP GetBreakpoint(const lldb::SBBreakpoint &breakpoint)
static lldb::ThreadSP GetThread(const lldb::SBThread &thread)
static lldb::ExecutionContextRefSP GetExecutionContextRef(const lldb::SBExecutionContext &exe_ctx)
static lldb::TargetSP GetTarget(const lldb::SBTarget &target)
static lldb::DebuggerSP GetDebugger(const lldb::SBDebugger &debugger)
static lldb::ProcessAttachInfoSP GetProcessAttachInfo(const lldb::SBAttachInfo &attach_info)
static lldb::StackFrameSP GetStackFrame(const lldb::SBFrame &frame)
static lldb::StackFrameListSP GetStackFrameList(const lldb::SBFrameList &frame_list)
static lldb::StreamSP GetStream(const lldb::SBStream &stream)
static Event * GetEvent(const lldb::SBEvent &event)
static std::optional< MemoryRegionInfo > GetMemoryRegionInfo(const lldb::SBMemoryRegionInfo &mem_region)
static lldb::ValueObjectSP GetValueObject(const lldb::SBValue &value)
static lldb::ThreadPlanSP GetThreadPlan(const lldb::SBThreadPlan &thread_plan)
static Status GetStatus(const lldb::SBError &error)
ScriptInterpreterPythonImpl & m_interpreter
llvm::Expected< T > ExtractValueFromPythonObject(python::PythonObject &p)
ScriptedPythonInterface(ScriptInterpreterPythonImpl &interpreter)
bool ForEach(std::function< bool(Object *object)> const &foreach_callback) const
std::shared_ptr< Dictionary > DictionarySP
std::shared_ptr< Object > ObjectSP
StructuredData::ObjectSP CreateStructuredObject() const
llvm::Expected< unsigned long long > AsUnsignedLongLong() const
void * LLDBSWIGPython_CastPyObjectToSBExecutionContext(PyObject *data)
void * LLDBSWIGPython_CastPyObjectToSBFrameList(PyObject *data)
void * LLDBSWIGPython_CastPyObjectToSBThread(PyObject *data)
void * LLDBSWIGPython_CastPyObjectToSBData(PyObject *data)
void * LLDBSWIGPython_CastPyObjectToSBTarget(PyObject *data)
void * LLDBSWIGPython_CastPyObjectToSBSymbolContext(PyObject *data)
void * LLDBSWIGPython_CastPyObjectToSBStream(PyObject *data)
void * LLDBSWIGPython_CastPyObjectToSBCommandReturnObject(PyObject *data)
void * LLDBSWIGPython_CastPyObjectToSBMemoryRegionInfo(PyObject *data)
void * LLDBSWIGPython_CastPyObjectToSBDebugger(PyObject *data)
void * LLDBSWIGPython_CastPyObjectToSBBreakpointLocation(PyObject *data)
void * LLDBSWIGPython_CastPyObjectToSBError(PyObject *data)
void * LLDBSWIGPython_CastPyObjectToSBAttachInfo(PyObject *data)
void * LLDBSWIGPython_CastPyObjectToSBThreadPlan(PyObject *data)
void * LLDBSWIGPython_CastPyObjectToSBLaunchInfo(PyObject *data)
void * LLDBSWIGPython_CastPyObjectToSBValueList(PyObject *data)
void * LLDBSWIGPython_CastPyObjectToSBValue(PyObject *data)
void * LLDBSWIGPython_CastPyObjectToSBEvent(PyObject *data)
void * LLDBSWIGPython_CastPyObjectToSBBreakpoint(PyObject *data)
void * LLDBSWIGPython_CastPyObjectToSBFrame(PyObject *data)
A class that represents a running process on the host machine.
class LLDB_API SBStream
Definition SBDefines.h:111
class LLDB_API SBThread
Definition SBDefines.h:118
std::shared_ptr< lldb_private::BreakpointLocation > BreakpointLocationSP
DescriptionLevel
Description levels for "void GetDescription(Stream *, DescriptionLevel)" calls.
@ kNumDescriptionLevels
class LLDB_API SBValueList
Definition SBDefines.h:138
std::shared_ptr< lldb_private::ProcessAttachInfo > ProcessAttachInfoSP
class LLDB_API SBExecutionContext
Definition SBDefines.h:73
class LLDB_API SBTarget
Definition SBDefines.h:117
std::shared_ptr< lldb_private::ValueObjectList > ValueObjectListSP
class LLDB_API SBFrameList
Definition SBDefines.h:80
class LLDB_API SBAttachInfo
Definition SBDefines.h:49
class LLDB_API SBBreakpointLocation
Definition SBDefines.h:53
class LLDB_API SBMemoryRegionInfo
Definition SBDefines.h:89
class LLDB_API SBEvent
Definition SBDefines.h:71
@ eStepTypeScripted
A step type implemented by the script interpreter.
@ kValueTypeFlagsMask
class LLDB_API SBThreadPlan
Definition SBDefines.h:120
class LLDB_API SBError
Definition SBDefines.h:70
class LLDB_API SBFrame
Definition SBDefines.h:79
class LLDB_API SBBreakpoint
Definition SBDefines.h:51
class LLDB_API SBSymbolContext
Definition SBDefines.h:115
class LLDB_API SBValue
Definition SBDefines.h:137
class LLDB_API SBDebugger
Definition SBDefines.h:67
std::shared_ptr< lldb_private::ProcessLaunchInfo > ProcessLaunchInfoSP
class LLDB_API SBData
Definition SBDefines.h:66
class LLDB_API SBCommandReturnObject
Definition SBDefines.h:62
class LLDB_API SBLaunchInfo
Definition SBDefines.h:86
std::shared_ptr< lldb_private::ExecutionContextRef > ExecutionContextRefSP