So what is the format of the summary strings? Summary
strings can contain plain text, control characters and
special symbols that have access to information about
the current object and the overall program state.
Normal characters are any text that doesn't contain a '{'
,
'}'
, '$'
, or '\'
character.
Variable names are found in between a "${"
prefix, and end with a "}"
suffix.
In other words, a variable looks like "${frame.pc}"
.
Basically, all the variables described in Frame and Thread Formatting
are accepted. Also acceptable are the control characters
and scoping features described in that page.
Additionally, ${var
and ${*var
become acceptable symbols in this scenario.
The simplest thing you can do is grab a member variable
of a class or structure by typing its expression
path. In the previous example, the expression path
for the floating member is simply .floating
,
because all you have to do to get at it given an object
of type i_am_cool
is access it straight
away. Thus, to ask the summary string to display floating
you would type ${var.floating}
(${var
is a placeholder token replaced with whatever variable
is being displayed).
If you have code like the following:
struct A {
int x;
int y;
};
struct B {
A x;
A y;
int z;
};
the expression path for the y
member of the x
member of an object of
type B
would be .x.y
and you
would type ${var.x.y}
to display it in a
summary string for type B
.
As you could be using a summary string for both
displaying objects of type T
or T*
(unless -p
is used to prevent this), the
expression paths do not differentiate between .
and ->
, and the above expression path .x.y
would be just as good if you were displaying a B*
,
or even if the actual definition of B
were:
struct B {
A *x;
A y;
int z;
};
This is unlike the behaviour of frame variable
which, on the contrary, will enforce the distinction. As
hinted above, the rationale for this choice is that
waiving this distinction enables one to write a summary
string once for type T
and use it for both
T
and T*
instances. As a
summary string is mostly about extracting nested
members' information, a pointer to an object is just as
good as the object itself for the purpose.
Of course, you can have multiple entries in one summary
string. For instance, the command used to produce the
above summary string for i_am_cool was:
type summary add -f "int = ${var.integer}, float =
${var.floating}, char = ${var.character%u}" i_am_cool
As you can see, the last expression path also contains
a %u
symbol which is nowhere to be found
in the actual member variable name. The symbol is
reminding of a printf()
format symbol, and
in fact it has a similar effect. If you add a % sign
followed by any one format name or abbreviation from the
above table after an expression path, the resulting
object will be displyed using exactly that format
instead of the LLDB default one.
There are two more special format symbols that you can
use only as part of a summary string: %V
and %@
. The first one tells LLDB to ignore
summary strings for the type of the object referred by
the expression path and instead print the object's
value. The second is only applicable to Objective-C
classes, and tells LLDB to get the object's description
from the Objective-C runtime. By default, if no format
is provided, LLDB will try to get the object's summary,
and if empty the object's value. If neither can be
obtained, nothing will be displayed.
As previously said, pointers and values are treated the
same way when getting to their members in an expression
path. However, if your expression path leads to a
pointer, LLDB will not automatically dereference it. In
order to obtain The deferenced value for a pointer, your
expression path must start with ${*var
instead of ${var
. Because there is no need
to dereference pointers along your way, the
dereferencing symbol only applies to the result of the
whole expression path traversing.
e.g.
(lldb) fr var -T c
(Couple) c = {
(SimpleWithPointers) sp = {
(int *) x = 0x00000001001000b0
(float *) y = 0x00000001001000c0
(char *) z = 0x00000001001000d0 "X"
}
(Simple *) s = 0x00000001001000e0
}
(lldb) type summary add -f "int = ${*var.sp.x},
float = ${*var.sp.y}, char = ${*var.sp.z%u}, Simple =
${*var.s}" Couple
(lldb) type summary add -c -p Simple
(lldb) fr var c
(Couple) c = int = 9, float = 9.99, char = 88, Simple
= (x=9, y=9.99, z='X')
Option -c
to type summary add
tells LLDB not to look for a summary string, but instead
to just print a listing of all the object's children on
one line, lay out as in the previous example. The -p
flag is used as a trick to show that aggregate types can
be dereferenced as well as primitive ones. The above
output would be shown even by typing type summary
add -f "int = ${*var.sp.x}, float = ${*var.sp.y}, char
= ${*var.sp.z%u}, Simple = ${var.s}" Couple
if
one took away the -p
flag from the summary
for type Simple
.