-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathLLDB_Eigen_Data_Formatter.py
131 lines (103 loc) · 4.85 KB
/
LLDB_Eigen_Data_Formatter.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import lldb
import os
def __lldb_init_module (debugger, dict):
debugger.HandleCommand("type summary add -x \"Eigen::Matrix\" -F LLDB_Eigen_Data_Formatter.format_matrix")
debugger.HandleCommand("type summary add -x \"Eigen::Array\" -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)]
# Save the actual stdout (1) and stderr (2) file descriptors.
self.save_fds = (os.dup(1), os.dup(2))
def __enter__(self):
# Assign the null pointers to stdout and stderr.
os.dup2(self.null_fds[0],1)
os.dup2(self.null_fds[1],2)
def __exit__(self, *_):
# Re-assign the real stdout/stderr back to (1) and (2)
os.dup2(self.save_fds[0],1)
os.dup2(self.save_fds[1],2)
# Close the null files
os.close(self.null_fds[0])
os.close(self.null_fds[1])
def evaluate_expression(valobj, expr):
return valobj.GetProcess().GetSelectedThread().GetSelectedFrame().EvaluateExpression(expr)
def _row_element(valobj, row, rows, cols):
for i in range(row, rows*cols, rows):
yield valobj.GetChildAtIndex(i, lldb.eNoDynamicValues, True).GetValue()
def print_raw_matrix(valobj, rows, cols):
if rows*cols > 100:
return "[matrix too large]"
output = ""
# 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(valobj.GetChildAtIndex(i, lldb.eNoDynamicValues, True).GetValue())))
# print values
for j in range(0, rows):
if j!=0:
output += " "
output += "".join(val.rjust(padding+1, ' ') for val in _row_element(valobj, j, rows, cols)) + ";\n"
return output + " ]\n"
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()