Search code examples
lldb

Can lldb display char * / strings in structs more efficiently?


lldb has a habit to show me strings in a very spread out manner, which is a little annoying but not a show stopper. But maybe someone already knows how to make it a bit more efficient with its display size:

Example:

(lldb) p *tq
(taskq_t) $14 = {
  tq_name = {
    [0] = 's'
    [1] = 'y'
    [2] = 's'
    [3] = 't'
    [4] = 'e'
    [5] = 'm'
    [6] = '_'
    [7] = 't'
    [8] = 'a'
    [9] = 's'
    [10] = 'k'
    [11] = 'q'
    [12] = '\0'
    [13] = '\0'
    [14] = '\0'
    [15] = '\0'
    [16] = '\0'
    [17] = '\0'
    [18] = '\0'
    [19] = '\0'
    [20] = '\0'
    [21] = '\0'
    [22] = '\0'
    [23] = '\0'
    [24] = '\0'
    [25] = '\0'
    [26] = '\0'
    [27] = '\0'
    [28] = '\0'
    [29] = '\0'
    [30] = '\0'
    [31] = '\0'
  }
  tq_lock = {

Would prefer:

(lldb) p *tq
(taskq_t) $14 = {
  tq_name = {
    "system_taskq\0"
  }
  tq_lock = {

Or similar - as in, a string. As it gets quite long when it is char path[MAXPATH].


Solution

  • Showing all the elements is the natural view for an array, and since there's no guarantee that a char array is actually a null terminated string, even printing char arrays as an array is a reasonable default. But as you observe, if you know the array holds a null terminated string you really do want to print it more compactly.

    Fortunately, lldb has a system for providing "alternate" views of data objects. That's why, for instance you see:

    * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
        frame #0: 0x0000000100003f0b has_char`main at has_char.c:8
       5    {
       6      char *myStr = "some string here";
       7      char myArr[20] = {'s', 'o', 'm', 'e', ' ', 's', 0};
    -> 8      return strlen(myStr) + strlen(myArr); 
                            ^
       9    }
    Target 0: (has_char) stopped.
    (lldb) v myArr
    (char [20]) myArr = "some s"
    

    By default lldb presents char[NN] arrays as null terminated strings.

    That's done using lldb's "summary formatters". There's a bunch more information about them here:

    https://lldb.llvm.org/use/variable.html

    You can find out how a particular variable gets its formatting, which is sometimes useful when you're looking for something to copy, with:

    (lldb) type summary info myArr
    summary applied to (char [20]) myArr is: `${var%s}` (hide value) (skip pointers)
    

    The summaries are registered by a type name or type regular expression, and then applied to any value of that type when printing it. They also follow typedef chains so the same summary will be provided for variables whose type is a typedef of a registered type. What is the type of tq_name, it looks like it is just a char array? I'm a little surprised you had to do anything here...

    Anyway, no worries, you can always add one explicitly for your type.

    The command for that is:

    (lldb) type summary add -s ${var%s} -p -v TypeNameOfTQ

    -s is the summary string, see the docs cited above for more on that.

    -p because you don't want to format a char [10]* this way.

    -v because you explicitly don't want to see the elements one by one - which is the natural value of the array.