├── QtFormatters.lldb ├── QtFormatters.py ├── README.md └── lldbtests ├── lldbtests.pro └── main.cpp /QtFormatters.lldb: -------------------------------------------------------------------------------- 1 | type summary add -x "^QString$" -e -F QtFormatters.QString_SummaryProvider 2 | type summary add -x "^QUrl$" -e -F QtFormatters.QUrl_SummaryProvider 3 | type synthetic add -x "^QVector<.+>$" -l QtFormatters.QVector_SyntheticProvider 4 | type summary add -x "^QVector<.+>$" -e -s "size=${svar%#}" 5 | type synthetic add -x "^QList<.+>$" -l QtFormatters.QList_SyntheticProvider 6 | type summary add -x "^QList<.+>$" -e -s "size=${svar%#}" 7 | type synthetic add -x "^QPointer<.+>$" -l QtFormatters.QPointer_SyntheticProvider 8 | type summary add -x "^QPointer<.+>$" -e -s "filled="${svar%#}" -------------------------------------------------------------------------------- /QtFormatters.py: -------------------------------------------------------------------------------- 1 | import lldb 2 | 3 | def QUrl_SummaryProvider(valobj, internal_dict): 4 | return valobj.GetFrame().EvaluateExpression(value.GetName() + '.url((QUrl::FormattingOptions)QUrl::PrettyDecoded).toUtf8().data()'); 5 | 6 | def QString_SummaryProvider(valobj, internal_dict): 7 | def make_string_from_pointer_with_offset(F,OFFS, L): 8 | 9 | strval = '"' 10 | try: 11 | data = F.GetPointeeData(0, L) 12 | G = data.uint16 13 | for X in range(0, L): 14 | V = G[X] 15 | if V == 0: 16 | continue 17 | strval += unichr(V) 18 | except Exception as e: 19 | pass 20 | strval = strval + '"' 21 | return strval.encode('utf-8') 22 | 23 | #qt4.8 24 | def qstring_summary(value): 25 | try: 26 | d = value.GetChildMemberWithName('d') 27 | offset = d.GetChildMemberWithName('alloc').GetValueAsUnsigned() 28 | size = d.GetChildMemberWithName('size').GetValueAsUnsigned() 29 | data = d.GetChildMemberWithName('data') 30 | return make_string_from_pointer_with_offset(data, offset, size) 31 | except Exception as e: 32 | return value 33 | 34 | return qstring_summary(valobj) 35 | 36 | class QVector_SyntheticProvider: 37 | def __init__(self, valobj, internal_dict): 38 | self.valobj = valobj 39 | 40 | def num_children(self): 41 | try: 42 | s = self.valobj.GetChildMemberWithName('d').GetChildMemberWithName('size').GetValueAsUnsigned() 43 | return s 44 | except: 45 | return 0; 46 | 47 | def get_child_index(self,name): 48 | try: 49 | return int(name.lstrip('[').rstrip(']')) 50 | except: 51 | return None 52 | 53 | def get_child_at_index(self,index): 54 | if index < 0: 55 | return None 56 | if index >= self.num_children(): 57 | return None 58 | if self.valobj.IsValid() == False: 59 | return None 60 | try: 61 | doffset = self.valobj.GetChildMemberWithName('d').GetChildMemberWithName('offset').GetValueAsUnsigned() 62 | type = self.valobj.GetType().GetTemplateArgumentType(0) 63 | elementSize = type.GetByteSize() 64 | return self.valobj.GetChildMemberWithName('d').CreateChildAtOffset('[' + str(index) + ']', doffset + index * elementSize, type) 65 | except: 66 | return None 67 | 68 | class QList_SyntheticProvider: 69 | def __init__(self, valobj, internal_dict): 70 | self.valobj = valobj 71 | 72 | def num_children(self): 73 | try: 74 | listDataD = self.valobj.GetChildMemberWithName('p').GetChildMemberWithName('d') 75 | begin = listDataD.GetChildMemberWithName('begin').GetValueAsUnsigned() 76 | end = listDataD.GetChildMemberWithName('end').GetValueAsUnsigned() 77 | return (end - begin) 78 | except: 79 | return 0; 80 | 81 | def get_child_index(self,name): 82 | try: 83 | return int(name.lstrip('[').rstrip(']')) 84 | except: 85 | return None 86 | 87 | def get_child_at_index(self,index): 88 | if index < 0: 89 | return None 90 | if index >= self.num_children(): 91 | return None 92 | if self.valobj.IsValid() == False: 93 | return None 94 | try: 95 | pD = self.valobj.GetChildMemberWithName('p').GetChildMemberWithName('d'); 96 | pBegin = pD.GetChildMemberWithName('begin').GetValueAsUnsigned() 97 | pArray = pD.GetChildMemberWithName('array').GetValueAsUnsigned() 98 | pAt = pArray + pBegin + index 99 | type = self.valobj.GetType().GetTemplateArgumentType(0) 100 | elementSize = type.GetByteSize() 101 | voidSize = pD.GetChildMemberWithName('array').GetType().GetByteSize() 102 | return self.valobj.GetChildMemberWithName('p').GetChildMemberWithName('d').GetChildMemberWithName('array').CreateChildAtOffset('[' + str(index) + ']', pBegin + index * voidSize, type) 103 | except: 104 | print "boned getchild" 105 | return None 106 | 107 | class QPointer_SyntheticProvider: 108 | def __init__(self, valobj, internal_dict): 109 | self.valobj = valobj 110 | 111 | def num_children(self): 112 | try: 113 | wp = self.valobj.GetChildMemberWithName('wp') 114 | d = wp.GetChildMemberWithName('d') 115 | if d.GetValueAsUnsigned() == 0 or d.GetChildMemberWithName('strongref').GetChildMemberWithName('_q_value').GetValueAsUnsigned() == 0 or wp.GetChildMemberWithName('value').GetValueAsUnsigned() == 0: 116 | return 0 117 | else: 118 | return 1 119 | except: 120 | return 0; 121 | 122 | def get_child_index(self,name): 123 | return 0 124 | 125 | def get_child_at_index(self,index): 126 | if index < 0: 127 | return None 128 | if index >= self.num_children(): 129 | return None 130 | if self.valobj.IsValid() == False: 131 | return None 132 | try: 133 | type = self.valobj.GetType().GetTemplateArgumentType(0) 134 | return self.valobj.GetChildMemberWithName('wp').GetChildMemberWithName('value').CreateChildAtOffset('value', 0, type) 135 | except: 136 | print "boned getchild" 137 | return None -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # README # 2 | 3 | This is LLDB python scripts that help debugging Qt applications. Original code is written by [Paul Perehogih](https://bitbucket.org/pperehogih/lldb-qt-formatters/overview). This particular implementation has been changed to support QString of Qt 4.8 and not 5.5 as in original implementation. 4 | 5 | I tested QString and QList only, hoping that the rest of the scripts will be compatible. But I don't know. These types are supported: 6 | 7 | - QString 8 | - QUrl 9 | - QVector 10 | - QList 11 | - QPointer 12 | 13 | # Installation # 14 | 15 | Clone this repo somewhere, e.g. ~/qtlldb. Then add the following lines to your ~/.lldbinit (create one if does not exist): 16 | 17 | ``` 18 | command script import ~/qtlldb/QtFormatters.py 19 | command source ~/qtlldb/QtFormatters.lldb 20 | ``` -------------------------------------------------------------------------------- /lldbtests/lldbtests.pro: -------------------------------------------------------------------------------- 1 | #------------------------------------------------- 2 | # 3 | # Project created by QtCreator 2015-10-16T21:24:57 4 | # 5 | #------------------------------------------------- 6 | 7 | QT += core 8 | 9 | QT -= gui 10 | 11 | TARGET = lldbtests 12 | CONFIG += console c++11 13 | CONFIG -= app_bundle 14 | 15 | TEMPLATE = app 16 | 17 | 18 | SOURCES += main.cpp 19 | -------------------------------------------------------------------------------- /lldbtests/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int main(int argc, char *argv[]) 8 | { 9 | QCoreApplication a(argc, argv); 10 | 11 | QString s = "Hello World"; 12 | 13 | QVector vi; 14 | vi << 11; 15 | vi << 22; 16 | vi << 33; 17 | 18 | QVector vs; 19 | vs << "Hello"; 20 | vs << "World"; 21 | 22 | QVector> vvs; 23 | vvs << vs; 24 | vvs << vs; 25 | 26 | QList li; 27 | li << 11; 28 | li << 22; 29 | li << 33; 30 | 31 | QList ls; 32 | ls << "Hello"; 33 | ls << "World"; 34 | 35 | QList> lls; 36 | lls << ls; 37 | lls << ls; 38 | 39 | QPointer ap; 40 | ap = &a; 41 | 42 | 43 | return a.exec(); 44 | } 45 | --------------------------------------------------------------------------------