# Get started This chapter assumes you are familiar with the GDB debugger commands. ## Start the debugger To start LLDB from a command line, enter: hexagon-lldb Copy to clipboard Where program is the name of an executable Hexagon file. Once started, LLDB displays a command line: (lldb) Copy to clipboard To perform a debug command, type the command name into the command line and press **Return**. After the command is performed, the command line reappears. It will continue to reappear after every debug command until you perform a command that exits LLDB. ## Debug commands Compared to the GDB command set, which is rather free-form, the LLDB command syntax is structured. All commands have the following form: noun verb [-options [option-value]] [argument [argument...]] Copy to clipboard Command line parsing is performed before command execution, so it is uniform across all commands. The syntax for basic commands is quite simple: arguments, options, and option values are all separated by white spaces, and double quotes are used to protect white spaces in an argument. To put a backslash (`\\`) or double quote (`"`) character in an argument, prefix it with a backslash in the argument, e.g. (`\\\\`). This makes the command syntax more regular, but it also means you might need to quote some arguments in LLDB that you would not in GDB. ### Command arguments LLDB attempts to reduce the number of special purpose argument parsers that are required, which sometimes forces you to be more explicit when specifying a command. For instance, to set a breakpoint in GDB, enter the following to break at line 12 of foo.c: (gdb) break foo.c:12 Copy to clipboard And enter the following to break at the function foo: (gdb) break foo Copy to clipboard The argument parser that GDB uses to distinguish foo.c:12 from foo from foo.c::foo (which specifies the function foo in the file foo.c) is complex. As a result, cases exist in GDB where it is virtually impossible to specify the function you want to break on, especially when using C++. By comparison, LLDB commands are more verbose but also more precise, and they allow for intelligent auto-completion. To set the same file and line breakpoint in LLDB, you can enter either of the following commands: (lldb) breakpoint set --file foo.c --line 12 (lldb) breakpoint set -f foo.c -l 12 Copy to clipboard To set a breakpoint on a function named foo, you can enter either of the following commands: (lldb) breakpoint set --name foo (lldb) breakpoint set -n foo Copy to clipboard You can specify the `--name` option multiple times to set a breakpoint on a group of functions. This is convenient because it enables you to set common conditions or commands without specifying them multiple times. For example: (lldb) breakpoint set --name foo --name bar Copy to clipboard ### Breakpoints In LLDB, you can set a breakpoint at a function using a method name. For instance, to set a breakpoint on all C++ methods named foo, you can use either of the following commands: (lldb) breakpoint set --method foo (lldb) breakpoint set -M foo Copy to clipboard To limit any breakpoints to a specific executable image, use the command option, –shlib path (or -s path for short). For example: (lldb) breakpoint set --shlib foo.dylib --name foo (lldb) breakpoint set -s foo.dylib -n foo Copy to clipboard You can repeat the –shlib option to specify several shared libraries. ### Completion Like GDB, the LLDB command interpreter performs the shortest unique string match on command names, so the following two commands will both execute the same command: (lldb) breakpoint set -n "-[SKTGraphicView alignLeftEdges:]" (lldb) br s -n "-[SKTGraphicView alignLeftEdges:]" Copy to clipboard LLDB also supports command completion for source file names, symbol names, file names, and so on. Press the **Tab** key to initiate completion. Note Tab completion is not supported in Windows. Individual options in a command can have different *completers*. For example, in the breakpoint command, –file completes to source files, –shlib completes to currently loaded shared libraries, and so on. You can also do things like this: if you specify –shlib and are completing on –file, LLDB will list only the source files in the shared library specified by –shlib. ### Help The individual LLDB commands are extensively documented. Use the help command to get an overview of which commands are available, or to obtain details on specific commands. There is also an apropos command, which searches the help text for all commands for a specified word, and then dumps a summary help string for each matching command. In some cases, the LLDB help system can provide information on the individual arguments of a command. For example: (lldb) help break command add Copy to clipboard Add a set of commands to a breakpoint, to be executed whenever the breakpoint is hit. Syntax: `breakpoint command add ...` When you see command arguments specified with angle brackets in the command syntax (such as <breakpt-id> in the example above), this indicates a common argument type that you can get further help on: (lldb) help -- Breakpoint ID's consist major and minor numbers; the major ... Copy to clipboard ### Aliases LLDB provides a mechanism for defining aliases for commonly used commands. For example, instead of entering this command: Copy to clipboard (lldb) breakpoint set –file foo.c –line 12 You can enter the following commands: (lldb) command alias bfl breakpoint set -f %1 -l %2 (lldb) bfl foo.c 12 Copy to clipboard Several aliases are predefined for commonly used commands (such as step, next, and continue). However, you can customize the LLDB command set in any way, and because LLDB reads the *~/.lldbinit* file at startup, you can store all your aliases in this file so they are available to you. Note Your aliases are also documented in the help command, so you can remind yourself which aliases you have defined. One of the predefined aliases is a weak emulator of the GDB break command. This command does not try to do everything the GDB break command can do (for example, it does not handle foo.c::bar). But it mostly works, and it makes the transition easier from GDB to LLDB. For convenience, the break command is aliased to b. But if you want to learn the LLDB command that is set natively, the b alias will get in the way of using the rest of the LLDB breakpoint commands. Fortunately, if you do not like a predefined alias, you can delete it with the unalias command. For example: (lldb) command unalias b Copy to clipboard Once the command alias is freed, use the following command to run the native LLDB breakpoint command with just b: (lldb) command alias b breakpoint Copy to clipboard ### Raw commands The LLDB command parser supports *raw* commands where, after any command options are stripped off, the rest of the command string is passed uninterpreted to the command. Raw commands are convenient for commands whose arguments might be a complex expression that would be painful to protect with backslashes. For example, the expression command is a raw command for obvious reasons. The help output for a command will tell you if the command is raw or not, so you know what to expect. When using raw commands, remember that raw commands can still have options. If your command string has any dashes in it, you must indicate that they are not option markers by putting – after the command name but before your command string. For example: watch set expr --size 8 -- 0x3fefff00 Copy to clipboard ### Python interpreter LLDB has a built-in Python interpreter, which is accessible with the script command. All the functionality of the debugger is available as classes in the Python interpreter. Thus, the more complex commands that in GDB you would introduce with the define command can be performed in LLDB by writing Python functions using the lldb-Python library. Then load the scripts into your running session and access them with the script command. ## Load a program As with GDB, you can use a single command to both start LLDB and specify the file to debug: lldb /Projects/Sketch/build/Debug/Sketch.app Current executable set to '/Projects/Sketch/build/Debug/Sketch.app' (x86_64). Copy to clipboard Or, you can use the file command to specify the file after the fact: lldb (lldb) **file /Projects/Sketch/build/Debug/Sketch.app** Current executable set to '/Projects/Sketch/build/Debug/Sketch.app' (x86_64). Copy to clipboard ## Set breakpoints To see all the options available for setting a breakpoint, use the help breakpoint set command. For example: (lldb) breakpoint set --selector alignLeftEdges: Breakpoint created: 1: name = 'alignLeftEdges:', locations = 1, resolved = 1 Copy to clipboard You can list the breakpoints that you already set: (lldb) breakpoint list Current breakpoints: 1: name = 'alignLeftEdges:', locations = 1, resolved = 1 1.1: where = Sketch\`-[SKTGraphicView alignLeftEdges:] + 33 at /Projects/Sketch/SKTGraphicView.m:1405, address = 0x0000000100010d5b, resolved, hit count = 0 Copy to clipboard Setting a breakpoint creates a *logical* breakpoint, which can resolve to one or more actual locations. For example, *break byselector* sets a breakpoint on all the methods that implement that selector in the classes in your program. Similarly, a file and line breakpoint might result in multiple locations if that file and line are inlined in different places in your code. A logical breakpoint has an integer identifier, and its locations have an identifier within their parent breakpoint. The two identifiers are joined by the a . character. For example, see the 1.1 string in the example above. Also, logical breakpoints remain *live*, so if another shared library is loaded and it has another implementation of the alignLeftEdges: selector, the new location is added to breakpoint 1 (in this case, a breakpoint named 1.2 is set on the newly loaded selector). The other piece of information provided in a breakpoint listing is whether the breakpoint location was *resolved* or not. A location is resolved when the file address to which it corresponds is loaded into the program you are debugging. For example, if you set a breakpoint in a shared library that subsequently is unloaded, that breakpoint location remains but it is no longer be resolved. GDB users should note that LLDB works like GDB does after using this command: (gdb) set breakpoint pending on Copy to clipboard That is, LLDB always makes a breakpoint from your specification, even if it cannot find any locations that match the specification. You can tell whether an expression was resolved by checking the locations field in the breakpoint list. A breakpoint is reported as pending when you set it, so you can more easily determine if you have made a typo (if that was the reason no locations were found): (lldb) breakpoint set --file foo.c --line 12 Breakpoint created: 2: file ='foo.c', line = 12, locations = 0 (pending) WARNING: Unable to resolve breakpoint to any actual locations. Copy to clipboard You can delete, disable, set conditions on, and ignore counts either on all the locations generated by your logical breakpoint or on one location your specification resolved to. For example, the following command prints a backtrace when the breakpoint is hit: (lldb) breakpoint command add 1.1 Enter your debugger command(s). Type 'DONE' to end. > bt > DONE Copy to clipboard By default, the breakpoint command add accepts LLDB commands on the command line. You can also specify this explicitly by passing the –command option. To implement your breakpoint command using the Python script, use the –script option. ## Set watchpoints In addition to breakpoints, you can use the help watchpoint command to see all the commands for watchpoint manipulations. For example, the following command watches a variable named global for a write operation, but it stops only if the condition (global==5) is true: (lldb) watch set var global Watchpoint created: Watchpoint 1: addr = 0x100001018 size = 4 state = enabled type = w declare @ '/Volumes/data/lldb/svn/ToT/test/functionalities/ watchpoint/watchpoint_commands/condition/main.cpp:12' (lldb) watch modify -c '(global==5)' (lldb) watch list Current watchpoints: Watchpoint 1: addr = 0x100001018 size = 4 state = enabled type = w declare @ '/Volumes/data/lldb/svn/ToT/test/functionalities/ watchpoint/watchpoint_commands/condition/main.cpp:12' condition = '(global==5)' (lldb) c Process 15562 resuming (lldb) about to write to 'global'... Process 15562 stopped and was programmatically restarted. Process 15562 stopped and was programmatically restarted. Process 15562 stopped and was programmatically restarted. Process 15562 stopped and was programmatically restarted. Process 15562 stopped * thread #1: tid = 0x1c03, 0x0000000100000ef5 a.out`modify + 21 at main.cpp:16, stop reason = watchpoint 1 frame #0: 0x0000000100000ef5 a.out`modify + 21 at main.cpp:16 13 14 static void modify(int32_t &var) { 15 ++var; -> 16 } 17 18 int main(int argc, char*\* argv) { 19 int local = 0; (lldb) bt * thread #1: tid = 0x1c03, 0x0000000100000ef5 a.out`modify + 21 at main.cpp:16, stop reason = watchpoint 1 frame #0: 0x0000000100000ef5 a.out`modify + 21 at main.cpp:16 frame #1: 0x0000000100000eac a.out`main + 108 at main.cpp:25 frame #2: 0x00007fff8ac9c7e1 libdyld.dylib`start + 1 (lldb) frame var global (int32_t) global = 5 (lldb) watch list -v Current watchpoints: Watchpoint 1: addr = 0x100001018 size = 4 state = enabled type = w declare @ '/Volumes/data/lldb/svn/ToT/test/functionalities/watchpoint/ watchpoint_commands/condition/main.cpp:12' condition = '(global==5)' hw_index = 0 hit_count = 5 ignore_count = 0 (lldb) Copy to clipboard ## Start your program To launch a program in LLDB, use the process launch command or one of its built-in aliases. For example: (lldb) process launch (lldb) run (lldb) r Copy to clipboard Note The process launch command automatically launches the Hexagon simulator and connects LLDB to it. After you launch a process, your process might stop somewhere: (lldb) process launch Hexagon-sim INFO: the rev_id used in the simulation is 0x00002105 (v5a) hexagon-sim WARNING: StartGDBserver:Setting up GDB server on port 10437 Process 1 stopped Process 1 launched: './factorial' (hexagon) Process 1 stopped * thread #1: tid = 0x0001, 0x00004130 factorial`main(argc=1,argv=0x0000b100) + 28 at factorial.c:32, stop reason = breakpoint 1.1 frame #0: 0x00004130 factorial`main(argc=1, argv=0x0000b100) + 28 at factorial.c:32 Copy to clipboard Note After a process is launched, the simulator output will be mixed with the LLDB output. ## Control your program After a program is launched, it can execute until it hits a breakpoint. The basic commands for controlling execution are all variations of the thread command. For example: (lldb) thread continue Resuming thread 0x2c03 in process 46915 Resuming process 46915 (lldb) Copy to clipboard Currently you can only operate on one thread at a time. However, in the future, LLDB will support commands of the form *step over thefunction in thread 1*, *step into the function in thread 2*, and *continue thread 3*, and so on. When LLDB eventually supports some threads running while others are stopped, this will be particularly important. For convenience, all the stepping commands have simple command aliases. For instance, the alias for thread continue is just the letter c. The other program stepping commands are mostly the same as in GDB: | **LLDB command** | **GDB command** | | --- | --- | | thread step-in | step s | | thread step-over | next n | | thread step-out | finish f | By default, LLDB defines aliases for all the common GDB control commands (s, step, n, next, finish). If any are missing, you can add them to your ~/.lldbinit file using the command alias command. LLDB also supports the *step by instruction* command variants: | **LLDB command** | **GDB command** | | --- | --- | | thread step-inst | stepi si | | thread step-over-inst | nexti ni | Finally, LLDB includes a *run until line or frame exit* stepping mode: (lldb) **thread until 100** Copy to clipboard This command either runs the thread in the current frame until it reaches line 100 in this frame, or it stops if it leaves the current frame. This behavior is almost equivalent to the GDB until command. By default, a process shares the LLDB terminal with the inferior process. In this mode (like when debugging with GDB), when the process is running, anything you type goes to the standard input of the inferior process. To interrupt the inferior program, press **Ctrl+C**. If you launch a process with the –no-stdin option, the command interpreter is always available to enter commands. This allows you to set a breakpoint, for example. without explicitly interrupting the program you are debugging: (lldb) process continue (lldb) breakpoint set --name stop_here Copy to clipboard Note For GDB users, it might seem odd to always have the (lldb) prompt. Many LLDB commands do not work while a program is running; the command interpreter should notify you when this is the case. (If you find any instances where the command interpreter is not doing its job, please file a bug report.) The commands that work while a program is running include: - Interrupting the process to halt execution (`process interrupt`) - Getting the process status (`process status`) - Setting and clearing the breakpoint (`breakpoint [set|clear|enable|disable|list] ...`) - Reading and writing memory (`memory [read|write] ...`) The issue of disabling stdio while running is a good opportunity to show how to set debugger properties in general. If you always want to run in the –no-stdin mode, you can set it as a generic process property using the LLDB settings command, which is equivalent to the GDB set command. For example, in this case you can specify the following command: (lldb) settings set target.process.disable-stdio true Copy to clipboard Over time, the GDB set command was expanded into many disordered options, such that there were useful options that even experienced GDB users did not know about because these options were too hard to find. By contrast, LLDB organizes the settings hierarchically, using the structure of the basic entities in the debugger. Anywhere you can specify a setting on a generic entity (such as threads), you can also apply the option to a specific instance, which can be convenient in some cases. You can view the available settings with settings list, and the settings command provides help explaining how the command works. ## Examine the thread state When you stop a program, LLDB chooses a current thread (usually the one that stopped for a reason), and a current frame in that thread (on stop, this is always the bottom-most frame). Many of the commands that are used to inspect state choose their current thread/frame in this way. To inspect the current state of your process, start with listing the threads: (lldb) thread list Process 46915 state is Stopped * thread #1: tid = 0x2c03, 0x00007fff85cac76a, where = libSystem.B.dylib` getdirentries64 +10, stop reason = signal = SIGSTOP, queue = com.apple.main-thread thread #2: tid = 0x2e03, 0x00007fff85cbb08a, where = libSystem.B.dylib`kevent + 10, queue = com.apple.libdispatch-manager thread #3: tid = 0x2f03, 0x00007fff85cbbeaa, where = libSystem.B.dylib\` workq_kernreturn + 10 Copy to clipboard The \* in this listing indicates that thread 1 is the current thread. To list the backtrace for that thread, use the thread backtrace command: (lldb) thread backtrace thread #1: tid = 0x2c03, stop reason = breakpoint 1.1, queue = com.apple. main-thread frame #0: 0x0000000100010d5b, where = Sketch-[SKTGraphicViewalignLeftEdges:] + 33 at /Projects/Sketch/SKTGraphicView.m:1405 frame #1: 0x00007fff8602d152, where = AppKit-`[NSApplication sendAction:to:from:] + 95 frame #2: 0x00007fff860516be, where = AppKit`-[NSMenuItem_corePerformAction] + 365 frame #3: 0x00007fff86051428, where = AppKit`-[NSCarbonMenuImplperformActionWithHighlightingForItemAtIndex:] + 121 frame #4: 0x00007fff860370c1, where = AppKit`-[NSMenuperformKeyEquivalent:] + 272 frame #5: 0x00007fff86035e69, where = AppKit`-[NSApplication_handleKeyEquivalent:] + 559 frame #6: 0x00007fff85f06aa1, where = AppKit`-[NSApplicationsendEvent:] + 3630 frame #7: 0x00007fff85e9d922, where = AppKit`-[NSApplication run] + 474 frame #8: 0x00007fff85e965f8, where = AppKit`NSApplicationMain + 364 frame #9: 0x0000000100015ae3, where = Sketch`main + 33 at /Projects/Sketch/SKTMain.m:11 frame #10: 0x0000000100000f20, where = Sketch`start + 52 Copy to clipboard You can also provide a list of threads to backtrace, or the all keyword to see all threads: (lldb) thread backtrace all Copy to clipboard You can select the current thread (which will be used by default in all the commands in [Examine the stack frame state](https://docs.qualcomm.com/doc/80-N3040-23/topic/lldb-debugger-get-started.html#examine-the-stack-frame-state)) with the thread select command: (lldb) thread select 2 Copy to clipboard Where the thread index is only the one shown in the thread list listing. ## Examine the stack frame state Use the frame variable command to display a stack frame’s arguments and local variables. For example: (lldb) frame variable self = (SKTGraphicView *) 0x0000000100208b40 _cmd = (struct objc_selector *) 0x000000010001bae1 sender = (id) 0x00000001001264e0 selection = (NSArray \*) 0x00000001001264e0 i = (NSUInteger) 0x00000001001264e0 c = (NSUInteger) 0x00000001001253b0 Copy to clipboard As shown in this example, if you do not specify any variable names, all arguments and locals are displayed. If you invoke the frame variable command with the names of specific locals, only those variables are printed. For example: (lldb) frame variable self (SKTGraphicView *) self = 0x0000000100208b40 Copy to clipboard You can also specify the path to a sub-element of one of the available locals, and that sub- element is printed: (lldb) frame variable self.isa (struct objc_class *) self.isa = 0x0000000100023730 Copy to clipboard The frame variable command is not a full expression parser, but it does support a few basic operators such as &, \*, ->, [] (no overloaded operators). Use the array brackets on pointers to treat pointers as arrays: (lldb) frame variable *self (SKTGraphicView *) self = 0x0000000100208b40 (NSView) NSView = { (NSResponder) NSResponder = { ... (lldb) frame variable &self (SKTGraphicView **) &self = 0x0000000100304ab (lldb) frame variable argv[0] (char const *) argv[0] = 0x00007fff5fbffaf8 "/Projects/Sketch/build/Debug/Sketch.app/Contents/MacOS/Sketch" Copy to clipboard The frame variable command also performs *object printing* operations on variables. Enable this feature by using the -O option with the frame variable command: (lldb) frame variable -O self (SKTGraphicView *) self = 0x0000000100208b40 Copy to clipboard Use the frame select command to select another stack frame to display: (lldb) frame select 9 frame #9: 0x0000000100015ae3, where = Sketch`function1 + 33 at /Projects/Sketch/SKTFunctions.m:11 Copy to clipboard You can also move up or down the stack by using the –relative (-r) option with the frame select command. Also, the predefined command aliases u and d work like their GDB equivalents. To view more complex data or change program data, use the expression command. It takes an expression and evaluates it in the scope of the currently selected frame. For example: (lldb) expr self $0 = (SKTGraphicView *) 0x0000000100135430 (lldb) expr self = 0x00 $1 = (SKTGraphicView *) 0x0000000000000000 (lldb) frame var self (SKTGraphicView *) self = 0x0000000000000000 Copy to clipboard You can also call functions: (lldb) expr (int) printf ("I have a pointer 0x%llx.\\n", self) $2 = (int) 22 I have a pointer 0x0. Copy to clipboard The expression command is one of the raw commands, which means you are not required to quote your entire expression, backslash protect the quote marks, and so on. Finally, the results of the expressions are stored in persistent variables (of the form $[0-9]+) that you can use in more expressions: (lldb) expr self = $0 $4 = (SKTGraphicView *) 0x0000000100135430 Copy to clipboard Last Published: Oct 06, 2026 [Previous Topic Conventions](https://docs.qualcomm.com/bundle/publicresource/80-N3040-23/topics/lldb-debugger-ug-introduction.md) [Next Topic Use the debugger](https://docs.qualcomm.com/bundle/publicresource/80-N3040-23/topics/use-the-debugger.md)