Introduction to the

LLDB is short for Low Lever Debugger, which should be called low-level Debugger in Chinese. It is the Debugger component of LLVM project. LLVM is a compiler framework system, written in C++, that optimizes compile-time, link-time, run-time, and idle-time of programs written in any programming language. Open to developers and compatible with existing scripts. If you know Swift and its authors, then you are familiar with Dr. Chris Lattner, so why mention him here? Yes, LLVM was originally developed by Dr. Chris Lattner.

LLDB supports debugging of programs written in C, objective-C, and C++. The Swift community maintains a release that adds support for the language. Built into Xcode by default, LLDB provides a broad set of commands designed to be compatible with older versions of GDB commands. In addition to using the standard configuration, you can easily customize the LLDB command to suit your needs. You can view all Debugger commands by typing Help in Xcode’s controller after it has entered LLDB debug mode, or herewebsite

Breakpoint commands

Breakpoint command. In the normal development process with Xcode, we usually set the breakpoint by clicking on the number of lines of code on the interface. You can also use the LLDB command to set breakpoints.

Set a breakpoint by name

Set C function name breakpoint

In the touchedBegan method, we set a breakpoint from the interface, enter the LLDB debug mode, and then enter the following command to set the function breakpoint:

breakpoint set -n "test1"-n is an abbreviation of –name, and then click continue or enter the LLDB command c to continue. You can see that many of the debugging functions that Xcode integrates come from LLDB. The next step in debugging is to enter n or s in LLDB. N will not enter when it encounters a subfunction, and s will enter when it encounters a subfunction.

Set the OC method name breakpoint

Set up a simple interface as shown in the pictureThen pause the program and type the following command on the console:

breakpoint set -n "-[ViewController save:]" -n "-[ViewController pause:]" -n "-[ViewController continue:]"

This sets a set of breakpoints, which have three breakpoints. You can use the following command to view all current breakpoints:

breakpoint list

Disable and enable breakpoints

To disable breakpoints, the following number isbreakpoint listYou can disable one group at the same time or one of the groups individuallyBreakpoint disable number Enable the breakpointBreakpoint enalbe number

Remove breakpoints

Remove breakpointsBreakpoint delete numberOne small detail here is that you can’t delete a set of breakpoints, you can only delete a set of breakpoints. If delete is followed by a breakpoint in a group, it is equivalent to disabling the breakpoint. If you do not enter the number, it is equivalent to deleting all breakpoints

Set a breakpoint based on the method

The breakpoints we just set are for specific methods of a class. We can also set breakpoints for methods independent of the class:

breakpoint set --selector touchesBegan:withEvent: As you can see, 98 breakpoints are set, but there is no obvious call to this method in our project. In fact, this method is used in the system library UIKit. LLDB is broken into the system library, so it can be usedbreakpoint listView all 98 breakpoints

If you don’t want to break to the system library like this, you can specify a file to set a method breakpoint, so let’s put a ‘touchesBegan’ method in the ViewController.

breakpoint set --file ViewController.m --selector touchesBegan:withEvent:

Set breakpoints for regular match

For an introduction to the -r parameter, enter help breakpoint set

Set the breakpoint by function name, evaluating a regular-expression to find the function name(s).
Copy the code

breakpoint set -r save:This will look for all matching methods based on the arguments after -rWe only have a save: method in the ViewController. Why do we show 11 breakpointsbreakpoint listTo viewAs you can see, except for the first one, which is the break point in our project, none of the other break points are in our project. It’s all in the system library.

Similarly, we can use the command breakpoint set -r save: –file viewController.m with the specified file

Breakpoint execution command

Breakpoint Command Add numberYou can add some commands to the breakpoint, so that when the breakpoint comes, you can automatically execute these commands, so that we can save some operations

Breakpoint set -r save: –file viewcontroller. m can be abbreviated to b-r save: -f viewController. m Breakpoint list Can be abbreviated to break Li Breakpoint disable 8.1 can be abbreviated to BRE dis 8.1 breakpoint enable 8.1 can be abbreviated to BRE en 8.1 Anyway, you can go to a variety of attempts, a little more than a letter may be able to work, more random, compared to the ordinary command wrong a character is not still pretty cow force.

Expression command

What do we usually do most in the LLDB console?poPrint an object, so what does this Po mean? You can run the following command on the terminal:help po In fact, one of the most commonly used Po commands is the expression -o command. Some people like to use itpPrint, sopWhat is it? Inputhelp pP is short for expression directivehelp expressionYou can see the meaning of -o, which is the description method of the specified language, so we usually use itpoOC objects, that is, execute the description method of the OC object.

throughhelp poWe know is performing expression in the main thread, so we can have a try in LLDB modify some of the common properties, such as the self. The backgroundColor, first came to the touchesBegan: breakpoints, in LLDB enter the following commands

p self.view.backgroundColor = [UIColor redColor];

The code was executed, but there was a confusing error, and there was no effect after the breakpoint was passed. But this line of code, if you run it in your program, is going to be fine, and if you look at the UIView header file, you can also see that it makes sure that it has this backgroundColor property. As for why I can’t find any answer after searching the Internet for half a day, I feel that it may be a bug of LLDB? This code is not valid, but we can try to change it in other ways, such as:

p [self.view setValue:[UIColor blueColor] forKey:@"backgroundColor"] KVC is still awesome, there’s another way, we know that what UIView really displays is its layer, so change the layer:

p self.view.layer.backgroundColor = [UIColor yellowColor].CGColor

