Prettifying Debug Variables in C++ with LLDB
Tags: cpp, lldb, debugging, tutorial
Published: 2020-05-14 06:22:00

---
title: Prettifying Debug Variables in C++ with LLDB
published: true
description: A quick introduction to variable pretty-printing in LLDB
tags: #cpp, #lldb, #debugging, #tutorial
---

## Prerequisites
This post is a quick introduction to variable formatting in LLDB, and so it assumes some familiarity with LLDB and C++ debugging.
To learn more about LLDB, please visit either of the following: 
* [Official Tutorial](https://lldb.llvm.org/use/tutorial.html)
* [PDR: LLDB Tutorial](https://aaronbloomfield.github.io/pdr/tutorials/02-lldb/index.html)
* [Advanced Debugging — Part 1: LLDB Console](https://medium.com/better-programming/advanced-debugging-part-1-lldb-console-5fe8cff13a93)
* [Improve Debugging Efficiency with LLDB](http://www.topcoder.com/thrive/articles/Improve%20Debugging%20Efficiency%20with%20LLDB)
* [LLDB and the Command Line](https://hub.packtpub.com/lldb-and-command-line/)

## What is variable formatting?

LLDB has ways of quickly representing the values of variables we see when debugging either through an IDE or the command line. 

For example, this is how debug variables and their values look like in CLion:

![Variables in CLion's Debug View](https://dev-to-uploads.s3.amazonaws.com/i/w5nswwikivy1it40zg9o.png)

## Why do we need to customize them?

While the defaults work perfectly well in the majority of cases, there are times when having a custom summary can significantly enhance readability and save time. 


### Consider the following example with color:

```cpp
using Color = uint32_t;
Color color = 0xFF880022; // ARGB
```

Without any formatters, the value would appear as an integer:
![Color without formatting](https://dev-to-uploads.s3.amazonaws.com/i/k9oq8u8uoor28qxi6r9s.png)

We can format `Color` types as hex by running the following command in an LLDB command-line session:
```
type format add -f hex Color
```
The value is now more readable:
![Color with formatting](https://dev-to-uploads.s3.amazonaws.com/i/hgtzswmkh1j68jatk789.png)

The ARGB channels can also be displayed via Python scripting (more below):
![Color with summary](https://dev-to-uploads.s3.amazonaws.com/i/v5y2o3a2d05kbr53ghc8.png)

## How to add custom summaries?

LLDB commands may be run either through the command-line (also available during a debug session in the IDE) or via a `.lldbinit` file in the home directory.

It is also possible to automatically load `.lldbinit` files from the current directory by specifying `settings set target.load-cwd-lldbinit true` in `~/.lldbinit` , which is useful for project-specific customizations.

Additional `.lldb` and `.py` files may be loaded via:

```
command script import /path/to/script.py
command source /path/to/script.lldb
```

The ARGB summary above can now be defined as a Python function:

```python
def ColorSummary(valobj, internal_dict):
  value = valobj.GetValueAsUnsigned(0);
  alpha = (value >> 24) & 0xFF
  red = (value >> 16) & 0xFF
  green = (value >> 8) & 0xFF
  blue = (value >> 0) & 0xFF
  return 'A: {}, R: {}, G: {}, B: {}'.format(alpha, red, green, blue)
```

To register it, first import the file, [`Summaries.py`](http://summaries.py), and associate the `ColorSummary` function to the `Color` type:

```
command script import ./Summaries.py
type summary add -F Summaries.ColorSummary Color
```

More information about defining function summaries can be found [here](http://lldb.llvm.org/use/variable.html#python-scripting).
The `valobj` variable is just a wrapper around the C++ variable and its type is an [lldb.SBValue](https://lldb.llvm.org/python_reference/lldb.SBValue-class.html).

### Synthetic Children
![Color with Synthetic Children](https://dev-to-uploads.s3.amazonaws.com/i/nmmvnbmhmwcvmxgkgyoe.png)
LLDB also supports defining custom children for any type. Instead of having the color channels be part of the summary, let's define them as synthetic children.

```python
class ColorSyntheticProvider:
  def __init__(self, valobj, internal_dict):
      self.valobj = valobj

  def num_children(self):
    return 4

  def get_child_at_index(self, index):
    if index < 0 or index > 3:
      return None

    value = self.valobj.GetValueAsUnsigned(0);
    value = (value >> 24 - index * 8) & 0xFF
    name = ['A', 'R', 'G', 'B'][index]
    childType = self.valobj.target.GetBasicType(lldb.eBasicTypeInt)
    return self.valobj.CreateValueFromData(name, 
                                           lldb.SBData.CreateDataFromInt(value), 
                                           childType)
```

Reference: [Synthetic Children](http://lldb.llvm.org/use/variable.html#synthetic-children), [lldb.eBasicTypeInt](https://lldb.llvm.org/python_reference/lldb-module.html), [lldb.SBData](https://lldb.llvm.org/python_reference/lldb.SBData-class.html)

And the command to register the provider inside the `.lldbinit` file:

```python
type synthetic add -l Summaries.ColorSyntheticProvider Color
```

## Where to go from here?

- The [official documentation](http://lldb.llvm.org/use/variable.html) is excellent and covers all the details.
- [Filters](http://lldb.llvm.org/use/variable.html#filters) may be used to hide children that are not useful for debugging.
- [Regex Typenames](http://lldb.llvm.org/use/variable.html#regular-expression-typenames) are particularly handy for registering summaries for templated types.
- More examples can be found on the [LLVM repository](https://github.com/llvm/llvm-project/blob/master/lldb/test/API/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py).
- For specific information about any command, simply type

    `help <command> <sub-command>` .