On Apr 28, 2014, at 3:01 PM, Poenitz Andre <andre.poen...@digia.com> wrote:
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 = ""> 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 |
import lldb def utf16string_summary(value,*rest): str_data = value.GetChildMemberWithName("str_data").GetChildMemberWithName("__ptr_").GetChildMemberWithName("__first_") length_vo = value.GetChildMemberWithName("len") 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("UTF16String",False),summary)
qstring.cpp
Description: Binary data
- Enrico 📩 egranata@.com ☎️ 27683 |
_______________________________________________ lldb-dev mailing list lldb-dev@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev