[lldb-dev] Using data formatters to display QString
Enrico Granata
egranata at apple.com
Mon Apr 28 17:38:47 PDT 2014
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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/lldb-dev/attachments/20140428/ecda9452/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: qstring.py
Type: text/x-python-script
Size: 752 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/lldb-dev/attachments/20140428/ecda9452/attachment.bin>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/lldb-dev/attachments/20140428/ecda9452/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: qstring.cpp
Type: application/octet-stream
Size: 411 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/lldb-dev/attachments/20140428/ecda9452/attachment.obj>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/lldb-dev/attachments/20140428/ecda9452/attachment-0002.html>
More information about the lldb-dev
mailing list