LLDB | Debugging like a pro

standarizing unconformity

Index


When developing programs, it is crucial to have the ability to analyse its functionality at runtime. Several tools exist to achieve this goal, but since we are working in an environment that comes with Clang, we can make use of LLDB.

If you come from environments like Visual Studio, you are familiar with UI functionality like the play button to start debugging a program, the visual and interactive breakpoints, and windows that show the call stack and frame variables. All those shiny things may prevent you to jump into a console world where you are only shown text, and all the interaction has to be done by writing commands. Don't be fooled tho, the same can be achieved in this text based workflow, and it is perhaps, even more convenient.

Prepare the program for debugging

In order to get the most out of the LLDB debugger we need to compile our program in a way that it stores useful data to inspect.

Orientative debugging can be achieved by placing printf (and alike) function calls in key steps of our program.

The easiest way is to tell our compiler that we are going to debug the program via some flags:

CFLAGS += -g3 -O0 -fno-omit-frame-pointer

More and deeper information about the compiler flags can be found at the official CLANG docs

Run a program in debug mode

After compiling our program in debug mode, we need to call our binary through LLDB. We can pass arguments to our program if we need it too.

lldb ./test-program -- [args]

Once we are inside the LLDB text interface, we can hit r and press return to run the program. If no errors appear, it will reach exit or loop condition and wait.

The official LLDB site has deeper information, refer there if needed.

Basic navigation in LLDB

As in most cli programs, navigation in LLDB works by entering commands using the keyboard.

Basic navigation gets us covered in running and stepping (over, into and out) through the execution timeline.

Set breakpoints

Of course the main point is to observe our program behavior at certain points in the execution timeline, not just running the program until it fails or exits. To do so, we can instruct LLDB to set breakpoints.

Conditional breakpoints

We can also make a breakpoint raise only if certain conditions are met.

Some common patterns in conditional breakpoints can be string comparison, checking for null pointers, variable changes and array indexes or loop counter checks.

Interacting with breakpoints

Now that we have set some breakpoints through the code, it should be useful to list, enable, disable and / or modify them when required.

Inspecting data

Once we are inside a breakpoint, the next logical thing is to inspect data. To do so we can move through the call stack or access variables' data.

We can inspect the current value for [args] by running: settings show target.run-args.

Backtrace / call stack

Variables and expressions

Summing Up

There is much more that can be achieved with LLDB and CLANG to further improve debugging, but in the same way the “sports” mode of your car is not what you use for everyday driving, and the car still delivers, this compact command cheat-sheet should be able to get you covered in most case scenarios when debugging C programs in the command line.