Skip to content

Commit

Permalink
Implemented support for dynamically sized matrices properly
Browse files Browse the repository at this point in the history
  • Loading branch information
Till Ehrengruber committed Aug 25, 2018
1 parent e5d5cb2 commit 7a07dc1
Showing 1 changed file with 83 additions and 52 deletions.
135 changes: 83 additions & 52 deletions LLDB_Eigen_Data_Formatter.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
import os

def __lldb_init_module (debugger, dict):
debugger.HandleCommand("type summary add -x \"Eigen::\" -F LLDB_Eigen_Data_Formatter.format")
debugger.HandleCommand("type summary add -x \"Eigen::Matrix\" -F LLDB_Eigen_Data_Formatter.format_matrix")

# Define a context manager to suppress stdout and stderr.
# see http://stackoverflow.com/questions/11130156/suppress-stdout-stderr-print-from-python-functions
class suppress_stdout_stderr(object):
def __init__(self):
# Open a pair of null files
self.null_fds = [os.open(os.devnull,os.O_RDWR) for x in range(2)]
self.null_fds = [os.open(os.devnull,os.O_RDWR) for x in xrange(2)]
# Save the actual stdout (1) and stderr (2) file descriptors.
self.save_fds = (os.dup(1), os.dup(2))

Expand All @@ -29,69 +29,100 @@ def __exit__(self, *_):
def evaluate_expression(valobj, expr):
return valobj.GetProcess().GetSelectedThread().GetSelectedFrame().EvaluateExpression(expr)

def format (valobj,internal_dict):
# fetch data
data = valobj.GetValueForExpressionPath(".m_storage.m_data.array")
num_data_elements = data.GetNumChildren()
rows = cols = 0
fixed_size = data.IsValid()

# return usual summary if storage can not be accessed
if fixed_size:
# determine expression path of the current valobj
stream = lldb.SBStream()
valobj.GetExpressionPath(stream)
valobj_expression_path = stream.GetData()

# determine rows and cols
with suppress_stdout_stderr():
rows = evaluate_expression(valobj, valobj_expression_path+".rows()").GetValueAsSigned()
cols = evaluate_expression(valobj, valobj_expression_path+".cols()").GetValueAsSigned()
#rows = lldb.frame.EvaluateExpression(valobj_expression_path+".rows()").GetValueAsSigned()
#cols = lldb.frame.EvaluateExpression(valobj_expression_path+".cols()").GetValueAsSigned()

#print(valobj.CreateValueFromExpression("bla", valobj_expression_path+".rows()"))

else:
data = valobj.GetValueForExpressionPath(".m_storage.m_data")
tr = valobj.GetValueForExpressionPath(".m_storage").GetChildMemberWithName('m_rows')
tc = valobj.GetValueForExpressionPath(".m_storage").GetChildMemberWithName('m_cols')
if tr.IsValid():
rows = tr.GetValueAsSigned()
if tc.IsValid():
cols = tc.GetValueAsUnsigned()
else:
# object likely a dynamic vector (need at least one column)
cols = 1

def print_raw_matrix(valobj, rows, cols):
output = ""

# check that the data layout fits a regular dense matrix
if fixed_size and rows*cols != num_data_elements:
print("error: eigen data formatter: could not infer data layout. printing raw data instead")
cols = 1
rows = num_data_elements

# print matrix dimensions
output += "rows: " + str(rows) + ", cols: " + str(cols) + "\n["

# determine padding
padding = 1
for i in range(0, rows*cols):
padding = max(padding, len(str(data.GetChildAtIndex(i).GetValue())))
for i in xrange(0, rows*cols):
padding = max(padding, len(str(valobj.GetChildAtIndex(i, lldb.eNoDynamicValues, True).GetValue())))

# print values
for i in range(0,rows):
for i in xrange(0,rows):
if i!=0:
output += " "

for j in range(0,cols):
val = data.GetChildAtIndex(j+i*cols, 0, 1).GetValue()
output += str(val).rjust(padding+1, ' ')

for j in xrange(0,cols):
val = valobj.GetChildAtIndex(j+i*cols, lldb.eNoDynamicValues, True).GetValue()
output += val.rjust(padding+1, ' ')
if i!=rows-1:
output += ";\n"

output+=" ]\n"

return output

def fixed_sized_matrix_to_string(valobj):
data = valobj.GetValueForExpressionPath(".m_storage.m_data.array")
num_data_elements = data.GetNumChildren()

# return usual summary if storage can not be accessed
if not data.IsValid():
return valobj.GetSummary()

# determine expression path of the current valobj
stream = lldb.SBStream()
valobj.GetExpressionPath(stream)
valobj_expression_path = stream.GetData()

# determine rows and cols
rows = cols = 0
with suppress_stdout_stderr():
# todo: check result is valid
rows = evaluate_expression(valobj, valobj_expression_path+".rows()").GetValueAsSigned()
cols = evaluate_expression(valobj, valobj_expression_path+".cols()").GetValueAsSigned()
#rows = lldb.frame.EvaluateExpression(valobj_expression_path+".rows()").GetValueAsSigned()
#cols = lldb.frame.EvaluateExpression(valobj_expression_path+".cols()").GetValueAsSigned()

#print(valobj.CreateValueFromExpression("bla", valobj_expression_path+".rows()"))

# check that the data layout fits a regular dense matrix
if rows*cols != num_data_elements:
print("error: eigen data formatter: could not infer data layout. printing raw data instead")
cols = 1
rows = num_data_elements

return print_raw_matrix(data, rows, cols)

def dynamically_sized_matrix_to_string(valobj):
data = valobj.GetValueForExpressionPath(".m_storage.m_data")
num_data_elements = data.GetNumChildren()

# return usual summary if storage can not be accessed
if not data.IsValid():
return valobj.GetSummary()

# determine expression path of the current valobj
stream = lldb.SBStream()
valobj.GetExpressionPath(stream)
valobj_expression_path = stream.GetData()

# determine rows and cols
rows = cols = 0
with suppress_stdout_stderr():
# todo: check result is valid
rows = evaluate_expression(valobj, valobj_expression_path+".rows()").GetValueAsSigned()
cols = evaluate_expression(valobj, valobj_expression_path+".cols()").GetValueAsSigned()

# try to access last value (if this throws an exception the matrix is probably not declared yet)
memory_accessable = True
try:
valobj.GetChildAtIndex(rows*cols, lldb.eNoDynamicValues, True).GetValue()
except:
memory_accessable = False

if not memory_accessable:
return "[uninitialized]"

return print_raw_matrix(data, rows, cols)

def format_matrix(valobj,internal_dict):
# determine type
if valobj.GetValueForExpressionPath(".m_storage.m_data.array").IsValid():
return fixed_sized_matrix_to_string(valobj)
elif valobj.GetValueForExpressionPath(".m_storage.m_data").GetType().IsPointerType():
return dynamically_sized_matrix_to_string(valobj)
else:
return valobj.GetSummary()

0 comments on commit 7a07dc1

Please sign in to comment.