Skip to content

Instantly share code, notes, and snippets.

@alanzeino
Last active February 27, 2024 14:06
Show Gist options
  • Save alanzeino/82713016fd6229ea43a8 to your computer and use it in GitHub Desktop.
Save alanzeino/82713016fd6229ea43a8 to your computer and use it in GitHub Desktop.
LLDB debugging with examples

LLDB Debugging Cheat Sheet

Commands

LLDB Commands

LLDB comes with a great set of commands for powerful debugging.

help

Your starting point for anything. Type help to get a list of all commands, plus any user installed ones. Type 'help <command-name> for more information on a command. Type help <command-name> <option> to get help for a specific option in a command too.

apropos

This is how you search in lldb for a command, or an option. apropos <search-term> should help you find what you're looking for.

breakpoint

Setting breakpoints in lldb is easy.

  • breakpoint set -l <line-number>; sets a breakpoint on a line in the current context.
  • breakpoint set --file <file-name> -l <line-number>; sets a breakpoint on a line on a given file.
  • breakpoint set --name <method-name>; sets a breakpoint on a given function name, globally. e.g., breakpoint set --name viewDidLoad or breakpoint set --name "-[UIView setFrame:]".
  • breakpoint set --selector <selector-name>; sets a breakpoint on a selector, globally. e.g., breakpoint set --selector dealloc.

expression

Expression can help you evaluate code! Helpful when you need to change some stuff, but can't recompile for some reason.

  • expr <return-type><expression>; e.g., expr (UIViewController *)[((UIViewController *)0x7f9492b70570).navigationController popViewControllerAnimated:YES]

By default, running an expression ignores breakpoints. You can force it to stop on any relevant breakpoints with --ignore-breakpoints.

  • expr --ignore-breakpoints false -- <expression>; e.g., expression --ignore-breakpoints false -- [self methodName]

You can even create new code and evaluate it inline.

  • expr for (int i = 0; i < 5; i++) { (void)NSLog(@"Meow"); }

Setting a global variable can help you keep around a reference to a given object, as long as it isn't deallocated from memory.

  • expr <type-name> $<variable-name> = <r-value>; e.g., expr UIWindow* $variable_name = 0x10d72852e.

Then you can use that variable to your hearts content. Omitting $ sets the scope for the variable only locally defined.

  • expr <type-name> <variable-name> = <r-value>; e.g., expr UIWindow* variable_name = 0x10d85832e.

thread

Manipulating the program counter with thread is super awesome.

If you spend all your time clicking step and step and step in xcode to get to a specific line, thread until can help you do this faster. thread until will continue all execution until that line, even if it is well inside several lines of conditional code.

  • thread until <line-number>; e.g., thread until 45

Even better, what if you want to skip the execution of a few lines? You could of course comment the lines out and recompile, but thread jump is faster.

  • thread jump -b <offset>; e.g., thread jump -b 2 will jump to two lines away, skipping those two lines in between.

Combine this with a breakpoint that continues after evaluation and suddenly you've permanently commented out two lines without even recompiling.

What if you want to just stop executing anything in a method you're in?

  • thread return

Need to know where you are in the stack?

  • thread backtrace

watchpoint

Need to know when a variable pointer changes? Use watchpoint set.

  • watchpoint set <variable-name>; e.g., watchpoint set _imageView.

Variable exists inside another object?

  • watchpoint set variable <object-name>-><variable-name>' e.g., watchpoint set variable self->personImageView.

frame

Print out a list of all variables in the current frame. Very useful when you don't like the way Xcode shows variables.

  • frame variable

Need to know where you are?

  • frame info

Chisel Commands

https://github.com/facebook/chisel

Chisel adds a number of awesome lldb commands that can help you debug like a master. Install it using the instructions provided and you can use the commands in LLDB just like the standard ones. If they sometimes done work, run command source ~/.lldbinit to load them again instead of closing and reopening Xcode.

pvc

Prints out a list of all view controllers currently displayed. Helpful when you need to start digging after pausing execution and you don't have the context you'd get from a breakpoint. Works by finding all displayed UIWindow instances, and starting from rootViewController.

  • pvc

pviews

Prints out a recursive description of all views and subviews.

  • pviews

fv

Helps you find a specific view currently on screen.

  • fv <search-term>; e.g., fv imageView.

fvc

Helps you find a specific view controller currently displayed.

  • fvc <search-term>; e.g., fvc requestviewcontroller.

presponder

Debug the responder chain for a control.

  • presponder <variable-name>; e.g., presponder _nameTextField.

bmessage

Same thing as breakpoint set --selector. A little smarter in that it goes up the superclass hierarchy if it doesn't find the selector, and sets the breakpoint when it does even if it's in a superclass.

  • bmessage <expression>; e.g., bmessage "-[MyView setFrame:]".

visualize

Given a view, visualize will composite all the subviews of the view into one image, save it to a PNG, and open it in Preview.app.

  • visualize <view-variable-name>; e.g., visualize _tableView.

show/hide

Shows and hides a view or layer.

  • show <view-variable-name>; e.g., show _tableView.

  • hide <view-variable-name>; e.g., hide _tableView.

pjson

Prints a JSON representation of an NSArray or NSDictionary.

  • pjson <object-variable-name>; e.g., pjson dictionary.

pdata

Prints a string representation of an NSData object.

  • pdata <object-variable-name>; e.g., pdata data.

The default encoding is UTF-8, which is analogous to typing this in LLDB (where 4 == NSUTF8StringEncoding):

po (NSString *)[[NSString alloc] initWithData:data encoding:(NSStringEncoding)4]

pcurl

Amazing command if you work heavily with networking code. Converts an NSURLRequest to a curl command and spits it out.

  • pcurl <object-variable-name>; e.g., pcurl urlRequest.

mwarning

Simulates a memory warning.

  • mwarning

Analogous to typing this in LLDB:

expr (void)[[UIApplication sharedApplication] performSelector:@selector(_performMemoryWarning)]

Reveal

http://revealapp.com

Similar to the View Debugger in Xcode 6, but actually useful. You can change fields, toggle properties, and see classes Apple doesn't want you to see.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment