Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
520 changes: 423 additions & 97 deletions lldb/bindings/python/static-binding/LLDBWrapPython.cpp

Large diffs are not rendered by default.

54 changes: 54 additions & 0 deletions lldb/bindings/python/static-binding/lldb.py
Original file line number Diff line number Diff line change
Expand Up @@ -7336,6 +7336,10 @@ def IsArtificial(self, *args):
"""
return _lldb.SBFrame_IsArtificial(self, *args)

def IsSynthetic(self):
r"""IsSynthetic(SBFrame self) -> bool"""
return _lldb.SBFrame_IsSynthetic(self)

def IsHidden(self):
r"""
Return whether a frame recognizer decided this frame should not
Expand Down Expand Up @@ -12231,6 +12235,56 @@ def GetGenericValue(self):
r"""Return the generic pointer if this data structure is a generic type."""
return _lldb.SBStructuredData_GetGenericValue(self)

def SetValueForKey(self, key, value):
r"""
Set the value corresponding to a key. If this data structure
is not a dictionary type, reset the type to be dictionary and overwrite
the previous data.
"""
return _lldb.SBStructuredData_SetValueForKey(self, key, value)

def SetUnsignedIntegerValue(self, value):
r"""
Change the type to unsigned interger and overwrite the previous data with
the new value.
"""
return _lldb.SBStructuredData_SetUnsignedIntegerValue(self, value)

def SetSignedIntegerValue(self, value):
r"""
Change the type to signed interger and overwrite the previous data with
the new value.
"""
return _lldb.SBStructuredData_SetSignedIntegerValue(self, value)

def SetFloatValue(self, value):
r"""
Change the type to float and overwrite the previous data with the new
value.
"""
return _lldb.SBStructuredData_SetFloatValue(self, value)

def SetBooleanValue(self, value):
r"""
Change the type to boolean and overwrite the previous data with the new
value.
"""
return _lldb.SBStructuredData_SetBooleanValue(self, value)

def SetStringValue(self, value):
r"""
Change the type to string and overwrite the previous data with the new
value.
"""
return _lldb.SBStructuredData_SetStringValue(self, value)

def SetGenericValue(self, value):
r"""
Change the type to generic and overwrite the previous data with the new
value.
"""
return _lldb.SBStructuredData_SetGenericValue(self, value)

def __repr__(self):
r"""__repr__(SBStructuredData self) -> std::string"""
return _lldb.SBStructuredData___repr__(self)
Expand Down
11 changes: 7 additions & 4 deletions lldb/examples/python/crashlog.py
Original file line number Diff line number Diff line change
Expand Up @@ -1540,23 +1540,26 @@ def load_crashlog_in_scripted_process(debugger, crashlog_path, options, result):
}
)
)

crashlog_sd = lldb.SBStructuredData()
crashlog_sd.SetGenericValue(
lldb.SBScriptObject(crashlog, lldb.eScriptLanguagePython)
)
structured_data.SetValueForKey("crashlog", crashlog_sd)

launch_info = lldb.SBLaunchInfo(None)
launch_info.SetProcessPluginName("ScriptedProcess")
launch_info.SetScriptedProcessClassName(
"crashlog_scripted_process.CrashLogScriptedProcess"
)
launch_info.SetScriptedProcessDictionary(structured_data)
launch_info.SetLaunchFlags(lldb.eLaunchFlagStopAtEntry)

error = lldb.SBError()
process = target.Launch(launch_info, error)

if not process or error.Fail():
raise InteractiveCrashLogException("couldn't launch Scripted Process", error)

process.GetScriptedImplementation().set_crashlog(crashlog)
process.Continue()

if not options.skip_status:

@contextlib.contextmanager
Expand Down
20 changes: 14 additions & 6 deletions lldb/examples/python/crashlog_scripted_process.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@


class CrashLogScriptedProcess(ScriptedProcess):
def set_crashlog(self, crashlog):
self.crashlog = crashlog
def parse_crashlog(self):
if self.crashlog.process_id:
if type(self.crashlog.process_id) is int:
self.pid = self.crashlog.process_id
Expand All @@ -29,8 +28,6 @@ def set_crashlog(self, crashlog):
if hasattr(self.crashlog, "asb"):
self.extended_thread_info = self.crashlog.asb

crashlog.load_images(self.options, self.loaded_images)

for thread in self.crashlog.threads:
if (
hasattr(thread, "app_specific_backtrace")
Expand Down Expand Up @@ -92,10 +89,21 @@ def __init__(self, exe_ctx: lldb.SBExecutionContext, args: lldb.SBStructuredData
no_parallel_image_loading.GetBooleanValue()
)

self.crashlog = None
crashlog = args.GetValueForKey("crashlog")
if crashlog and crashlog.IsValid():
if crashlog.GetType() == lldb.eStructuredDataTypeGeneric:
self.crashlog = crashlog.GetGenericValue()

if not self.crashlog:
# Return error
return

self.pid = super().get_process_id()
self.crashed_thread_idx = 0
self.exception = None
self.extended_thread_info = None
self.parse_crashlog()

def read_memory_at_address(
self, addr: int, size: int, error: lldb.SBError
Expand All @@ -104,8 +112,8 @@ def read_memory_at_address(
return lldb.SBData()

def get_loaded_images(self):
# TODO: Iterate over corefile_target modules and build a data structure
# from it.
if len(self.loaded_images) == 0:
self.crashlog.load_images(self.options, self.loaded_images)
return self.loaded_images

def should_stop(self) -> bool:
Expand Down
136 changes: 136 additions & 0 deletions lldb/examples/python/templates/scripted_process.py
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,142 @@ def get_extended_info(self):
"""
return self.extended_info

def get_scripted_frame_plugin(self):
"""Get scripted frame plugin name.

Returns:
str: Name of the scripted frame plugin.
"""
return None


class ScriptedFrame(metaclass=ABCMeta):
"""
The base class for a scripted frame.

Most of the base class methods are `@abstractmethod` that need to be
overwritten by the inheriting class.
"""

@abstractmethod
def __init__(self, thread, args):
"""Construct a scripted frame.

Args:
thread (ScriptedThread): The thread owning this frame.
args (lldb.SBStructuredData): A Dictionary holding arbitrary
key/value pairs used by the scripted frame.
"""
self.target = None
self.originating_thread = None
self.thread = None
self.args = None
self.id = None
self.name = None
self.register_info = None
self.register_ctx = {}
self.variables = []

if (
isinstance(thread, ScriptedThread)
or isinstance(thread, lldb.SBThread)
and thread.IsValid()
):
self.target = thread.target
self.process = thread.process
self.originating_thread = thread
self.thread = self.process.GetThreadByIndexID(thread.tid)
self.get_register_info()

@abstractmethod
def get_id(self):
"""Get the scripted frame identifier.

Returns:
int: The identifier of the scripted frame in the scripted thread.
"""
pass

def get_pc(self):
"""Get the scripted frame address.

Returns:
int: The optional address of the scripted frame in the scripted thread.
"""
return None

def get_symbol_context(self):
"""Get the scripted frame symbol context.

Returns:
lldb.SBSymbolContext: The symbol context of the scripted frame in the scripted thread.
"""
return None

def is_inlined(self):
"""Check if the scripted frame is inlined.

Returns:
bool: True if scripted frame is inlined. False otherwise.
"""
return False

def is_artificial(self):
"""Check if the scripted frame is artificial.

Returns:
bool: True if scripted frame is artificial. False otherwise.
"""
return True

def is_hidden(self):
"""Check if the scripted frame is hidden.

Returns:
bool: True if scripted frame is hidden. False otherwise.
"""
return False

def get_function_name(self):
"""Get the scripted frame function name.

Returns:
str: The function name of the scripted frame.
"""
return self.name

def get_display_function_name(self):
"""Get the scripted frame display function name.

Returns:
str: The display function name of the scripted frame.
"""
return self.get_function_name()

def get_variables(self, filters):
"""Get the scripted thread state type.

Args:
filter (lldb.SBVariablesOptions): The filter used to resolve the variables
Returns:
lldb.SBValueList: The SBValueList containing the SBValue for each resolved variable.
Returns None by default.
"""
return None

def get_register_info(self):
if self.register_info is None:
self.register_info = self.originating_thread.get_register_info()
return self.register_info

@abstractmethod
def get_register_context(self):
"""Get the scripted thread register context

Returns:
str: A byte representing all register's value.
"""
pass

class PassthroughScriptedProcess(ScriptedProcess):
driving_target = None
Expand Down
2 changes: 2 additions & 0 deletions lldb/include/lldb/API/SBFrame.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ class LLDB_API SBFrame {

bool IsArtificial() const;

bool IsSynthetic() const;

/// Return whether a frame recognizer decided this frame should not
/// be displayes in backtraces etc.
bool IsHidden() const;
Expand Down
29 changes: 29 additions & 0 deletions lldb/include/lldb/API/SBStructuredData.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,35 @@ class SBStructuredData {
/// Return the generic pointer if this data structure is a generic type.
lldb::SBScriptObject GetGenericValue() const;

/// Set the value corresponding to a key. If this data structure
/// is not a dictionary type, reset the type to be dictionary and overwrite
/// the previous data.
void SetValueForKey(const char *key, SBStructuredData &value);

/// Change the type to unsigned interger and overwrite the previous data with
/// the new value.
void SetUnsignedIntegerValue(uint64_t value);

/// Change the type to signed interger and overwrite the previous data with
/// the new value.
void SetSignedIntegerValue(int64_t value);

/// Change the type to float and overwrite the previous data with the new
/// value.
void SetFloatValue(double value);

/// Change the type to boolean and overwrite the previous data with the new
/// value.
void SetBooleanValue(bool value);

/// Change the type to string and overwrite the previous data with the new
/// value.
void SetStringValue(const char *value);

/// Change the type to generic and overwrite the previous data with the new
/// value.
void SetGenericValue(SBScriptObject value);

protected:
friend class SBAttachInfo;
friend class SBCommandReturnObject;
Expand Down
1 change: 1 addition & 0 deletions lldb/include/lldb/API/SBSymbolContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ class LLDB_API SBSymbolContext {
friend class SBTarget;
friend class SBSymbolContextList;

friend class lldb_private::ScriptInterpreter;
friend class lldb_private::python::SWIGBridge;

SBSymbolContext(const lldb_private::SymbolContext &sc_ptr);
Expand Down
1 change: 1 addition & 0 deletions lldb/include/lldb/Core/FormatEntity.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ struct Entry {
FrameRegisterFlags,
FrameRegisterByName,
FrameIsArtificial,
FrameKind,
ScriptFrame,
FunctionID,
FunctionDidChange,
Expand Down
35 changes: 35 additions & 0 deletions lldb/include/lldb/Core/StructuredDataImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,41 @@ class StructuredDataImpl {

void SetObjectSP(const StructuredData::ObjectSP &obj) { m_data_sp = obj; }

void SetValueForKey(llvm::StringRef key,
const StructuredData::ObjectSP &value) {
if (!m_data_sp ||
m_data_sp->GetType() != lldb::eStructuredDataTypeDictionary) {
m_data_sp = StructuredData::FromKeyValue(key, value);
} else if (StructuredData::Dictionary *dict =
m_data_sp->GetAsDictionary()) {
dict->AddItem(key, value);
}
}

void SetUnsignedIntegerValue(uint64_t value) {
m_data_sp = StructuredData::FromInteger(value);
}

void SetSignedIntegerValue(int64_t value) {
m_data_sp = StructuredData::FromInteger(value);
}

void SetFloatValue(double value) {
m_data_sp = StructuredData::FromFloat(value);
}

void SetBooleanValue(bool value) {
m_data_sp = StructuredData::FromBoolean(value);
}

void SetStringValue(std::string value) {
m_data_sp = StructuredData::FromString(std::move(value));
}

void SetGenericValue(void *value) {
m_data_sp = StructuredData::FromGeneric(value);
}

lldb::StructuredDataType GetType() const {
return (m_data_sp ? m_data_sp->GetType() :
lldb::eStructuredDataTypeInvalid);
Expand Down
Loading