Summary: Many times when debugging variables might not be available even though a user can successfully set breakpoints and stops somewhere. Letting the user know will help users fix these kinds of issues and have a better debugging experience. Examples of this include: - enabling -gline-tables-only and being able to set file and line breakpoints and yet see no variables - unable to open object file for DWARF in .o file debugging for darwin targets due to modification time mismatch or not being able to locate the N_OSO file. This patch adds an new API to SBValueList: lldb::SBError lldb::SBValueList::GetError(); object so that if you request a stack frame's variables using SBValueList SBFrame::GetVariables(...), you can get an error the describes why the variables were not available. This patch adds the ability to get an error back when requesting variables from a lldb_private::StackFrame when calling GetVariableList. It also now shows an error in response to "frame variable" if we have debug info and are unable to get varialbes due to an error as mentioned above: (lldb) frame variable error: "a.o" object from the "/tmp/libfoo.a" archive: either the .o file doesn't exist in the archive or the modification time (0x63111541) of the .o file doesn't match Reviewers: labath JDevlieghere aadsm yinghuitan jdoerfert sscalpone Subscribers: Differential Revision: https://reviews.llvm.org/D133164
176 lines
5.3 KiB
C++
176 lines
5.3 KiB
C++
//===-- SWIG Interface for SBValueList --------------------------*- C++ -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
namespace lldb {
|
|
|
|
%feature("docstring",
|
|
"Represents a collection of SBValues. Both :py:class:`SBFrame.GetVariables()` and
|
|
:py:class:`SBFrame.GetRegisters()` return a SBValueList.
|
|
|
|
SBValueList supports :py:class:`SBValue` iteration. For example (from test/lldbutil.py),::
|
|
|
|
def get_registers(frame, kind):
|
|
'''Returns the registers given the frame and the kind of registers desired.
|
|
|
|
Returns None if there's no such kind.
|
|
'''
|
|
registerSet = frame.GetRegisters() # Return type of SBValueList.
|
|
for value in registerSet:
|
|
if kind.lower() in value.GetName().lower():
|
|
return value
|
|
|
|
return None
|
|
|
|
def get_GPRs(frame):
|
|
'''Returns the general purpose registers of the frame as an SBValue.
|
|
|
|
The returned SBValue object is iterable. An example:
|
|
...
|
|
from lldbutil import get_GPRs
|
|
regs = get_GPRs(frame)
|
|
for reg in regs:
|
|
print('%s => %s' % (reg.GetName(), reg.GetValue()))
|
|
...
|
|
'''
|
|
return get_registers(frame, 'general purpose')
|
|
|
|
def get_FPRs(frame):
|
|
'''Returns the floating point registers of the frame as an SBValue.
|
|
|
|
The returned SBValue object is iterable. An example:
|
|
...
|
|
from lldbutil import get_FPRs
|
|
regs = get_FPRs(frame)
|
|
for reg in regs:
|
|
print('%s => %s' % (reg.GetName(), reg.GetValue()))
|
|
...
|
|
'''
|
|
return get_registers(frame, 'floating point')
|
|
|
|
def get_ESRs(frame):
|
|
'''Returns the exception state registers of the frame as an SBValue.
|
|
|
|
The returned SBValue object is iterable. An example:
|
|
...
|
|
from lldbutil import get_ESRs
|
|
regs = get_ESRs(frame)
|
|
for reg in regs:
|
|
print('%s => %s' % (reg.GetName(), reg.GetValue()))
|
|
...
|
|
'''
|
|
return get_registers(frame, 'exception state')
|
|
"
|
|
) SBValueList;
|
|
class SBValueList
|
|
{
|
|
public:
|
|
|
|
SBValueList ();
|
|
|
|
SBValueList (const lldb::SBValueList &rhs);
|
|
|
|
~SBValueList();
|
|
|
|
bool
|
|
IsValid() const;
|
|
|
|
explicit operator bool() const;
|
|
|
|
void
|
|
Clear();
|
|
|
|
void
|
|
Append (const lldb::SBValue &val_obj);
|
|
|
|
void
|
|
Append (const lldb::SBValueList& value_list);
|
|
|
|
uint32_t
|
|
GetSize() const;
|
|
|
|
lldb::SBValue
|
|
GetValueAtIndex (uint32_t idx) const;
|
|
|
|
lldb::SBValue
|
|
FindValueObjectByUID (lldb::user_id_t uid);
|
|
|
|
lldb::SBValue
|
|
GetFirstValueByName (const char* name) const;
|
|
|
|
lldb::SBError GetError();
|
|
|
|
%extend {
|
|
%nothreadallow;
|
|
std::string lldb::SBValueList::__str__ (){
|
|
lldb::SBStream description;
|
|
const size_t n = $self->GetSize();
|
|
if (n)
|
|
{
|
|
for (size_t i=0; i<n; ++i)
|
|
$self->GetValueAtIndex(i).GetDescription(description);
|
|
}
|
|
else
|
|
{
|
|
description.Printf("<empty> lldb.SBValueList()");
|
|
}
|
|
const char *desc = description.GetData();
|
|
size_t desc_len = description.GetSize();
|
|
if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r'))
|
|
--desc_len;
|
|
return std::string(desc, desc_len);
|
|
}
|
|
%clearnothreadallow;
|
|
}
|
|
|
|
#ifdef SWIGPYTHON
|
|
%pythoncode %{
|
|
def __iter__(self):
|
|
'''Iterate over all values in a lldb.SBValueList object.'''
|
|
return lldb_iter(self, 'GetSize', 'GetValueAtIndex')
|
|
|
|
def __len__(self):
|
|
return int(self.GetSize())
|
|
|
|
def __getitem__(self, key):
|
|
count = len(self)
|
|
#------------------------------------------------------------
|
|
# Access with "int" to get Nth item in the list
|
|
#------------------------------------------------------------
|
|
if type(key) is int:
|
|
if key < count:
|
|
return self.GetValueAtIndex(key)
|
|
#------------------------------------------------------------
|
|
# Access with "str" to get values by name
|
|
#------------------------------------------------------------
|
|
elif type(key) is str:
|
|
matches = []
|
|
for idx in range(count):
|
|
value = self.GetValueAtIndex(idx)
|
|
if value.name == key:
|
|
matches.append(value)
|
|
return matches
|
|
#------------------------------------------------------------
|
|
# Match with regex
|
|
#------------------------------------------------------------
|
|
elif isinstance(key, type(re.compile('.'))):
|
|
matches = []
|
|
for idx in range(count):
|
|
value = self.GetValueAtIndex(idx)
|
|
re_match = key.search(value.name)
|
|
if re_match:
|
|
matches.append(value)
|
|
return matches
|
|
|
|
%}
|
|
#endif
|
|
|
|
|
|
};
|
|
|
|
} // namespace lldb
|