On Apr 29, 2014, at 6:50 AM, Eran Ifrah <eran.if...@gmail.com> wrote:
> Hi Enrico and all, > Thanks for the references, it helped me a lot. > I am now able to view QString within lldb from the command line, but not from > within my plugin :P (this was my intention all the way) > > I created the following 2 files: > ~/.lldbinit, with this single line: > > command script import /home/eran/.lldb/qstring.py > > In the script: ~/.lldb/qstring.py, I placed the following content (a slightly > modified printer based on your example): > > import lldb > > def utf16string_summary(value, *rest): > f = open('/tmp/py.log','w+b') > f.write('inside utf16string_summary\n') > f.close() > str_data = > value.GetChildMemberWithName("d").GetChildMemberWithName("data") > length_vo = > value.GetChildMemberWithName("d").GetChildMemberWithName("size") > length = length_vo.GetValueAsUnsigned(0) > if length == 0: > return '""' > data = str_data.GetPointeeData(0, length) > error = lldb.SBError() > bytes = data.ReadRawData(error, 0, 2*length) > return '"%s"' % (bytes.decode('utf-16').encode('utf-8')) > > def __lldb_init_module(debugger, *rest): > summary = > lldb.SBTypeSummary.CreateWithFunctionName("qstring.utf16string_summary") > summary.SetOptions(lldb.eTypeOptionHideChildren) > debugger.GetDefaultCategory().AddTypeSummary( > lldb.SBTypeNameSpecifier("QString", False), summary ) > > This setup works when I am using lldb-3.5 from the command line (i.e. QString > is displayed in the following format: m_stringMemeber = "some content") > How recent/non recent is lldb-3.5? Did you try with trunk at all? > Now, this is how I set it up from within my plugin: > > I tried both: > m_debugger = lldb::SBDebugger::Create(true); // source init files > > and I have also tried this: > > m_debugger = lldb::SBDebugger::Create(); > ... > lldb::SBCommandReturnObject ret; > m_debugger.GetCommandInterpreter().HandleCommand("command source > /home/eran/.lldbinit", ret); > if ( !ret.Succeeded() ) { > // print error here if any > } > > Both did not have any affect, i.e. when I view the content of QString in the > IDE, I don't see the summary as it should > Any hints? > Well, I see two - or rather three - potential issues First of all, Is the summary loaded? To check if it is, run “type summary list” and make sure you see a formatter for QString listed in the default category - and that the default category is enabled Second, is the summary working? If it is loaded, we can test it manually: do something like this while you’re stopped in a frame with a QString variable (lldb) script value = lldb.frame.FindVariable(“myQStringThingNameHere”) (lldb) script print qstring.utf16string_summary(value,None) Does anything come out with a manual invocation? Assuming the summary is registered, and manually calling it works - how are you fetching the summary in your plugin? Since it works at the command line, I assume the type name for QString is just plain QString with no namespaces in front. Is that correct? > Thanks > > > On Tue, Apr 29, 2014 at 3:38 AM, Enrico Granata <egran...@apple.com> wrote: > On Apr 28, 2014, at 3:01 PM, Poenitz Andre <andre.poen...@digia.com> wrote: > >> >> Enrico Granata wrote: >> > Eran Ifrah wrote: >> > You can't use expressions in summary strings. >> > We have thought about this several times and have a couple ideas on how >> > it could be done but for now it's not there. >> > >> > If you need to resort to an expression, you can use a python formatter >> > instead and then you are free to call as many expressions as you like. >> > >> > However, this will cause a slowdown - running expressions is not >> > free - and if you ever need to make sure nothing is altering your >> > program state, running expressions might not be a safe bet. >> > Is there really no other way to get to those UTF8 bytes? >> >> QString is stored in UTF16 internally. It can be accessed directly >> through structure member access and pointer arithmetic and converted >> using Python. "Running expressions" is not needed. >> >> Andre' > > > Here’s a small example for general reference: > Assume I have the following data structure: > > #include <string> > #include <memory> > > class UTF16String { > public: > UTF16String (const char16_t *data) { > len = std::char_traits<char16_t>::length(data); > str_data.reset(new char16_t[len]); > memcpy(str_data.get(),data,sizeof(char16_t)*(len+1)); > } > > private: > std::unique_ptr<char16_t[]> str_data; > size_t len; > }; > > int main() { > UTF16String string {u"Just some data in UTF16 here"}; > return 0; > } > > > This is what it looks like “raw” on OS X: > (UTF16String) string = { > str_data = { > __ptr_ = { > std::__1::__libcpp_compressed_pair_imp<char16_t *, > std::__1::default_delete<char16_t> > = { > __first_ = 0x00000001001037e0 > } > } > } > len = 28 > } > > To define a formatter for it you essentially want to grab two elements: the > data pointer (__first_ = 0x00000001001037e0) and the length (len = 30) > In our example, the length is defined in UTF16-characters rather than bytes. > This is something you want to know when writing a formatter > > So let’s delve right in: > def utf16string_summary(value,*rest): > str_data = > value.GetChildMemberWithName("str_data").GetChildMemberWithName("__ptr_").GetChildMemberWithName("__first_") > length_vo = value.GetChildMemberWithName("len") > > Now we have SBValues for the string data and for the length - we want the > “number stored inside” the length: > length = length_vo.GetValueAsUnsigned(0) > if length == 0: > return '""' > > As a special case - if the length is zero, just return an empty string. I am > not going to go in detail over all the possible checks here (hint: what if > str_data’s value is zero?) > > Now let’s grab the bytes - we want length char16_t at the location pointed to > by our str_data: > data = str_data.GetPointeeData(0,length) > > And now let’s grab a Python string out of those bytes: > error = lldb.SBError() > bytes = data.ReadRawData(error,0,2*length) > > The 2*length argument is carefully crafted to ensure we get all the bytes we > need - it of course depends on sizeof(char16_t) == 2 > > Python is pretty good at string management, all we have to do now is tell it > to turn our string from UTF16 into UTF8: > return '"%s"' % (bytes.decode('utf-16').encode('utf-8')) > > You’re done. To add the summary automatically to LLDB whenever you command > script import the python file with the formatter: > def __lldb_init_module(debugger,*rest): > summary = > lldb.SBTypeSummary.CreateWithFunctionName("qstring.utf16string_summary") > summary.SetOptions(lldb.eTypeOptionHideChildren) > > debugger.GetDefaultCategory().AddTypeSummary(lldb.SBTypeNameSpecifier("UTF16String",False),summary) > > This is what you get with the summary enabled: > (UTF16String) string = "Just some data in UTF16 here” > > Find the C++ and the Python parts of the example attached for reference - and > of course feel free to ping back with any additional questions > > > > > - Enrico > 📩 egranata@.com ☎️ 27683 > > > > > > > > -- > Eran Ifrah > Author of codelite, a cross platform open source C/C++ IDE: > http://www.codelite.org > wxCrafter, a wxWidgets RAD: http://wxcrafter.codelite.org - Enrico 📩 egranata@.com ☎️ 27683
_______________________________________________ lldb-dev mailing list lldb-dev@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev