LLDB数据格式化程序可以调用方法吗?

时间:2014-08-18 18:52:49

标签: qt getter lldb formatter

我正在使用LLDB调试Qt应用程序。在断点我可以写

(lldb) p myQString.toUtf8().data()

并查看myQString中包含的字符串,因为data()返回char *。我想能够写

(lldb) p myQString

并获得相同的输出。这对我不起作用:

(lldb) type summary add --summary-string "${var.toUtf8().data()}" QString

是否可以编写这样的简单格式化程序,或者我是否需要知道QString的内部并编写python脚本?

或者,我是否应该采用另一种方式使用LLDB以这种方式查看QStrings?

4 个答案:

答案 0 :(得分:2)

以下工作正常。

首先,注册摘要命令:

debugger.HandleCommand('type summary add -F  set_sblldbbp.qstring_summary "QString"')

这是一个实现

def make_string_from_pointer_with_offset(F,OFFS,L):
    strval = 'u"'
    try:
        data_array = F.GetPointeeData(0, L).uint16
        for X in range(OFFS, L):
            V = data_array[X]
            if V == 0:
                break
            strval += unichr(V)
    except:
        pass
    strval = strval + '"'
    return strval.encode('utf-8')


#qt5
def qstring_summary(value, unused):
    try:
        d = value.GetChildMemberWithName('d')
        #have to divide by 2 (size of unsigned short = 2)
        offset = d.GetChildMemberWithName('offset').GetValueAsUnsigned() / 2
        size = get_max_size(value)
        return make_string_from_pointer_with_offset(d, offset, size)
    except:
        print '?????????????????????????'
        return value

def get_max_size(value):
    _max_size_ = None
    try:
        debugger = value.GetTarget().GetDebugger()
        _max_size_ = int(lldb.SBDebugger.GetInternalVariableValue('target.max-string-summary-length', debugger.GetInstanceName()).GetStringAtIndex(0))
    except:
        _max_size_ = 512
    return _max_size_

答案 1 :(得分:2)

我正在尝试收集所有Qt类型的格式化程序:https://bitbucket.org/lukeworth/lldb-qt-formatters

因此,在LLDB中可视化Qt位的最简单方法是安装这些脚本。

答案 2 :(得分:1)

预计您尝试做的事情不会奏效。摘要字符串功能不允许调用表达式。

在调试器中调用表达式总是很有意思,在数据格式化程序中更是如此(如果你在IDE中 - 比如说Xcode - 格式化程序会自动运行)。每当你停在某个地方时,即使你只是跨过一行,所有这些小表达式都会自动反复运行,而且性能成本很高 - 这甚至没有考虑到你的数据可能在一个有趣的状态已经和正在运行的表达式有可能更改它,使你的调试会话比所需的更棘手。

如果上面的文字仍然没有阻止你(:-)),你想编写一个Python格式化程序,并使用SB API来运行你的表达式。您的值是SBValue对象,可以访问SBFrame和SBTarget。这两者的组合允许您运行EvaluateExpression(" blah")并返回另一个SBValue,可能是char *,然后您可以请求GetSummary()获取您的c-string。

另一方面,如果您现在被说服格式化程序中运行的表达式不是最理想的,那么好消息是QString肯定必须将其数据指针存储在某处...如果您发现它在哪里,您可以将格式化程序写为$ {var.member1.member2.member3.theDataPointer}并获得相同的结果!

答案 3 :(得分:0)

这是我在网上找到的UTF16字符串解释lldb脚本的试错版改编(我道歉,我不记得来源 - 而且我不能归功于作者)

请注意,对于Qt 4.3.2 以及接近它的版本,这是 - 作为对数据'的处理。从那以后,指针在Qt 5.x

之间发生了变化

def QString_SummaryProvider(valobj, internal_dict):

data = valobj.GetChildMemberWithName('d')#.GetPointeeData()
strSize = data.GetChildMemberWithName('size').GetValueAsUnsigned()
newchar = -1
i = 0 
s = u'"'
while newchar != 0:
    # read next wchar character out of memory
    data_val = data.GetChildMemberWithName('data').GetPointeeData(i, 1)
    size = data_val.GetByteSize()
    e = lldb.SBError()
    if size == 1:
        newchar = data_val.GetUnsignedInt8(e, 0)    # utf-8
    elif size == 2:
        newchar = data_val.GetUnsignedInt16(e, 0)   # utf-16
    elif size == 4:
        newchar = data_val.GetUnsignedInt32(e, 0)   # utf-32
    else:
        s = s + '<unexpected char size - error parsing QString>'
        break
    if e.fail:
        s = s + '<parse error:' + e.why() + '>' 
        break

    i = i + 1 
    if i > strSize:
        break
    # add the character to our string 's'
    # print "char2 = %s" % newchar
    if newchar != 0:
        s = s + unichr(newchar)
s = s + u'"'
return s.encode('utf-8')