LLDB is a new generation of high-performance debuggers built using the LLVM infrastructure. LLDB converts debugging information to clANG type so that it can take advantage of the clANG compiler infrastructure. That is, LLDB supports C/C++/OC language features and runtimes in its expressions without having to re-implement them. It also uses the compiler to handle all ABI interfaces, disassembly instructions, and extraction of instruction details when calling function expressions, taking the LLVM and Clang infrastructure to the extreme. Multiline expressions that declare local variables and types. The JIT expression of clang can be used directly when needed. When the JIT is not available, the intermediate representation IR is restored directly.

GDB to LLDB command map

LLDB

Abbreviations of LLDB commands: If a command has only one full name, it can be used as a shorthand.

P with Po

Note that this is not print and Print Object. Instead, expression — and ***expression –object-description –***.

po [[[UIApplication sharedApplication] keyWindow] recursiveDescription] po [[[UIWindow keyWindow] rootViewController] _printHierarchy] Po [[UIWindow keyWindow] recursiveDescription] Po [$myButton allTargets] # check the receiver of the button eventR11
po (Class)0x00000002821d6a00
Copy the code

A common Po is actually the same thing as an E-O.

Prints the result as an object

e -O -- myArray
Copy the code

Print format of p

p 16    # default format
p/x 16  # hex, 0x10
p/t 16  # binaryP /c Prints charactersCopy the code
  • Output Formats

expression

expr char *$str = (char *)malloc(8)
expr (void)strcpy($str, "munkeys")
expr $str[1] = 'o'
expr (void)free($str)
Copy the code

Use EXPR to dynamically debug:

expr id $myView = (id)0x7f82b1d01fd0
expr (void)[$myView setBackgroundColor:[UIColor blueColor]]
expr (void)[CATransaction flush] e $R11! .backgroundColor = UIColor.green e CATransaction.flush()Copy the code

Usually, changes in the interface cannot be seen until the program continues to run. Because the changes must be sent to the render service (backboardd).

The CATransaction flush operation updates the interface in real time without continuing, as is the case with Caflush in Chisel.

Dynamically manipulate UIViewController

e id $nvc = [[[UIApplication sharedApplication] keyWindow] rootViewController]
e id $vc = [UIViewController new]
e (void)[[$vc view] setBackgroundColor:[UIColor yellowColor]]
e (void)[$vc setTitle:@"Yay!"]
e (void)[$nvc pushViewContoller:$vc animated:YES]
caflush // e (void)[CATransaction flush]
Copy the code

Viewing stack Information

bt
bt all
Copy the code

The breakpoint

br list
br dis 1 Disable a breakpoint
br del 1 # delete a breakpoint
br s -a 0x0023234f
br set -f main.m -l 16 Create a breakpoint
breakpoint set -F "-[NSArray objectAtIndex:]"
br s -a 0x02107730+0x000ab000 -c '(BOOL)[(NSString *)$r2 isEqualToString:@"snakeninny"]'
b -[NSResponder mouseUp:]
Copy the code

Observed variables

watchpoint set v weakstr
Copy the code

dis

Disassembly, can be used to view NSMallocBlock information.

dis -s *(void**)(0x600002f51110+16)
Copy the code

Dis-s [memory address] This command can be used to disassemble the symbol information corresponding to an address and the beginning part of the assembly.

Because the internal offset of the block object is 16 bytes, the position is the address of the function that the block object holds executing code.

Internal implementation of block:

struct __block_impl { void *isa; 8 bytes int Flags; // 4 bytes int Reserved; // 4 bytes void *FuncPtr; // Therefore, the offset of the executing code corresponding to the block is 16 bytes}Copy the code

View memory x

Memory read format:

Memory_read /[quantity][format][number of bytes] Memory addressCopy the code

Abbreviations:

X /[Quantity][format][number of bytes] Memory addressCopy the code

Among them,

  • Format: x is hexadecimal, f is floating point, d is base 10.
  • Byte size: B is byte. H is half word(two bytes); W is word(4 bytes); G is for giant Word (8 bytes)
  • X /4xw 0x123456789: Indicates that word is read for four times in hexadecimal format.

Such as

(lldb) x/16xg 0x28118ed80
0x28118ed80: 0x000025a105bb2255 0x00000002811a3d80
0x28118ed90: 0x0000000282eda5e0 0x00000002821d6a00
0x28118eda0: 0x00000002831816c0 0x00000002805c6c10
0x28118edb0: 0x00000002805e4d50 0x0000000000000000
0x28118edc0: 0x000000028118ee00 0x000000028118f180
0x28118edd0: 0x0000000280ba8e88 0x0000000000000001
0x28118ede0: 0x0000000148431202 0x0000000000000001
0x28118edf0: 0x00000002808c8730 0x0000000000000000
Copy the code

Calculate by expression

x/1w `$str+ 3 `# remove the first three bytes of the STR string.
Copy the code

process

process plugin packet send qGetProfileData
Copy the code
(lldb) process plugin packet send qGetProfileData
  packet: qGetProfileData
response: num_cpu:2; host_user_ticks:53835219; host_sys_ticks:0; host_idle_ticks:304497309; elapsed_usec:1592816260139518; task_used_usec:11353; thread_used_id:7031e7; thread_used_usec:693129; thread_used_name:; thread_used_id:70326f; thread_used_usec:2256; thread_used_name:; thread_used_id:703272; thread_used_usec:4102; thread_used_name:636f6d2e6170706c652e75696b69742e6576656e7466657463682d746872656164; thread_used_id:703273; thread_used_usec:5171; thread_used_name:; thread_used_id:703274; thread_used_usec:1050; thread_used_name:; thread_used_id:703285; thread_used_usec:12; thread_used_name:; total:2099249152; used:1428979712; anonymous:13664256; phys_footprint:13959952; mem_cap:1450; cpu_cap_p:50;cpu_cap_t:180; --end--;Copy the code

View information consistent with the Profile tool. Xcode uses STD :: String MachTask::GetProfileData(DNBProfileDataScanType scanType) to retrieve App information. Such as:

static void GetPurgeableAndAnonymous(task_t task, uint64_t &purgeable,
                                     uint64_t &anonymous) {
#if defined(TASK_VM_INFO) && TASK_VM_INFO >= 22

  kern_return_t kr;
  mach_msg_type_number_t info_count;
  task_vm_info_data_t vm_info;

  info_count = TASK_VM_INFO_COUNT;
  kr = task_info(task, TASK_VM_INFO_PURGEABLE, (task_info_t)&vm_info,
                 &info_count);
  if (kr == KERN_SUCCESS) {
    purgeable = vm_info.purgeable_volatile_resident;
    anonymous =
        vm_info.internal + vm_info.compressed - vm_info.purgeable_volatile_pmap;
  }

#endif
}
Copy the code
phys_footprint = (internal - alternate_accounting) + (internal_compressed - alternate_accounting_compressed) + iokit_mapped + purgeable_nonvolatile + purgeable_nonvolatile_compressed + page_table
Copy the code

The GetProfileData function is executed when RNBRemote receives qGetProfileData, which LLDB can send.

Other useful uses

frame

Frame Info can view the current line count and source file.

Control program flow

Thread Return NO causes the current function to immediately return a forged return value.

Observe changes in instance variables

See when the _layer of UIView has been overridden.

Find the relative position of the _layer variable on the object
p (ptrdiff_t)ivar_getOffset((struct Ivar *)class_getInstanceVariable([MyView class], "_layer"))
# ($myView + 8) is the memory address to be written to
watchpoint set expression -- (int *)($myView + 8)
Copy the code

This is true of wivar $myView _layer in Chisel.

List the libraries used

image list -o -f
Copy the code

View object reference counts

CFGetRetainCount((__bridge CFTypeDef)obj)
[obj retainCount]
Copy the code

Real machine simulates slow motion painting

Expr -- [[UIApplication sharedApplication] keyWindow].layer.speed = 0.1Copy the code

Image command combination

Find the code location corresponding to the stack address.

image lookup --address 0x0000000106d71a12
Copy the code

Problems with unknown types or type mismatches

p NSLog(@"% @",[self.view viewWithTag:1001]) 
# error: 'NSLog' has unknown return type; cast the call to its declared return type 
# error: 1 errors parsing expression
Copy the code

If we find a similar error with unknown type using the LLDB command (common with ID types, such as a value in NSArray), then we must explicitly declare the type. For example, the command above, we have to modify it like this.

p (void)NSLog(@"% @",[self.view  viewWithTag:1001])
Copy the code

Use (CGRect)[self.view frame] instead of Po self.view.frame

chisel

Chisel can’t be used

error: module importing failed: Missing parentheses in call to 'print'. 
Did you mean print('Whoops! You are missing the <' + arg.argName + '> argument.')? (fblldb.py, line 98)
Copy the code

Solutions:

Xcode does not support Python 2.x, so use the latest Chisel and replace the brew installation directory /usr/localIn the Cellar/chisel, version 1.8.1 / libexec file.Copy the code

Common command

The command usage role
pviews pviews View the View hierarchy
pvc pvc Check the VC hierarchy
presponder presponder 0x7fce735209e0 Get response link
pclass pclass 0x7fce735209e0 View the inheritance relationship of a class
pmethods pmethods 0x7fce735209e0 View all the methods of the class
pinternals pinternals 0x7fce735209e0 View the member variables of the class
fvc,fv fvc RootViewController Gets a list of instances of the class
taplog taplog Breakpoints can handle views that respond to events at a time,

Without having to find the corresponding code to break the point
flicker flicker 0x7ffc03438290 Causes the current View to flash once
vs vs 0x7ffc03438290 View the current level of the layer, one level up, one level down
visualize visualize 0x7fce735209e0 Preview images, colors, views, etc
pactions pactions 0x7fce735209e0 View the button interface and click events
pblock pblock 0x1140c7060 Check the block
show,hide show 0x7fce735209e0 Show, hide View
mask,unmask mask 0x7fce735209e0 Find out where the view is
border/unborder border 0x7fce735209e0 Find out where the view is
caflush caflush Force core animation refresh, redraw UI interface.

Flush the render server (equivalent to a “repaint” if no animations are in-flight).
bmessage bmessage -[MyViewController viewWillAppear:] Add a symbolic breakpoint to a method without worrying about which class implements the method.

Set a symbolic breakpoint on the method of a class or the method of an instance

without worrying which class in the hierarchy actually implements the method.

Will break the point in its parent’s viewWillAppear: method and add the condition :[self isKindOfClass:[MyViewController class]]
wivar wivar $myView _layer Set a watchpoint on an instance variable of an object

Custom commands

Process:

Lldbinit -> load the py file -> run the __lldb_init_module -> add the custom commandCopy the code

Create the ~ /.lldbinit file

command script import /usr/local/ Cellar/chisel, version 1.8.1 / libexec/FBLLDB pyCopy the code

Write command

#! /usr/bin/python
# Example file with custom commands, located at /magical/commands/example.py

import lldb
import fblldbbase as fb

def lldbcommands(a):
  return [ PrintKeyWindowLevel() ]
  
class PrintKeyWindowLevel(fb.FBCommand):
  def name(self):
    return 'pkeywinlevel'
    
