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
.