[lldb-dev] Using data formatters to display QString

Eran Ifrah eran.ifrah at gmail.com
Tue Apr 29 06:50:15 PDT 2014


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")

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?

Thanks


On Tue, Apr 29, 2014 at 3:38 AM, Enrico Granata <egranata at apple.com> wrote:

> On Apr 28, 2014, at 3:01 PM, Poenitz Andre <Andre.Poenitz at 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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/lldb-dev/attachments/20140429/88d8f8c6/attachment.html>


More information about the lldb-dev mailing list