May 29, 2019
(crossposted to debugger; please reply in ldc)

Having struggled with this a bit myself, I wanted to share the following python script for lldb to format and print dlang native string variables in a debugging session.

LIMITATIONS: This works for me on lldb-8 on Ubuntu18.04; does NOT work on my Mac though admittedly lldb is somewhat broken due to conflict with Homebrew-installed python version.

The python script will need further modification before it will work with wstring and dstring.

BACKGROUND: lldb does not recognize dlang char/wchar/dchar; this can be seen in lldb messages like:
error: need to add support for DW_TAG_base_type 'immutable(char)'
encoded with DW_ATE = 0x10, bit_size = 8
error: need to add support for DW_TAG_base_type 'char' encoded with DW_ATE = 0x10, bit_size = 8
error: need to add support for DW_TAG_base_type 'dchar' encoded with DW_ATE = 0x10, bit_size = 32

Pointers to these data are typed as void, and thus not displayed. Additionally, because D strings are not \0 terminated, lldb's built in string formatting (frame var stringvar.ptr -f s) will print trailing garbage.

(Now that C++20 has char16_t and char32_t this should be easy to hotfix in https://github.com/llvm-mirror/lldb/blob/af72c1627f754a1e75ae5a24fe33820c79b5a715/source/Symbol/ClangASTContext.cpp#L1364-L1369 until a true D plugin for lldb can be created.)

Script:
import lldb

def string(valobj,internal_dict):
    """valobj: an SBValue which you want to provide a summary for
    internal_dict: an LLDB support object not to be used"""

    lenobj = valobj.GetChildMemberWithName("length")
    strlen = lenobj.GetValueAsUnsigned(0)

    ptrobj = valobj.GetChildMemberWithName("ptr")

    # does not work de novo, (ie from lldb.SBType()) yields nothing
    charptrtype = ptrobj.GetType().GetBasicType(lldb.eBasicTypeChar).GetPointerType()
    charptr = ptrobj.Cast(charptrtype)
    data = charptr.GetPointeeData(0, strlen)

    error = lldb.SBError()
    return data.GetString(error, 0)
EOF


Session:
(lldb) frame v infile
(string) infile = (length = 18, ptr = 0x00007fffffffe1ce)
(lldb) frame v infile.ptr
(void *) infile.ptr = 0x00007fffffffe1ce

 ^^^^ note that ptr is typed as void* because lldb does not recognize immutable(char)*

(lldb) command script import ~/dlang.py
(lldb) type summary add -F dlang.string string

(lldb) frame v infile
(string) infile = resources/hg19.bed

Commands can be placed in ~/.lldbinit file