As an example, we create a persons array, store a list of persons, and dynamically add a Person using LLDB expression.As you can see, LLDB’s expression command can be followed by multiple lines of code, which is handy for dynamic debugging

The bt command

Enter the LLDB inputhelp btAs you can see, BT means to look at the current thread call stack

Create the following four methods and give the demo4 method a breakpoint, then click on the screen to enter the breakpointThe inputbtYou can see the call stack for the current methodThe inputupYou can look at the last method that was called, and you can see even the source code, and of course you can’t see the source code in reverse, you can only see the assembly code, typedownYou can return to the next methodIf up and down step by step are too slow, you can also use them directlyFrame the select numberDirectly in placeWhy do you flip the stack frame up and down like this? Of course, to see some information about the current stack, such as the variables used by the current stackframe variableOC has two hidden arguments, self and _cmd. Event is the display argument for demo1, if not knownframe variableCan also be viewed through the LLDB help documentationhelp frame variable

Thread the return command

When we debug to a certain frame, if you do not want to program after the code, can usethread returnThe thread returns the value. Note that the value returned after return is based on the actual situation. For example:If not usedthread return NOWhen the breakpoint came to isRuning, we forced the return of NO, so we changed the execution flow of the program during debugging

None of the above methods work in reverse… Because we don’t get symbols for reverse projects

So how should reverse play LLDB? Memory breakpoint

Watchpoint Memory breakpoint

Memory breakpoints, not only for methods, but also for variables

Watchpoint Sets a memory breakpoint based on the variable name

watchpoint set variable p1->_nameAs shown in the figure, the Person class has a name property, but when we set the memory breakpoint, the property is not available, because the property is essentially a member variable of getters and setters underlined, so we need to use itp1->_nameWhen p1. Name is assigned, the breakpoint is reached. Name = LLDB Watchpoint 1 hit Then the old value and the new value are displayed

Watchpoint Sets a memory breakpoint based on the memory address

Watchpoint Set Expression Indicates the addressAgain, after we instantiate p1, its address in memory is determined, so the address of its member variable is also determined, so we can take the memory address of P1. Name, and set a breakpoint based on its memory address. Every time the program makes a change to P1.name, it comes to a breakpoint, and you can see that the breakpoint below comes twice, once in viewDidload, and once in touchesBegan

Target stop – hook command

This command is similar to the breakpoint execution command for breakpoint, except the breakpoint execution command requires a breakpoint to be specified, and the command is global. Whenever a breakpoint occurs, the following command is executedThrough the log can see stop – hook command can add, delte, disable and enable, list, specifically how to use each command, you can continue to use the help command to view, add, for example, help documents are detailedLet’s add one globally hereframe variableCommand, and then go to the break point to tryYou can see that the breakpoint comes and it automatically executesframe variableInstruction to print parameter variablesThere is also a shortcut to remove the stop-hook directiveUndisplay numberCompared with theTarget stop-hook Delete numberIt’s a lot shorter

. Lldbinit file

You can configure frequently used commands to.lldbinit files so that you don’t have to add them every time. This file is usually placed in the user directory. The dot at the beginning of the file is a hidden file. If you don’t have one, you can create one yourself. Here we add such a commandRun the project again until you reach the breakpoint to see the associated print

Image instruction

A Mach-o file is an image. A mach-o file is an image. Our APP is also a mirror. Let’s start by looking at the information about a class in our APP

image look up -t name

image list

The inputhelp image listView the description of the commandAs you can see, image list means to list the current executable and the shared library images that it depends on. This command is often used in reverse to get the location of our APP in memory.

Memory address breakpoint in reverse

Here we are calling the Demo4 method in the touchesBegan: methodNow we open our APP’s Mach-o file with hopper, assuming we’re interested in our demo4 method and want to make a break point.The hopper address is just the offset of this method from the first address of our APP plus the virtual address, so to get the actual memory address of this method in our phone, we need to add the memory address of our APP’s first address. throughimage listThe first one is the initial address of our APP.The virtual address can be seen in the __PAGEZERO section of our Mach-o fileSo the location of this method in our phone’s memory is:

0x102964000 + 0x100005b8c - 0x100000000 = 0x102969B8C

We enter LLDB mode and enter the following memory address breakpointbreakpoint set --address 0x102969B8C The breakpoint is set, and then we push out LLDB mode, click on the screen, and the breakpoint is there

ASLR is mentioned here as a computer security technology to prevent memory corruption vulnerability from being exploited. It means that the location of our APP is not fixed when it is loaded into the real memory of the mobile phone every time, so the first address of our APP we can see through the Image List after the APP is running is random.

The contents of the Mach-o file of our APP are fixed relative to the initial address of the Mach-O file. The initial address is determined after the APP is loaded into memory, so the contents of the Mach-O file, such as method implementation, function implementation, constant data, etc. can be found in memory…

We can define a global variable in the viewController.m file and see if we can find it in the Mach-o file. When you define a global variable and run it, print its address and the first address of the current APP. Its address minus the first address of the APP is the offset from our APP’s Mach-o file.0x102b959f0 - 0x102b8c000 = 0x99F0

Using MachOView to look at our APP’s Mach-o file, find the address 0x99F0 and see if the value of a is 0x123456678Some of you may be curious, how does this look like this? In fact, this is because of the way the machines access data. Some machines are in big-endian mode, while some machines are in small-endian modeBig and small mode

We can also see that our global variables are stored in the __DATA, __DATA section.