# Variable formatting LLDB supports the custom formatting of variables as they are displayed in the debugger. ## Variable display LLDB has a data formatters subsystem that lets you define custom display options for variables. Typically, when you type a frame variable or run some expression, LLDB automatically chooses the way to display your results on a per-type basis. For example: (lldb) frame variable (uint8_t) x = 'a' (intptr_t) y = 124752287 Copy to clipboard However, in certain cases you may want to define a different style for the display of certain data types. To do so, you must give hints to the debugger regarding how the variables are to be displayed. The LLDB type command allows you to do just that. Using the type command, you can change the variable display to look like this: (lldb) frame variable (uint8_t) x = chr='a' dec=65 hex=0x41 (intptr_t) y = 0x76f919f Copy to clipboard Several features are related to data visualization: formats, summaries, filters, synthetic children. To reflect this, the type command has five subcommands: - `type format` - `type summary` - `type filter` - `type synthetic` - `type category` These subcommands are meant to bind printing options to types. When variables are printed, LLDB first checks if custom printing options have been associated to a variable type, and if so, it uses them instead of the default format. Each subcommand (except the type category) has four subcommands: - `add` - Associate a new printing option to one or more types - `delete` - Delete an existing association - `list` - Provide a listing of all associations - `clear` - Delete all associations ## Type formats Type formats enable you to quickly override the default format for displaying primitive types (the usual basic C/C++ types: int, float, char, and so on). If you want all int variables in your program to print out as hexadecimal values, you can add a format to the int type. Enter the following at the LLDB command line: (lldb) type format add --format hex int Copy to clipboard The --format option (which can be shortened to -f) accepts a format name <#formatstable>. Then provide one or more types to apply to the new format. A frequent scenario is that your program has a typedef for a numeric type that you know represents something that must be printed in a certain way. Again, you can add a format just to that typedef by using type format add with the name alias. But things can quickly get hierarchical. Consider the following example: typedef int A; typedef A B; typedef B C; typedef C D; Copy to clipboard Here you want to display all A types as hexadecimal, all C types as byte arrays, and leave the default types untouched (while this example might seem contrived, it is realistic in large software systems). If you simply enter the following: (lldb) type format add -f hex A (lldb) type format add -f uint8_t[] C Copy to clipboard The values of type B are shown as hexadecimal, and values of type D are shown as byte arrays: (lldb) frame variable -T (A) a = 0x00000001 (B) b = 0x00000002 (C) c = {0x03 0x00 0x00 0x00} (D) d = {0x04 0x00 0x00 0x00} Copy to clipboard This print formatting occurs because by default, LLDB cascades formats through typedef chains. You can use the -C option to avoid cascading, thus creating the two commands required to achieve your goal: (lldb) type format add -C no -f hex A (lldb) type format add -C no -f uint8_t[] C Copy to clipboard Which provides the intended output: (lldb) frame variable -T (A) a = 0x00000001 (B) b = 2 (C) c = {0x03 0x00 0x00 0x00} (D) d = 4 Copy to clipboard Two additional options you should know about are --skip-pointers (-p) and --skip-references (-r). These options prevent LLDB from applying a format for type T to values of type T\* and T& respectively: (lldb) type format add -f float32[] int (lldb) frame variable pointer *pointer -T (int *) pointer = {1.46991e-39 1.4013e-45} (int) *pointer = {1.53302e-42} (lldb) type format add -f float32[] int -p (lldb) frame variable pointer *pointer -T (int *) pointer = 0x0000000100100180 (int) *pointer = {1.53302e-42} Copy to clipboard While you can apply formats to pointers and references, they do no attempt to dereference the pointer and extract the value before applying the format. This means you are effectively formatting the address stored in the pointer itself, rather than the referenced value. For this reason, when defining formats, you might want to use the -p option. To delete a custom format, type type format delete followed by the name of the type to which the format applies. Even if you defined the same format for multiple types on the same command, type format delete only removes the format for the type name specified as the argument. To delete all formats, use type format clear. To see all the formats defined, use type format list. However, if all you intend is to display one variable in a custom format, while leaving the others of the same type untouched, you can simply enter: (lldb) frame variable counter -f hex Copy to clipboard The value of counter is displayed as a hexadecimal number, and it displays this way until you either pick a different format or until you let your program run again. ### Options default binary | b boolean | B bytes | y bytes with ASCII | Y c-string | s char[] character | c character array | a complex float | F complex integer | I decimal | i enumeration | E float | f float32[] | float64[] hex | x int8_t[] | uint8_t[] int16_t[] | uint16_t[] int32_t[] | uint32_t[] int64_t[] | uint64_t[] uint128_t[] octal | o pointer | p printable character | C unicode16 | U unicode32 | U unsigned decimal | u Copy to clipboard #### Descriptions - **default** - Use the default LLDB algorithm to pick a format. - **binary** | **b** - Show the value as a sequence of bits. - **boolean** | **B** - Show the value as a TRUE/FALSE Boolean, using the customary rule that 0 is FALSE and everything else is TRUE. - **bytes** | **y** - Show the bytes one after the other. For example: (int) s.x = 07 00 00 00 Copy to clipboard - **bytes with ASCII** | **Y** - Show the bytes, but also display them as ASCII characters. For example: .. code-block: (int *) c.sp.x = 50 f8 bf 5f ff 7f 00 00 P.._.... Copy to clipboard - **c-string** | **s** - Show the value as a zero-terminated C string. - **char[]** - Show the value as an array of characters. For example: (char) *c.sp.z = {X} Copy to clipboard - **character** | **c** - Show the bytes as ASCII characters. For example: ( int *) c.sp.x = P\xf8\xbf_\xff\x7f\0\0 Copy to clipboard **character array** | **a** Show the value as a character array. For example: (int *) pointer = \x80\x01\x10\0\x01\0\0\0 Copy to clipboard - **complex float** | **F** - Interpret the value as the real and imaginary part of a complex floating-point number. For example: (int *) c.sp.x = 2.76658e+19 + 4.59163e-41i Copy to clipboard - **complex integer** | **I** - Interpret the value as the real and imaginary parts of a complex integer number. For example: (int *) pointer = 1048960 + 1i Copy to clipboard - **decimal** | **i** - Show the value as a signed integer number (this option does not perform a cast; it simply shows the bytes as an integer with sign). - **enumeration** | **E** - Show the value as an enumeration, printing the value’s name if available or the integer value otherwise. For example: (enum enumType) val_type = eValue2 Copy to clipboard - **float** | **f** - Show the value as a floating-point number (this option does not perform a cast; it only interprets the bytes as an IEEE754 floating point value). - **float32[]** | **float64[]** - Show an array of the corresponding floating-point types. For example: (int *) pointer = {1.46991e-39 1.4013e-45} Copy to clipboard - **hex** | **x** - Show the value in hexadecimal notation (this option does not perform a cast; it simply shows the bytes as hex). - **int8\_t[]** | **uint8\_t[]** | **int16\_t[]** **uint16\_t[]** | **int32\_t[]** | **uint32\_t[]** **int64\_t[]** | **uint64\_t[]** | **uint128\_t[]** - Show the values as an array of the corresponding integer types. For example: (int) x = {1 0 0 0} (with uint8_t[]) (int) y = {0x00000001} (with uint32_t[]) Copy to clipboard - **octal** | **o** - Show the value in octal notation. - **pointer** | **p** - Show the value as a native pointer (unless the value is really a pointer, the resulting address will probably be invalid). - **printable character** | **C** - Show the bytes as printable ASCII characters. For example: (int *) c.sp.x = P.._.... Copy to clipboard - **unicode16** | **U** - Show the value as UTF-16 characters. For example: (float) x = 0xd70a 0x411f Copy to clipboard - **unicode32** - Show the value as UTF-32 characters. For example: (float) x = 0x411fd70a Copy to clipboard - **unsigned decimal** | **u** - Show the value as an unsigned integer number (this option does not perform a cast; it simply shows the bytes as an unsigned integer). ## Type summaries Type formats work by showing a different kind of display for the value of a variable. However, they only work for basic types. To display a class or structure type in a custom format, you must use a different feature known as *type summaries*. This feature works by extracting information from classes, structures, and other aggregate types, and arranging them in a user-defined format. For example, before adding a type summary: (lldb) frame variable -T one (i_am_cool) one = { (int) x = 3 (float) y = 3.14159 (char) z = 'E' } Copy to clipboard After adding a summary: (lldb) frame variable one (i_am_cool) one = int = 3, float = 3.14159, char = 69 Copy to clipboard There are two ways to use type summaries: - Bind a summary string to the type - Write a Python script that returns the string to be used as summary Both options are enabled by the type summary add command. The following obtains the output shown in the example: (lldb) type summary add --summary-string "int = ${var.x}, float = ${var.y}, char = ${var.z%u}" i_am_cool Copy to clipboard ### Summary strings Summary strings are written using a simple control language, exemplified by the snippet in the previous section. A summary string contains a sequence of tokens that are processed by LLDB to generate the summary. Summary strings can contain plain text, control characters, and special variables that have access to information about the current object and the overall program state. - Plain text is any sequence of characters that does not contain a {, }, $, or \ character, which are the control characters ([control characters](https://docs.qualcomm.com/doc/80-N3040-23/topic/frame-and-thread-formatting.html#frame-and-thread-control-characters)). - Special variables begin with a ${ prefix, and end with a } suffix. Variables can be either a simple name, or they can refer to complex objects that themselves have sub-items. In other words, a variable looks like ${object} or ${object.child.otherchild}. - A variable can also be prefixed or suffixed with other symbols meant to change the way its value is handled. An example is ${var.int\_pointer[0-3]}. The syntax is the same as described in [Frame and thread formatting](https://docs.qualcomm.com/doc/80-N3040-23/topic/frame-and-thread-formatting.html), plus additional symbols specific to summary strings. The main addition is ${var, which is used to refer to the variable for which a summary is being created. The simplest thing you can do is get a member variable of a class or structure by typing its *expression path*. In the previous example, the expression path for the field float y is simply .y. Thus, to use the summary string to display y, type ${var.y}. In the following code, the expression path for the y member of the x member of an object of type B is .x.y. Type ${var.x.y} to display it in a summary string for type B: struct A { int x; int y; }; struct B { A x; A y; int z; }; Copy to clipboard By default, a summary defined for type T, also works for types T\* and T& (you can disable this behavior). For this reason, expression paths do not differentiate between . and ->; the expression path above, .x.y, is as good as if you were displaying a B\*, or even if the actual definition of B is: struct B { A *x; A y; int *z; }; Copy to clipboard This example is unlike the behavior of a frame variable which, on the contrary, enforces the distinction. As hinted above, the rationale for this choice is that waiving this distinction allows you to write a summary string once for type T, and use it for both T and T\* instances. Because a summary string is about extracting nested members’ information, a pointer to an object is as good as the object itself for the purpose. To access the value of the integer pointed to by B::z, you cannot simply specify ${var.z}, because that symbol refers to the pointer z. To dereference it and get the pointed value, specify ${var.z}. The ${var directs LLDB to first get the object that the expression paths leads to, and then dereference it. In this example, it is equivalent to (bObject.z) in C/C++ syntax. Because the . and -> operators can both be used, dereferences are not required in the middle of an expression path (for example, do not specify ${\*(var.x).x}) to read A::x as contained in \*(B::x). To achieve that effect, simply specify ${var.x->x}, or even ${var.x.x}. A summary string can contain more than one ${var specifier, and can use ${var and ${\*var specifiers together. Note The \* operator only binds to the result of the whole expression path, rather than piecewise, and using parentheses will not change that behavior. ### Formatting summary elements An expression path can include formatting codes. Much like the type formats discussed previously, you can customize the way variables are displayed in summary strings, regardless of the format they have applied to their types. To do that, use %/format/ inside an expression path, such as in ${var.x->x%u}, which displays the value of x as an unsigned integer. You can also use other special format markers, which are not available for formats themselves, but which carry a special meaning when used in this context. Special format markers | **Symbol** | **Description** | | --- | --- | | %S | Object summary (the default for aggregate types) | | %V | Object value (the default for non-aggregate types) | | %@ | Language runtime-specific description (for C++, this does nothing) | | %L | Object location (memory address, register name, and so on) | | %# | Number of children of this object | | %T | Name of the object data type | Using the --inline-children (-c) option with type summary add directs LLDB to not search for a summary string, but instead to just print a listing of all the object’s children on one line. For example, given the following type pair: (lldb) frame variable --show-types a_pair (pair) a_pair = { (int) first = 1; (int) second = 2; } Copy to clipboard If you enter the following command: (lldb) type summary add --inline-children pair Copy to clipboard The output becomes: (lldb) frame variable a_pair (pair) a_pair = (first=1, second=2) Copy to clipboard Of course, you can obtain the same effect by entering the following: (lldb) type summary add pair --summary-string "(first=${var.first},second=${var.second})" Copy to clipboard While the result is the same, using --inline-children can often save time. To see the values of the variables, not their names, combine the --omit-names, or -O (uppercase letter), option with --inline-children to get the following: (lldb) frame variable a_pair (pair) a_pair = (1, 2) Copy to clipboard Which is equivalent to: (lldb) type summary add pair --summary-string "(${var.first},${var.second})" Copy to clipboard ### Bit fields and array syntax Sometimes a basic type’s value represents several different values packed together in a bit field. With the classical view, there is no way to look at them. Hexadecimal display can help, but if the bits span nibble boundaries, the help is limited. Binary view would show it all without ambiguity, but that view is often too detailed and hard to read for real-life scenarios. To cope with this issue, LLDB supports native bit field formatting in summary strings. If your expression paths leads to a so-called scalar type (the usual int, float, char, double, short, long, long long, double, long double and unsigned variants), you can direct LLDB to grab only some bits out of the value and display them in any format you like. If you only need one bit, you can use the [/n/] notation, just as in indexing an array. To extract multiple bits, you can use a slice-like syntax: [/n/-/m/]. For example: (lldb) frame variable float_point (float) float_point = -3.14159 (lldb) type summary add --summary-string "Sign: ${var[31]%B} Exponent: ${var[30-23]%x} Mantissa: ${var[0-22]%u}" float (lldb) frame variable float_point (float) float_point = -3.14159 Sign: true Exponent: 0x00000080 Mantissa: 4788184 Copy to clipboard In this example, LLDB shows the internal representation of a float variable by extracting bit fields out of a float object. When typing a range, the extremes n and m are always included, and the order of the indices is irrelevant. LLDB also allows you to use a similar syntax to display array members inside a summary string. For instance, you may want to display all arrays of a given type using a more compact notation than the default, and then access just the individual array members that prove interesting to your debugging task. You can direct LLDB to format arrays in special ways, independent of the way the array the members’ data type is formatted. For example: (lldb) **frame variable sarray** (Simple [3]) sarray = { [0] = { x = 1 y = 2 z = '\x03' } [1] = { x = 4 y = 5 z = '\x06' } [2] = { x = 7 y = 8 z = '\t' } } (lldb) type summary add --summary-string "${var[].x}" "Simple [3]" (lldb) frame variable sarray (Simple [3]) sarray = [1,4,7] Copy to clipboard The [] symbol is defined as follows: if var is an array and its size is known, apply this summary string to every element of the array. In the example above, LLDB is directed to display .x for every element of the array. If you find one or more of those integers anomalous, you can inspect those items in greater detail, without the array format getting in the way: (lldb) frame variable sarray[1] (Simple) sarray[1] = { x = 4 y = 5 z = '\x06' } Copy to clipboard You can also direct LLDB to print only a subset of the array range by using the same syntax used to extract bit for bit fields: (lldb) type summary add --summary-string "${var[1-2].x}" "Simple [3]" (lldb) frame variable sarray (Simple [3]) sarray = [4,7] Copy to clipboard If you are dealing with a pointer that you know is an array, you can use this syntax to display the elements contained in the pointed array instead of just the pointer value. However, because pointers have no notion of their size, the empty brackets [] operator does not work, and you must explicitly provide higher and lower bounds. Typically, LLDB requires the square brackets operator [] to handle arrays and pointers correctly, and for pointers it also requires a range. However, a few special cases are defined to make your life easier: You can print a zero-terminated string (C-string) using the %s format, omitting square brackets, as in: (lldb) type summary add --summary-string "${var%s}" "char *" Copy to clipboard This syntax works for char\* as well as for char[] because LLDB can rely on the final 0 terminator to know when the string has ended. LLDB has default summary strings for char\* and char[] that use this special case. On debugger startup, the following are defined automatically: (lldb) type summary add --summary-string "${var%s}" "char *" (lldb) type summary add --summary-string "${var%s}" -x "char \[[0-9]+]" Copy to clipboard Any of the array formats (int8\_t[], float32{}, …), and the y, Y and a formats work to print an array of a non-aggregate type, even if square brackets are omitted. (lldb) type summary add --summary-string "${var%int32_t[]}" "int [10]" Copy to clipboard This feature, however, is not enabled for pointers because there is no way for LLDB to detect the end of the pointed data. This also does not work for other formats (such as Boolean), and you must specify the square brackets operator to get the expected output. ## Python scripts Summary strings are typically good enough for summarizing the contents of a variable. However, to do more than simply picking some values and rearranging them for display, summary strings are not effective because they lack the power to perform any kind of computation on the value of variables. To solve this issue, you can bind some Python scripting code as a summary for your data type, and that script can both extract children variables as the summary strings do, and to perform active computation on the extracted values. For example: class Rectangle { private: int height; int width; public: Rectangle() : height(3), width(5) {} Rectangle(int H) : height(H), width(H*2-1) {} Rectangle(int H, int W) : height(H), width(W) {} int GetHeight() { return height; } int GetWidth() { return width; } }; Copy to clipboard Summary strings are effective to reduce the screen real estate used by the default viewing mode, but they are not effective for displaying the area and perimeter of Rectangle objects. In this case, attach a small Python script to the Rectangle class: (lldb) type summary add -P Rectangle Enter your Python command(s). Type 'DONE' to end. def function(valobj,internal_dict): height_val = valobj.GetChildMemberWithName('height') width_val = valobj.GetChildMemberWithName('width') height = height_val.GetValueAsUnsigned(0) width = width_val.GetValueAsUnsigned(0) area = height*width perimeter = 2*(height + width) return 'Area: ' + str(area) + ', Perimeter: ' + str(perimeter) DONE (lldb) frame variable (Rectangle) r1 = Area: 20, Perimeter: 18 (Rectangle) r2 = Area: 72, Perimeter: 36 (Rectangle) r3 = Area: 16, Perimeter: 16 Copy to clipboard To write effective summary scripts, you must know the LLDB public API, which is the way Python code can access the LLDB object model. Note For further details on the API see the rest of this chapter or the LLDB API reference documentation ([http://lldb.llvm.org/python_reference/index.html](http://lldb.llvm.org/python_reference/index.html)). As a brief introduction, your script is encapsulated as a function that is passed two parameters, valobj and internal\_dict: - valobj is the object encapsulating the actual variable being displayed, and its type is SBValue. - internal\_dict is an internal support parameter used by LLDB; do not touch it. Of the many possible operations on an SBValue, the most basic operation is to retrieve the children objects that it contains (which are the fields of the object that is wrapped by it), by calling GetChildMemberWithName() and passing it the child’s name as a string. If the variable has a value, you can ask for it and return it as a string using GetValue() or as a signed/unsigned number using GetValueAsSigned(), GetValueAsUnsigned(). You can also retrieve an SBData object by calling GetData() and then reading the object’s contents out of the SBData. To traverse several levels of hierarchy, as you can do with summary strings, use the method GetValueForExpressionPath(). Pass this function an expression path similar to those used in summary strings. One of the differences is that dereferencing a pointer does not occur by prefixing the path with a \*, but by calling the Dereference() method on the returned SBValue. To access array slices, you cannot do that (yet) via this method call, and instead must use GetChildAtIndex(). Query this function for the array items one by one. Also, handling custom formats is something you must deal with on your own. Other than interactively typing a Python script, there are two other ways for you to input a Python script as a summary: - Using the –python-script option with type summary add, and entering the script code as an option argument: (lldb) type summary add --python-script "height = valobj.GetChildMemberWithName('height').GetValueAsUnsigned(0); width =valobj.GetChildMemberWithName('width').GetValueAsUnsigned(0); return 'Area: %d' % (height*width)" Rectangle Copy to clipboard - Using the –python-function (-F) option with type summary add, and specifying the name of a Python function with the correct prototype. You will probably define (or have already defined) the function in the interactive interpreter, or you will somehow load it from a file using the command script import command. LLDB will generate a warning if it cannot find the function you passed, but it will still register the binding. ## Regular expression type names To associate the custom summary string to the array types, you must specify the array size as part of the type name. This can become tiresome when using arrays of different sizes, such as Simple [3], Simple [9], Simple [12], and so on. If you use the -x option, type names are treated as regular expressions instead of type names. This options lets you rephrase the above example for arrays of type Simple [3] as: (lldb) type summary add --summary-string "${var[].x}" -x "Simple\[[0- 9]+\]" (lldb) frame variable (Simple [3]) sarray = [1,4,7] (Simple [2]) sother = [3,6] Copy to clipboard The above scenario works for Simple [3] as well as for any other array of Simple objects. While this feature is mostly useful for arrays, you can also use regular expressions to catch other type sets grouped by name. However, because regular expression matching is slower than normal name matching, LLDB will first try to match by name in any way it can; only when this fails will LLDB resort to regular expression matching. One of the ways LLDB uses this feature internally, is to match the names of STL container classes, regardless of the template arguments provided. The details for this are in file FormatManager.cpp. The regular expression language used by LLDB is the *POSIX extendedlanguage*, as defined by the *Single UNIX Specification* ([http://pubs.opengroup.org/onlinepubs/7908799/xsh/regex.h.html](http://pubs.opengroup.org/onlinepubs/7908799/xsh/regex.h.html)). ## Named summaries For a given type, there may be different meaningful summary representations. Currently, however, only one summary can be associated to a type at each moment. To temporarily override the association for a variable without changing the summary string for to its type, use named summaries. Named summaries work by attaching a name to a summary when creating it. Then, when the summary is to be attached to a variable, the frame variable command supports a `--summary` option that directs LLDB to use the named summary given instead of the default summary. For example: (lldb) type summary add --summary-string "x=${var.integer}" --name NamedSummary (lldb) frame variable one (i_am_cool) one = int = 3, float = 3.14159, char = 69 (lldb) frame variable one --summary NamedSummary (i_am_cool) one = x=3 Copy to clipboard When defining a named summary, binding it to one or more types becomes optional. Even if you bind the named summary to a type and later change the summary string for that type, the named summary will not be changed. You can delete named summaries by using the type summary delete command, as if the summary name was the data type that the summary is applied to A summary attached to a variable using the –summary option, has the same semantics that a custom format attached using the -f option has: it stays attached until you attach a new one, or until you let your program run again. ## Synthetic children Summaries work well when you can navigate through an expression path. For LLDB to do this, the appropriate debugging information must be available. Some types are opaque, i.e. no knowledge of their internals is provided. When that is the case, expression paths do not work correctly. In other cases, the internals are available to use in expression paths, but they do not provide a user-friendly representation of the object’s value. For instance, consider an STL vector, as implemented by the [GNU C++ Library](http://gcc.gnu.org/onlinedocs/libstdc++/) (lldb) frame variable numbers -T (std::vector) numbers = { (std::_Vector_base >) std::_Vector_base > = { (std::_Vector_base >::_Vector_impl)_M_impl = { (int *) _M_start = 0x00000001001008a0 (int *) _M_finish = 0x00000001001008a8 (int *) _M_end_of_storage = 0x00000001001008a8 } } } Copy to clipboard Here you can see how the type is implemented, and you can write a summary for that implementation. But, it will not help you infer which items are actually stored in the vector. What you would like to see is probably something like: (lldb) frame variable numbers -T (std::vector) numbers = { (int) [0] = 1 (int) [1] = 12 (int) [2] = 123 (int) [3] = 1234 } Copy to clipboard Synthetic children are a way to get that result. The feature is based on the idea of providing a new set of children for a variable that replaces the ones available by default through the debug information. The example uses synthetic children to provide the vector items as children for the std::vector object. To create synthetic children, you must provide a Python class that adheres to a given *interface* [\[1\]](https://docs.qualcomm.com/doc/80-N3040-23/topic/variable-formatting.html#f1). For example, consider the following example: class SyntheticChildrenProvider: def init (self, valobj, internal_dict): # this call should initialize the Python object using valobj as the variable to provide synthetic children for def num_children(self): # this call should return the number of children that you want your object to have def get_child_index(self,name): # this call should return the index of the synthetic child whose name is given as argument def get_child_at_index(self,index): # this call should return a new LLDB SBValue object representing the child at the index given as argument def update(self): # 2 - this call should be used to update the internal state of this Python object whenever the state of the variables in LLDB changes. def has_children(self): # 3 - this call should return True if this object might have children, and False if this object can be guaranteed not to have children. Copy to clipboard `update(self)` [\[2\]](https://docs.qualcomm.com/doc/80-N3040-23/topic/variable-formatting.html#f2) and `has_children(self)` [\[3\]](https://docs.qualcomm.com/doc/80-N3040-23/topic/variable-formatting.html#f3) are optional. For examples of how synthetic children are created, look at examples/synthetic in the LLDB trunk ([http://llvm.org/svn/llvm-project/lldb/trunk/examples/synthetic/](http://llvm.org/svn/llvm-project/lldb/trunk/examples/synthetic/)). Be aware that the code in those files (except bitfield/) is legacy code and is not maintained. Look at this example to get a feel for this feature because it is an easy and well-commented example. The design pattern consistently used in synthetic providers shipped with LLDB is to use the init to store the SBValue instance as a part of self. The update function is then used to perform the actual initialization. After writing a synthetic children provider, you must load it into LLDB before it can be used: - Use the LLDB script command to type Python code interactively. - Or, use the command script import command to load Python code from a Python module (ordinary rules apply to importing modules this way). - Or, type the code for the provider class interactively while adding it. For example, consider a Foo class that makes available a synthetic children Foo\_Provider class in a Python module contained in the ~/Foo\_Tools.py file. The following interaction sets Foo\_Provider as a synthetic children provider in LLDB: (lldb) command script import ~/Foo_Tools.py (lldb) type synthetic add Foo --python-class Foo_Tools.Foo_Provider (lldb) frame variable a_foo (Foo) a_foo = { x = 1 y = "Hello world" } Copy to clipboard LLDB has synthetic children providers for a core subset of STL classes, both in the version provided by [libstdcpp](http://gcc.gnu.org/libstdc++/) and [libcxx](http://libcxx.llvm.org/), as well as for several Foundation classes. Synthetic children extend summary strings by enabling a new special variable: ${svar. This symbol tells LLDB to refer expression paths to the synthetic children instead of the real children. For example: (lldb) type summary add --expand -x "std::vector<" --summary-string "${svar%#} items" (lldb) frame variable numbers (std::vector) numbers = 4 items { (int) [0] = 1 (int) [1] = 12 (int) [2] = 123 (int) [3] = 1234 } Copy to clipboard In some cases, if LLDB cannot use the real object to get a child specified in an expression path, it will automatically refer to the synthetic children. While in summaries it is best to always use `${svar` to make your intentions clearer, interactive debugging can benefit from this behavior. For example: (lldb) frame variable numbers[0] numbers[1] (int) numbers[0] = 1 (int) numbers[1] = 12 Copy to clipboard Unlike many other visualization features, however, the access to synthetic children only works when using the frame variable, and it is not supported in the expression command: (lldb) expression numbers[0] Error [IRForTarget]: Call to a function '_ZNSt33vector >ixEm' that is not present in the target error: Couldn't convert the expression to DWARF Copy to clipboard The reason for this limitation () is that classes might have an overloaded operator [], or other special provisions, and the expression command chooses to ignore synthetic children in the interest of equivalence with code you asked to be compiled from source. As shown in this example, the expression command cannot parse and display some variables because the classes might have an overloaded operator [] or other special provision. Thus, the expression command ignores synthetic children in the interest of equivalence with the code you asked to be compiled from source. ## Filters Filters are a solution to the display of complex classes. At times classes have many member variables, but not all of them are necessary for you to see. A filter solves this issue by letting you see only those member variables you care about. Of course, you can easily implement the equivalent of a filter using synthetic children, but a filter lets you do the job without writing Python code. For example, if your class Foobar has member variables named A through Z, but you only need to see the variables named B, H, and Q, you can define the following filter: (lldb) type filter add Foobar --child B --child H --child Q (lldb) frame variable a_foobar (Foobar) a_foobar = { (int) B = 1 (char) H = 'H' (std::string) Q = "Hello world" } Copy to clipboard ## Categories Categories are a way to group related formatters. For instance, LLDB groups the formatters for the libstdc++ types in a category named gnu-libstdc++. Basically, categories serve as containers in which to store formatters for the same library or OS release. By default, several categories are created in LLDB: - Default The category where every formatter ends up, unless another category is specified. - gnu-libstdc++ Formatters for std::string, std::vector, std::list, and std::map as implemented by libstdcpp . - libcxx Formatters for std::string, std::vector, std::list, and std::map as implemented by libcxx. - system Truly basic types for which a formatter is required. - VectorTypes > > > Compact display for several vector types. The `type` command has several options that also include an add option: - `type filter add` - `type format add` - `type summary add` - `type synthetic add` To specify a custom category in which to add the formatter, use a type *<option>* add command with the –category (-w) option. For example, the following command automatically creates a (disabled) category named newcategory: (lldb) type summary add Foobar --summary-string "a foobar" --category newcategory Copy to clipboard To delete the formatter, you must specify the correct category. Categories can be in one of two states: enabled or disabled. A category is initially disabled and can be enabled using the type category enable command. To disable an enabled category, use the **type category disable** command. The order in which categories are enabled or disabled is significant, because LLDB uses that order when looking for formatters. Therefore, when you enable a category, it becomes the second one to be searched (after default, which always stays on top of the list). The default categories are enabled in such a way to use the following search order: 1. default 2. objc 3. gnu-libstdc++ 4. libcxx 5. VectorTypes 6. system As noted, gnu-libstdc++ and libcxx contain formatters for C++ STL data types. The system category contains formatters for char\* and char[], which reflect the behavior of older versions of LLDB that had built-in formatters for these types. Because these are now formatters, you can even replace them with your own versions. No special command exists to create a category. When you place a formatter in a category, if that category does not exist, it is automatically created. For example: (lldb) type summary add Foobar --summary-string "a foobar" --category newcategory Copy to clipboard This command automatically creates a (disabled) category named newcategory. Another way to create a new (empty) category is to enable it, as in: (lldb) type category enable newcategory Copy to clipboard However, in this case LLDB warns you that enabling an empty category has no effect. If you add formatters to the category after enabling it, they will be honored. But an empty category itself does not change the way any type is displayed. The reason the debugger warns you is because enabling an empty category might be a typo, and you effectively wanted to enable a similarly named but not empty category. ## Finding formatters 101 Given a variable, the process of searching for a formatter (including formats, starting in SVN rev r192217 [\[4\]](https://docs.qualcomm.com/doc/80-N3040-23/topic/variable-formatting.html#f4)) involves a rather intricate set of rules. LLDB starts looking in each enabled category, according to the order in which they were enabled (latest enabled first). In each category, LLDB does the following: 1. If there is a formatter for the type of the variable, use it. 2. If this object is a pointer, and there is a formatter for the pointee type that does not skip pointers, use it. 3. If this object is a reference, and there is a formatter for the referred type that does not skip references, use it. 4. If this object type is a typedef, go through the typedef hierarchy. (LLDB might not be able to do this if the compiler has not emitted enough information.) If the required information to traverse typedef hierarchies is missing, type cascading will not work. (The LLVM Clang compiler emits the correct debugging information for LLDB to cascade.) If at any level of the hierarchy there is a valid formatter that can cascade, use it. 5. If everything has failed, repeat the above search, looking for regular expressions instead of exact matches. 6. If any of those attempts returned a valid formatter to be used, that one is used, and the search is terminated (without going to look in other categories). If nothing was found in the current category, the next enabled category is scanned according to the same algorithm. If there are no more enabled categories, the search has failed. Note Previous versions of LLDB defined cascading to mean not only going through typedef chains, but also through inheritance chains. This feature has been removed because it significantly degrades performance. You must set up your formatters for every type in inheritance chains to which you want the formatter to apply. Footnotes [[1](https://docs.qualcomm.com/doc/80-N3040-23/topic/variable-formatting.html#id1)] The term is italicized because Python has no explicit notion of interface in the sense of a given set of methods that must be implemented by a Python class ([http://en.wikipedia.org/wiki/Duck_typing](http://en.wikipedia.org/wiki/Duck_typing)) [[2](https://docs.qualcomm.com/doc/80-N3040-23/topic/variable-formatting.html#id2)] This method is optional. Also, it can optionally choose to return a value (starting with SVN rev153061/LLDB-134). If it returns a value and that value is TRUE, LLDB can cache the children and the children count that it previously obtained, and it will not return to the provider class to ask. If nothing (None) or anything other than TRUE is returned, LLDB discards the cached information and asks. Regardless, when necessary, LLDB will call update. [[3](https://docs.qualcomm.com/doc/80-N3040-23/topic/variable-formatting.html#id3)] This method is optional (starting with SVN rev166495/LLDB-175). While implementing it in terms of num\_children is acceptable, you are encouraged to look for optimized coding alternatives when appropriate. [[4](https://docs.qualcomm.com/doc/80-N3040-23/topic/variable-formatting.html#id4)] [http://llvm.org/viewvc/llvm-project?view=revision&revision=192217](http://llvm.org/viewvc/llvm-project?view=revision&revision=192217) Last Published: Oct 06, 2026 [Previous Topic lldb.utils.symbolication.Symbolicator](https://docs.qualcomm.com/bundle/publicresource/80-N3040-23/topics/frame-symbolication.md)