  def description(self):
    return 'An incredibly contrived command that prints the window level of the key window.'
    
  def run(self, arguments, options):
    # It's a good habit to explicitly cast the type of all return
    # values and arguments. LLDB can't always find them on its own.
    # lldb.debugger.HandleCommand('p (CGFloat)[(id)[(id)[UIApplication sharedApplication] keyWindow] windowLevel]')
    lldb.debugger.HandleCommand('po UIApplication.shared.keyWindow? .rootViewController! ')
Copy the code

Import the command into Chisel

Modify the ~ /. Lldbinit file

command script import /usr/local/ Cellar/chisel, version 1.8.1 / libexec/FBLLDB py script FBLLDB. LoadCommandsInDirectory ('/ usr/local/Cellar/chisel, version 1.8.1 / libexec/commands/')
Copy the code

Development Workflow

Developing commands, whether for local use or contributing to Chisel directly, both follow the same workflow. 
Create a command as described in the Custom Commands section and then

Start LLDB
Reach a breakpoint (or simply pause execution via the pause button in Xcode's debug bar or process interrupt if attached directly) Execute command source ~/.lldbinit in LLDB to source the commands Run the command you are working on Modify the command Optionally run script reload(modulename) Repeat steps 3-6  until the command becomes a source of happinessCopy the code

Key: Run command source ~/. Lldbinit in LLDB to dynamically load commands.

All LLDB commands

(lldb) help
Debugger commands:
  apropos           -- List debugger commands related to a word or subject.
  breakpoint        -- Commands for operating on breakpoints (see 'help b' for
                       shorthand.)
  bugreport         -- Commands for creating domain-specific bug reports.
  command           -- Commands for managing custom LLDB commands.
  disassemble       -- Disassemble specified instructions in the current
                       target.  Defaults to the current function for the
                       current thread and stack frame.
  expression        -- Evaluate an expression on the current thread.  Displays
                       any returned value with LLDB's default formatting. frame -- Commands for selecting and examing the current thread's
                       stack frames.
  gdb-remote        -- Connect to a process via remote GDB server.  If no host
                       is specifed, localhost is assumed.
  gui               -- Switch into the curses based GUI mode.
  help              -- Show a list of all debugger commands, or give details
                       about a specific command.
  kdp-remote        -- Connect to a process via remote KDP server.  If no UDP
                       port is specified, port 41139 is assumed.
  language          -- Commands specific to a source language.
  log               -- Commands controlling LLDB internal logging.
  memory            -- Commands for operating on memory in the current target
                       process.
  platform          -- Commands to manage and create platforms.
  plugin            -- Commands for managing LLDB plugins.
  process           -- Commands for interacting with processes on the current
                       platform.
  quit              -- Quit the LLDB debugger.
  register          -- Commands to access registers for the current thread and
                       stack frame.
  reproducer        -- Commands controlling LLDB reproducers.
  script            -- Invoke the script interpreter with provided code and
                       display any results.  Start the interactive interpreter
                       if no code is supplied.
  settings          -- Commands for managing LLDB settings.
  source            -- Commands for examining source code described by debug
                       information for the current target process.
  statistics        -- Print statistics about a debugging session
  target            -- Commands for operating on debugger targets.
  thread            -- Commands for operating on one or more threads in the
                       current process.
  type              -- Commands for operating on the type system.
  version           -- Show the LLDB debugger version.
  watchpoint        -- Commands for operating on watchpoints.
Current command abbreviations (type 'help command alias' for more info):
  add-dsym  -- Add a debug symbol file to one of the target's current modules by specifying a path to a debug symbols file, or using the options to specify a module to download symbols for. attach -- Attach to process by ID or name. b -- Set a breakpoint using one of several shorthand formats. bt -- Show the current thread's call stack.  Any numeric argument
               displays at most that many frames.  The argument 'all' displays
               all threads.
  c         -- Continue execution of all threads in the current process.
  call      -- Evaluate an expression on the current thread.  Displays any
               returned value with LLDB's default formatting. continue -- Continue execution of all threads in the current process. detach -- Detach from the current target process. di -- Disassemble specified instructions in the current target. Defaults to the current function  for the current thread and stack frame. dis -- Disassemble specified instructions in the current target. Defaults to the current function for the current thread and stack frame. display -- Evaluate an expression at every stop (see 'help target
               stop-hook'.) down -- Select a newer stack frame. Defaults to moving one frame, a numeric argument can specify an arbitrary number. env -- Shorthand for viewing and setting environment variables. exit  -- Quit the LLDB debugger. f -- Select the current stack frame by index from within the current thread (see 'thread backtrace'.)
  file      -- Create a target using the argument as the main executable.
  finish    -- Finish executing the current stack frame and stop after
               returning.  Defaults to current thread unless specified.
  image     -- Commands for accessing information for one or more target
               modules.
  j         -- Set the program counter to a new address.
  jump      -- Set the program counter to a new address.
  kill      -- Terminate the current target process.
  l         -- List relevant source code using one of several shorthand formats.
  list      -- List relevant source code using one of several shorthand formats.
  n         -- Source level single step, stepping over calls.  Defaults to
               current thread unless specified.
  next      -- Source level single step, stepping over calls.  Defaults to
               current thread unless specified.
  nexti     -- Instruction level single step, stepping over calls.  Defaults to
               current thread unless specified.
  ni        -- Instruction level single step, stepping over calls.  Defaults to
               current thread unless specified.
  p         -- Evaluate an expression on the current thread.  Displays any
               returned value with LLDB's default formatting.
  parray    -- Evaluate an expression on the current thread.  Displays any
               returned value with LLDB's default formatting. po -- Evaluate an expression on the current thread. Displays any returned value with formatting controlled by the type's author.
  poarray   -- Evaluate an expression on the current thread.  Displays any
               returned value with LLDB's default formatting. print -- Evaluate an expression on the current thread. Displays any returned value with LLDB's default formatting.
  q         -- Quit the LLDB debugger.
  r         -- Launch the executable in the debugger.
  rbreak    -- Sets a breakpoint or set of breakpoints in the executable.
  re        -- Commands to access registers for the current thread and stack
               frame.
  repl      -- Evaluate an expression on the current thread.  Displays any
               returned value with LLDB's default formatting.
  run       -- Launch the executable in the debugger.
  s         -- Source level single step, stepping into calls.  Defaults to
               current thread unless specified.
  si        -- Instruction level single step, stepping into calls.  Defaults to
               current thread unless specified.
  sif       -- Step through the current block, stopping if you step directly
               into a function whose name matches the TargetFunctionName.
  step      -- Source level single step, stepping into calls.  Defaults to
               current thread unless specified.
  stepi     -- Instruction level single step, stepping into calls.  Defaults to
               current thread unless specified.
  t         -- Change the currently selected thread.
  tbreak    -- Set a one-shot breakpoint using one of several shorthand formats.
  undisplay -- Stop displaying expression at every stop (specified by stop-hook
               index.)
  up        -- Select an older stack frame.  Defaults to moving one frame, a
               numeric argument can specify an arbitrary number.
  v         -- Show variables for the current stack frame. Defaults to all
               arguments and local variables in scope. Names of argument,
               local, file static and file global variables can be specified.
               Children of aggregate variables can be specified such as
               'var->child.x'. The -> and [] operators in 'frame variable' do not invoke operator overloads if they exist, but directly access the specified element. If you want to trigger operator overloads use the expression command to print  the variable instead. It is worth noting that except for overloaded operators, when printing local variables 'expr local_var' and 'frame var
               local_var' produce the same results. However, 'frame variable' is more efficient, since it uses debug information and memory reads directly, rather than parsing and evaluating an expression, which may even involve JITing and running code in the target program. var -- Show variables for the current stack frame.  Defaults to all arguments and local variables in scope. Names of argument, local, file static and file global variables can be specified. Children of aggregate variables can be specified such as 'var->child.x'. The -> and [] operators in 'frame variable' do not invoke operator overloads if they exist, but directly access the specified element. If you want to trigger operator overloads use the expression command to print  the variable instead. It is worth noting that except for overloaded operators, when printing local variables 'expr local_var' and 'frame var
               local_var' produce the same results. However, 'frame variable' is more efficient, since it uses debug information and memory reads directly, rather than parsing and evaluating an expression, which may even involve JITing and running code in the target program. vo -- Show variables for the current stack frame. Defaults to all arguments and local variables in scope. Names of argument, local, file static and file global variables can be specified. Children of aggregate variables can be specified such as 'var->child.x'. The -> and [] operators in 'frame variable' do not invoke operator overloads if they exist, but directly access the specified element. If you want to trigger operator overloads use the expression command to print  the variable instead. It is worth noting that except for overloaded operators, when printing local variables 'expr local_var' and 'frame var
               local_var' produce the same results. However, 'frame variable' is more efficient, since it uses debug information and memory reads directly, rather than parsing and evaluating an expression, which may even involve JITing and running code in the target program. x -- Read from the memory of the current target process. Current user-defined commands: alamborder -- Put a border around views with an ambiguous layout alamunborder -- Removes the border around views with an  ambiguous layout bdisable -- Disable a set of breakpoints for a regular expression benable -- Enable a set of breakpoints for a regular expression binside -- Set a breakpoint for a relative address within the framework/library that's currently running. This does the
                   work of finding the offset for the framework/library and
                   sliding your address accordingly.
  bmessage      -- Set a breakpoint for a selector on a class, even if the
                   class itself doesn't override that selector. It walks the hierarchy until it finds a class that does implement the selector and sets a conditional breakpoint there. border -- Draws a border around 
      
       . Color and width can be optionally provided.  Additionally depth can be provided in order to recursively border subviews. caflush -- Force Core Animation to flush. This will '
      repaint' the UI but also may mess with ongoing animations. dcomponents -- Set debugging options for components. dismiss -- Dismiss a presented view controller. fa11y -- Find the views whose accessibility labels match labelRegex and puts the address of the first result on the clipboard. findinstances -- Find instances of specified ObjC classes. flicker -- Quickly show and hide a view to quickly help visualize where it is. fv -- Find the views whose class names match classNameRegex and puts the address of first on the clipboard. fvc -- Find the view controllers whose class names match classNameRegex and puts the address of first on the clipboard. heapfrom -- Show all nested heap pointers contained within a given variable. hide -- Hide a view or layer. mask -- Add a transparent rectangle to the window to reveal a possibly obscured or hidden view or layer'S Bounds mWarning -- Simulate a memory warning pa11y -- Print accessibility Labels of all viewsin hierarchy of
                   <aView>
  pa11yi        -- Print accessibility identifiers of all views in hierarchy of
                   <aView>
  pactions      -- Print the actions and targets of a control.
  paltrace      -- Print the Auto Layout trace for the given view. Defaults to
                   the key window.
  panim         -- Prints if the code is currently execution with a UIView
                   animation block.
  pbcopy        -- Print object and copy output to clipboard
  pblock        -- Print the block`s implementation address and signature
  pbundlepath   -- Print applicationPcells -- Print the visible cells of the highest table view in the hierarchy. Pcomponents -- Print the inheritance starting from an instance of any class. Pcomponents -- Print a recursive description of components found starting from 
      
       . pcurl -- Print the NSURLRequest (HTTP) as curl command.  pdata -- Print the contents of NSData object as string. pdocspath -- Print application'
      s 'Documents'Pinternals -- Show the internals of an object by dereferencing it as a pointer. pinvocation -- Print the stack frame, receiver, and arguments of the current invocation. It will fail toprint all arguments if
                   any arguments are variadic (varargs).
  pivar         -- Print the value of an object'named instance variable. pjson -- Print JSON representation of NSDictionary or NSArray object Print out the value of the key path expression using -valueForKeyPath: pmethods -- Print the class and instance methods of a class. poobjc -- Print the expression result, with the expression run in an ObjC++ context. (Shortcut for "expression -O -l ObjC++ -- " ) pproperties -- Print the properties of an instance or Class present -- Present a view controller. presponder -- Print the responder chain starting from a specific responder. psjson -- Print JSON representation of Swift Dictionary or Swift Array object ptv --  Print the highest table view in the hierarchy. pvc -- Print the recursion description of 
      
       . pviews -- Print the recursion description of 
       
        . rcomponents -- Synchronously reflow and update all components. sequence -- Run commands in sequence, stopping on any error. setinput -- Input text into text field or text view that is first responder. settext -- Set text on text on a view by accessibility id. show -- Show a view or layer. slowanim -- Slows down animations. Works on the iOS  Simulator and a device. taplog -- Log tapped view to the console. uikit -- Imports the UIKit module to get access to the types while in lldb. unborder -- Removes border around 
        
         . unmask -- Remove mask from a view or layer unslowanim -- Turn off slow animations. visualize -- Open a UIImage, CGImageRef, UIView, or CALayer in Preview.app on your Mac. vs -- Interactively search for a view by walking the hierarchy. wivar -- Set a watchpoint for an object'
        
       
      s instance variable.
  xdebug        -- Print debug description the XCUIElement in human readable
                   format.
  xnoid         -- Print XCUIElement objects with label but without identifier.
  xobject       -- Print XCUIElement details.
  xtree         -- Print XCUIElement subtree.
  zzz           -- Executes specified lldb command after delay.
For more information on any command.type 'help <command-name>'.
Copy the code

The resources

  • Dancing with the debugger – the waltz of LLDB
  • LLDB advanced debugging +Cycript
  • chisel
  • Chisel-lldb command plug-in to make debugging easier