I'm sorry in advance, if it's not a correct mailing list, there doesn't
seem to be lldb-usage mailing list.
I'm writing a pretty-printer python script, which - to cut to the chase,
pretty prints members of a class by using EvaluateExpression and creating
new object inside it. It doesn't seem to work - i'm getting "<could not
resolve type>" error. Should my idea work in a first place and i't s a bug
or it shouldn't and i need to find a different solution?
I'm attaching a repro case:
clang++ q.cpp -g -o o -std=c++20
lldb o
command script import lldb_script.py
br set --file q.cpp --line 19
r
print c
it prints:
(lldb) print c
(C) $0 = CCC {
= <could not resolve type>
}
it should something akin to:
(lldb) print c
(C) $0 = CCC {
b = B {
a = A {
id = "qwerty"
}
}
}
#include <iostream>
#include <string>
#include <string_view>
struct A {
std::string_view id() const { return "qwerty"; }
};
struct B {
A a() const { return A(); }
};
struct C {
B b() const { return B(); }
};
int main()
{
C c;
return 0;
}
import lldb.formatters.Logger
import lldb
import logging
import sys
import codecs
import platform
import json
logger = lldb.formatters.Logger.Logger()
logfile = codecs.open('log.txt', 'wb', encoding='utf8')
log = logging.getLogger()
log.setLevel(logging.INFO)
FORMAT = "[%(filename)s:%(lineno)s] %(message)s"
if log.handlers:
log.handlers[0].setFormatter(logging.Formatter(FORMAT))
ch = logging.StreamHandler(logfile)
ch.setLevel(logging.DEBUG)
formatter = logging.Formatter(FORMAT)
ch.setFormatter(formatter)
log.addHandler(ch)
log.error('-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------')
log.error('starting')
module = sys.modules[__name__]
if sys.version_info[0] == 2:
# python2-based LLDB accepts utf8-encoded ascii strings only.
def to_lldb_str(s): return s.encode(
'utf8', 'backslashreplace') if isinstance(s, unicode) else s
range = xrange
else:
to_lldb_str = str
log = logging.getLogger(__name__)
class V(object):
def __init__(self, v, dict=None):
self.v = v
def EvaluateExpression(self, expr, name=None):
v = self.v.CreateValueFromExpression(name, expr).dynamic
assert v
return V(v)
class Base(V):
regex = False
def get_summary(self):
return ''
def update(self):
pass
def num_children(self):
return 0
def has_children(self):
return False
def get_child_at_index(self, index):
return None
def get_child_index(self, name):
return -1
class cc_A(Base):
type = 'A'
regex = False
def num_children(self):
return 1
def has_children(self):
return True
def get_child_at_index(self, index):
assert index == 0
v = self.EvaluateExpression(f"id()", f'id')
return v.v
class cc_B(Base):
type = 'B'
regex = False
def num_children(self):
return 1
def has_children(self):
return True
def get_child_at_index(self, index):
assert index == 0
v = self.EvaluateExpression(f"a()", f'a')
return v.v
class cc_C(Base):
type = 'C'
regex = False
def get_summary(self):
return 'CCC'
def num_children(self):
return 1
def has_children(self):
return True
def get_child_at_index(self, index):
assert index == 0
return self.EvaluateExpression(f"b()").v
def initialize_category(debugger):
global module, std_category
std_category = debugger.CreateCategory('C++')
std_category.SetEnabled(True)
glob = globals()
todo = []
log.error('initialize_category')
def add(a, b, c, d):
todo.append(lambda: a(b, c, d))
for x, c in glob.items():
if x.startswith('ff_'):
if isinstance(c.type, list):
for t in c.type:
add(attach_summary_to_type, c, t, c.regex)
else:
add(attach_summary_to_type, c, c.type, c.regex)
elif x.startswith('cc_'):
if isinstance(c.type, list):
for t in c.type:
add(attach_synthetic_to_type, c, t, c.regex)
else:
add(attach_synthetic_to_type, c, c.type, c.regex)
for d in todo:
d()
def attach_synthetic_to_type(synth_class, type_name, is_regex=False):
global module, std_category
#log.info('attaching synthetic %s to "%s", is_regex=%s', synth_class.__name__, type_name, is_regex)
synth = lldb.SBTypeSynthetic.CreateWithClassName(
__name__ + '.' + synth_class.__name__)
synth.SetOptions(lldb.eTypeOptionCascade)
std_category.AddTypeSynthetic(
lldb.SBTypeNameSpecifier(type_name, is_regex), synth)
def summary_fn(valobj, dict): return get_synth_summary(synth_class, valobj, dict)
# LLDB accesses summary fn's by name, so we need to create a unique one.
summary_fn.__name__ = '_get_synth_summary_' + synth_class.__name__
setattr(module, summary_fn.__name__, summary_fn)
attach_summary_to_type(summary_fn, type_name, is_regex)
def attach_summary_to_type(summary_fn, type_name, is_regex=False):
global module, std_category
#log.info('attaching summary %s to "%s", is_regex=%s', summary_fn.__name__, type_name, is_regex)
summary = lldb.SBTypeSummary.CreateWithFunctionName(
__name__ + '.' + summary_fn.__name__)
summary.SetOptions(lldb.eTypeOptionCascade)
std_category.AddTypeSummary(
lldb.SBTypeNameSpecifier(type_name, is_regex), summary)
def get_synth_summary(synth_class, valobj, dict):
synth = synth_class(valobj.GetNonSyntheticValue())
synth.update()
summary = synth.get_summary()
return to_lldb_str(summary)
def __lldb_init_module(debugger, dict):
initialize_category(debugger)
_map_capping_size = 255
_list_capping_size = 255
_list_uses_loop_detector = True
_deque_capping_size = 255
_______________________________________________
lldb-dev mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev