A: breakPoint

Breakpoint debugging is one of the most common methods used by project developers, but we usually point breakpoints on a line of code. Let’s look at other ways to set breakpoints.

To set a breakpoint: breakpoint set -n

Set breakpoints for functions

First we define a function

void test1(){
    NSLog(@"3");
}
Copy the code

Then write the following code in your controller

Breakpoint set -n test1 breakpoint set -n test1

(lldb) breakpoint set -n test1 Breakpoint 2: Where = 001--LLDB debug 'test1 + 16 at viewController.m :30:5, address = 0x0000000104a31CC8 (LLDB)Copy the code

The output statement above means:

The second breakpoint is at the test1 function on line 30 of the viewController file of the MachO file named LLDB

Above, Breakpoint 2 represents the second Breakpoint set. If you set five breakpoints before the project runs, the sixth Breakpoint will appear when you set breakpoints through Breakpoint

Set a breakpoint for the method

How to set breakpoints for OC methods?

First we create three buttons on the page and implement trigger methods accordingly

- (IBAction)save:(id)sender {NSLog(@" save! ); } - (IBAction)pauseGame:(id)sender {NSLog(@" pause "); } - (IBAction)continueGame:(id)sender {NSLog(@" continue "); }Copy the code

Run the project, and then click the button below. This button means to pause the project, and then we can set the breakpoint with the command

The command to set a breakpoint for the OC method is

(lldb) breakpoint set -n "-[ViewController save:]" -n "-[ViewController pauseGame:]" -n "-[ViewController continueGame:]"
Breakpoint 1: 3 locations.
Copy the code

View the breakpoint list: Breakpoint List

The above shows setting a breakpoint, but a breakpoint has three locations. Let’s look at the breakpoint list

(lldb) breakpoint list Current breakpoints: 1: names = {'-[ViewController save:]', '-[ViewController pauseGame:]', '-[ViewController continueGame:]'}, locations = 3, Resolved = 3, hit count = 0 Where = 001--LLDB debug '-[ViewController save:] + 43 at viewController. m:33:5, address = 0x000000010b4e0CEb, resolved, Hit count = 0 Where = 1--LLDB debug '-[ViewController pauseGame:] + 43 at ViewController.m:36:5, address = 0x000000010b4e0d3b, resolved, Hit count = 0 Where = 001--LLDB debug '-[continueGame:] + 43 at viewController.m :39:5, address = 0x000000010b4e0d8b, resolved, hit count = 0 (lldb)Copy the code

We found that the breakpoint column is clear in three places, click the button to test that there are indeed breakpoints

Disable, enable, and delete breakpoints

When a breakpoint breaks, the c command continues meaning skip the breakpoint

(LLDB) C Process 21081 dump 2020-11-11 20:45:41.211892+0800 001--LLDB debug [21081:2419390] save!Copy the code

Disable: Breakpoint disable

Breakpoint disable + Breakpoint number, meaning that breakpoint is disabled

For example, we disable the first breakpoint and then look at the breakpoint list:

(lldb) breakpoint disable 1 1 breakpoints disabled. (lldb) breakpoint list Current breakpoints: 1: names = {'-[ViewController save:]', '-[ViewController pauseGame:]', '-[ViewController continueGame:]'}, Locations = 3 Options: Disabled Where = 0 --LLDB debug '-[ViewController save:] + 43 at viewController.m :33:5, address = 0x000000010b4e0ceb, unresolved, Hit count = 2 Where = 001--LLDB debug '-[ViewController pauseGame:] + 43 at ViewController.m:36:5, address = 0x000000010b4e0d3b, Unresolved, hit count = 1 unresolved, hit count = 1 Where = 001--LLDB debug '-[continueGame:] + 43 at viewController.m :39:5, address = 0x000000010b4e0d8b, unresolved, hit count = 0 (lldb)Copy the code

If you click on the button, the breakpoint will not be used

Enable: breakpoint enable

Breakpoint enable + Breakpoint number means enabling breakpoints

(lldb) breakpoint enable 1 1 breakpoints enabled. (lldb) breakpoint list Current breakpoints: 1: names = {'-[ViewController save:]', '-[ViewController pauseGame:]', '-[ViewController continueGame:]'}, locations = 3, Resolved = 3, hit count = 3 Where = 001--LLDB debug '-[ViewController save:] + 43 at viewController. m:33:5, address = 0x000000010b4e0CEb, resolved, Hit count = 2 Where = 1--LLDB debug '-[ViewController pauseGame:] + 43 at ViewController.m:36:5, address = 0x000000010b4e0d3b, resolved, Hit count = 1 Where = 001--LLDB debug '-[continueGame:] + 43 at viewController.m :39:5, address = 0x000000010b4e0d8b, resolved, hit count = 0Copy the code

We found that when we enabled the breakpoint, disable disappeared behind the breakpoint, and when we clicked the button again, the breakpoint would break

Let’s disable one of the breakpoints again

(LLDB) BreakPoint Disable 1.1 1 Breakpoints Disabled. (LLDB) Breakpoint list Current Breakpoints: 1: names = {'-[ViewController save:]', '-[ViewController pauseGame:]', '-[ViewController continueGame:]'}, locations = 3, Resolved = 2, hit count = 3 Where = 0 --LLDB debug '-[ViewController save:] + 43 at viewController.m :33:5, address = 0x000000010b4e0ceb, unresolved, Options: Disabled 1.2: Where = 1--LLDB debug '-[ViewController pauseGame:] + 43 at ViewController.m:36:5, address = 0x000000010b4e0d3b, resolved, Hit count = 1 Where = 001--LLDB debug '-[continueGame:] + 43 at viewController.m :39:5, address = 0x000000010b4e0d8b, resolved, hit count = 0Copy the code

We found that only the 1.1 position had disable after it, and clicking on the button did not break except the first button

Delete: breakpoint delete

Let’s add a couple of breakpoints to the project,

(lldb) breakpoint list Current breakpoints: 1: names = {'-[ViewController save:]', '-[ViewController pauseGame:]', '-[ViewController continueGame:]'}, locations = 3, Resolved = 2, hit count = 3 Where = 001--LLDB debug '-[ViewController save:] + 43 at viewController. m:33:5, address = 0x000000010b4e0CEb, resolved, Hit count = 2 Where = 1--LLDB debug '-[ViewController pauseGame:] + 43 at ViewController.m:36:5, address = 0x000000010b4e0d3b, resolved, Hit count = 1 Where = 001--LLDB debug '-[continueGame:] + 43 at viewController.m :39:5, address = 0x000000010b4e0d8b, resolved, hit count = 0 2: File = '/Volumes/ iOS Video /iOS Defense Team 2/20191023- Application Security - Talk 9- LLDB/009--LLDB/ code /001--LLDB debugging /001--LLDB Debugging/viewController.m ', Locations = 1, resolved = 1, Hit count = 0 Where = 001--LLDB debug '-[ViewController eatWithObject:] + 46 at ViewController.m:43:26, address = 0x000000010b4e0dde, resolved, hit count = 0Copy the code

Then delete the second breakpoint with the command:

(lldb) breakpoint delete 2 1 breakpoints deleted; 0 breakpoint locations disabled. (lldb) breakpoint list Current breakpoints: 1: names = {'-[ViewController save:]', '-[ViewController pauseGame:]', '-[ViewController continueGame:]'}, locations = 3, Resolved = 2, hit count = 3 Where = 001--LLDB debug '-[ViewController save:] + 43 at viewController. m:33:5, address = 0x000000010b4e0CEb, resolved, Hit count = 2 Where = 1--LLDB debug '-[ViewController pauseGame:] + 43 at ViewController.m:36:5, address = 0x000000010b4e0d3b, resolved, Hit count = 1 Where = 001--LLDB debug '-[continueGame:] + 43 at viewController.m :39:5, address = 0x000000010b4e0d8b, resolved, hit count = 0 (lldb)Copy the code

We found that the second breakpoint was deleted. What if we wanted to delete the 1.1 breakpoint?

(LLDB) BreakPoint delete 1.1 0 Breakpoints deleted; 1 breakpoint locations disabled. (lldb) breakpoint list Current breakpoints: 1: names = {'-[ViewController save:]', '-[ViewController pauseGame:]', '-[ViewController continueGame:]'}, locations = 3, Resolved = 2, hit count = 3 Where = 0 --LLDB debug '-[ViewController save:] + 43 at viewController.m :33:5, address = 0x000000010b4e0ceb, unresolved, Options: Disabled 1.2: Where = 1--LLDB debug '-[ViewController pauseGame:] + 43 at ViewController.m:36:5, address = 0x000000010b4e0d3b, resolved, Hit count = 1 Where = 001--LLDB debug '-[continueGame:] + 43 at viewController.m :39:5, address = 0x000000010b4e0d8b, resolved, hit count = 0 (lldb)Copy the code

A breakpoint cannot be deleted at any location of a breakpoint, but can only be disabled, even if a breakpoint has only one location

In addition, breakpoints added during the project will be numbered, even if they are removed. Breakpoints added later will be numbered, but will not overwrite old breakpoints

Other instructions for breakpoints: Help breakpoint

(lldb) help breakpoint Commands for operating on breakpoints (see 'help b' for shorthand.) Syntax: breakpoint <subcommand> [<command-options>] The following subcommands are supported: clear -- Delete or disable breakpoints matching the specified source file and line. command -- Commands for adding, removing and listing LLDB commands executed when a breakpoint is hit. delete -- Delete the specified breakpoint(s). If no breakpoints are specified, delete them all. disable -- Disable the specified breakpoint(s) without deleting them. If none are specified, disable all breakpoints. enable -- Enable the specified disabled breakpoint(s). If no breakpoints are specified, enable all of them. list -- List some or all breakpoints at configurable levels of detail. modify -- Modify the options on a breakpoint or set of breakpoints in the executable. If no breakpoint is specified, acts on the last created breakpoint. With the exception of -e, -d and -i, passing an empty argument clears the modification. name -- Commands to manage name tags for breakpoints read -- Read and  set the breakpoints previously saved to a file with "breakpoint write". set -- Sets a breakpoint or set of breakpoints in the executable. write -- Write the breakpoints listed to a file that can be read in with "breakpoint read". If given no arguments, writes all breakpoints. For more help on any particular subcommand, type 'help <command> <subcommand>'. (lldb)Copy the code

Breakpoint by method name :breakpoint set –selector

(lldb) breakpoint set --selector touchesBegan:withEvent:
Breakpoint 7: 97 locations.
(lldb) 
Copy the code

We found 97 locations in total, and that’s because a lot of UIKit system classes have this method in them

We can also specify a file to set breakpoints by method name

(lldb) breakpoint set --file ViewController.m --selector touchesBegan:withEvent: Breakpoint 8: [ViewController began :withEvent:] + 77 at ViewController. M :90:5, address = 0x000000010b4e123d (lldb)Copy the code

Fuzzy set breakpoint: breakpoint set -r + method name

With this command, we can set breakpoints obtrusibly, that is, any method that contains characters in its name will set breakpoints

(lldb) breakpoint set -r Game: Breakpoint 11: 2 locations. (lldb) breakpoint list Current breakpoints: 11: Regex = 'Game:', locations = 2, resolved = 2, hit count = 0 Where = 001--LLDB debug '-[continueGame:] + 43 at viewController.m :39:5, address = 0x000000010b4e0d8b, Resolved, Hit Count = 0 11.2: Where = 1--LLDB debug '-[ViewController pauseGame:] + 43 at ViewController.m:36:5, address = 0x000000010b4e0d3b, resolved, hit count = 0 (lldb)Copy the code

We find Game in the method name of the breakpoint:

Similarly, we can specify a file for fuzzy breakpoint setting

(lldb) breakpoint set --file ViewController.m -r Game:
Breakpoint 12: 2 locations.
(lldb) 
Copy the code

Note that method names are case sensitive

And there’s a shorthand for these breakpoints:

For example, to set a breakpoint:

(lldb) b -f ViewController.m -r Game Breakpoint 17: 2 locations. (lldb) breakpoint list Current breakpoints: 17: Regex = 'Game', locations = 2, resolved = 2, hit count = 0 Where = 001--LLDB debug '-[continueGame:] + 43 at viewController.m :39:5, address = 0x000000010b4e0d8b, Resolved, Hit Count = 0 17.2: Where = 1--LLDB debug '-[ViewController pauseGame:] + 43 at ViewController.m:36:5, address = 0x000000010b4e0d3b, resolved, hit count = 0 (lldb)Copy the code

Shorthand to view breakpoints:

(LLDB) break li Current breakpoints: 17: regex = 'Game', locations = 2, Resolved = 2, hit count = 0 Where = 001--LLDB debug '-[continueGame:] + 43 at viewController.m :39:5, address = 0x000000010b4e0d8b, Resolved, Hit Count = 0 17.2: Where = 1--LLDB debug '-[ViewController pauseGame:] + 43 at ViewController.m:36:5, address = 0x000000010b4e0d3b, resolved, hit count = 0 (lldb)Copy the code

Shortened disable:

(lldb) break dis 17.1
1 breakpoints disabled.
(lldb) 
Copy the code

Shorthand enabled:

(lldb) break en 17.1
1 breakpoints enabled.
(lldb) 
Copy the code

2. Execute statement: P

Execute code instruction: expression + Execute statement

(lldb) expression self.view.subviews
(__NSArrayM *) $0 = 0x0000600000d03630 @"3 elements"
(lldb) 
Copy the code

But in practice, we generally use P instruction to execute:

(lldb) p self.view.subviews
(__NSArrayM *) $1 = 0x0000600000d03630 @"3 elements"
(lldb) 
Copy the code

Let’s see what the P directive is:

(lldb) help p
     Evaluate an expression on the current thread.  Displays any returned value
     with LLDB's default formatting.  Expects 'raw' input (see 'help
     raw-input'.)

Syntax: p <expr>

Command Options Usage:
  p <expr>


'p' is an abbreviation for 'expression --'
(lldb) 
Copy the code

We find that p is actually short for expression

When we want to see the value of a variable, we use the Po command. Let’s see what Po is:

(lldb) help po
     Evaluate an expression on the current thread.  Displays any returned value
     with formatting controlled by the type's author.  Expects 'raw' input (see
     'help raw-input'.)

Syntax: po <expr>

Command Options Usage:
  po <expr>


'po' is an abbreviation for 'expression -O  --'
(lldb) 
Copy the code

Expression is short for expression. We know that expression is an instruction to execute. Let’s see what it is:

We find that -o is the description method for similar objects

P as the execution statement instruction, let’s try it out, stop the program, and then we execute the following instruction:

(lldb) p sender.backgroundColor=[UIColor redColor];
error: <user expression 0>:1:8: property 'backgroundColor' not found on object of type 'UIButton *'
sender.backgroundColor=[UIColor redColor];
       ^
(lldb) 
Copy the code

When we release the breakpoint, we see that the button color has changed

And we can also modify variables, for example we break the following method:

The name is then modified by the P instruction

(LLDB) p name = @"234" (NSTaggedPointerString *) $0 = 0xde7f7b1CE0722058 @"234" 2020-11-11 22:06:31.599465+0800 001--LLDB debug [23841:2488906] Save! 234Copy the code

If name is an object, then we can also modify the properties of the object. This is called memory debugging

For example, we create a mutable array in a method and break it:

We add an element to the array using the command, and then print it, and we find that there is an extra element in the array

(lldb) p [array addObject:@"4"] (lldb) po array <__NSArrayM 0x600000f17c90>( 1, 2, 3, 2020-11-11 22:14:15.499845+0800 001--LLDB debug [24073:2494681] (1, 2, 3, 4)Copy the code

Let’s say the array has objects in it

(lldb) p self.models.lastObject
(Person *) $0 = 0x00006000029c4c20
(lldb) p $0.name=@"123"
error: <user expression 1>:1:4: property 'name' not found on object of type 'id _Nullable'
$0.name=@"123"
   ^
(lldb) 
Copy the code

We find that the setting is unsuccessful because we need a strong roll of $0, for example

(lldb) p (Person *)self.models.lastObject
(Person *) $1 = 0x00006000029c4c20
(lldb) p $1.name = @"123";
(NSTaggedPointerString *) $2 = 0x8904a8a4b4d8c163 @"123"
(lldb) 
Copy the code

And p can execute multiple statements, such as to the breakpoint above

(lldb) p Person *p = [Person new]; p.name = @"123"; [self.models addObject:p]; (lldb) po self.models <__NSArrayM 0x6000027de580>( <Person: 0x6000029c4b40>, <Person: 0x6000029c4c00>, <Person: 0x6000029c4c20>, <Person: 0x6000029c4c60> ) (lldb)Copy the code

We find that we create an object with the P statement and then add the object to the array

Look at the function call stack

Write the following code in the Demo:

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    NSString *str = @"123";
    [self test1:str];
}

-(void)test1:(NSString *)str{
    NSLog(@"%@",str);
    [self test2:str];
}
-(void)test2:(NSString *)str{
    NSLog(@" %s %@",__func__,str);
    [self test3:str];
}
-(void)test3:(NSString *)str{
    NSLog(@" %s %@",__func__,str);
    [self test4:str];
}
-(void)test4:(NSString *)str{
    NSLog(@" %s %@",__func__,str);
}
Copy the code

Look at the stack instruction: BT

In test4, we set a breakpoint, run it, and then we can use the instructionbtTo view the stack information for the call:

Note that if test2 calls test3, the stack may not print if there is no code other than test3

Look at a stack instruction: frame Select 1

We can use frame Select 1 to view the details of a stack:

(lldb) frame select 1
frame #1: 0x0000000100dab178 ZJJAllModule_Example`-[ZJJLLDBViewController test3:](self=<unavailable>, _cmd=<unavailable>, str=<unavailable>) at ZJJLLDBViewController.m:34:5 [opt]
   31  	}
   32  	-(void)test3:(NSString *)str{
   33  	    NSLog(@" %s %@",__func__,str);
-> 34  	    [self test4:str];
    	    ^
   35  	}
   36  	-(void)test4:(NSString *)str{
   37  	    NSLog(@" %s %@",__func__,str);
(lldb) 
Copy the code

So we can see the details of the first stack

Look at the previous stack instruction: up

(lldb) up
frame #2: 0x0000000100dab118 ZJJAllModule_Example`-[ZJJLLDBViewController test2:](self=<unavailable>, _cmd=<unavailable>, str=<unavailable>) at ZJJLLDBViewController.m:30:5 [opt]
   27  	}
   28  	-(void)test2:(NSString *)str{
   29  	    NSLog(@" %s %@",__func__,str);
-> 30  	    [self test3:str];
    	    ^
   31  	}
   32  	-(void)test3:(NSString *)str{
   33  	    NSLog(@" %s %@",__func__,str);
(lldb) 
Copy the code

Look at the next stack instruction: down

(lldb) down
frame #1: 0x0000000100dab178 ZJJAllModule_Example`-[ZJJLLDBViewController test3:](self=<unavailable>, _cmd=<unavailable>, str=<unavailable>) at ZJJLLDBViewController.m:34:5 [opt]
   31  	}
   32  	-(void)test3:(NSString *)str{
-> 34  	    [self test4:str];
    	    ^
   35  	}
   36  	-(void)test4:(NSString *)str{
   37  	    NSLog(@" %@",str);
(lldb) 
Copy the code

We enter test1 with the up instruction

View method parameter :frame variable

For example, let’s add a breakpoint to viewDidLoad and look at the variables in the viewDidLoad method:

(lldb) frame variable (ZJJLLDBViewController *) self = 0x00007fb3d7c28ae0 (SEL) _cmd = "test2:" (__NSCFConstantString *)  str = 0x000000010add84f0 @"123"Copy the code

We found three arguments: self, _cmd, and STR, so that the argument and the station variable are printed out. Note that the __func__ function cannot be used in the method, otherwise the parameter value will not be printed out

Let’s change the code to look like this, with __func__ removed

- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. NSString *str = @"123"; [self test1:str]; } -(void)test1:(NSString *)str{ NSLog(@"%@",str); [self test2:str]; } -(void)test2:(NSString *)str{ NSLog(@"%@",str); [self test3:str]; NSLog(@"%@",str); } - (void) test3: (nsstrings *) STR {NSLog (@ % @ "before" test3:, STR); [self test4:str]; NSLog (@ "test3: % @", STR); } -(void)test4:(NSString *)str{ NSLog(@"%@",str); }Copy the code

Create a breakpoint in test4 and return to test3 with the up directive:

2020-11-12 14:28:22.000125+0800 ZJJAllModule_Example[12007:139341] 123 2020-11-12 14:28:22.000318+0800 ZJJAllModule_Example[12007:139341] 123 2020-11-12 14:28:22.000465+0800 ZJJAllModule_Example[12007:139341] test3: front 123 ZJJAllModule_Example was compiled with optimization - stepping may behave oddly; variables may not be available. (lldb) up frame #1: 0x000000010a8135b2 ZJJAllModule_Example`-[ZJJLLDBViewController test3:](self=<unavailable>, _cmd=<unavailable>, str=<unavailable>) at ZJJLLDBViewController.m:35:5 [opt] 32 } 33 -(void)test3:(NSString *)str{ 34 NSLog (@ % @ "before" test3:, STR); -> 35 [self test4:str]; ^ 36 NSLog(@"test3: back %@", STR); 37 } 38 -(void)test4:(NSString *)str{ (lldb)Copy the code

Let’s change the value of STR with the p instruction and see if the value of STR can be changed in the following method

(lldb) p str = @"nmc"
error: Couldn't materialize: couldn't get the value of variable str: variable not available
error: errored out in DoExecute, couldn't PrepareToExecuteJITExpression
(lldb) 
Copy the code

We found that it was immutable because executed code is immutable

Add returen: Thread Return to the breakpoint

We don’t want the program to go down at the breakpoint, but the program doesn’t crash, so we add a return to the program at the breakpoint with thread Return

Other instructions

  • The first is the equivalent of instruction C
  • The second single step executes $n next as a whole, using NI under assembly
  • The third step is to enter $s when a subfunction is encountered, and si is used under assembly

Memory breakpoints

Let’s change the code to look like this:

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
//    NSString *str = @"123";
//    [self test1:str];

    self.dataArray = [NSMutableArray array];

    ZJJPerson *p1 = [ZJJPerson new];
    p1.name = @"111";
    p1.age = 1;

    ZJJPerson *p2 = [ZJJPerson new];
    p2.name = @"222";
    p2.age = 2;

    ZJJPerson *p3 = [ZJJPerson new];
    p3.name = @"333";
    p3.age = 3;

    [self.dataArray addObject:p1];
    [self.dataArray addObject:p2];
    [self.dataArray addObject:p3];

}

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{

    ZJJPerson *p1 = [self.dataArray firstObject];
    p1.name = @"ABC";
}
Copy the code

To the [super viewDidLoad]; This line adds a breakpoint, rerunts, and then uses the N or Xcode tool to make the LLDB walk to p1.

After p1 is created, the object of P1 already exists in the heap, pointer to p1 object because [self.dataArray addObject:p1]; Method, which is still saved after the viewDidLoad method is done.

Watchpoint set variable p1->_name

Watchpoint set variable p1->_name

(lldb) watchpoint set variable p1->_name Watchpoint created: Watchpoint 1: addr = 0x6000010dc008 size = 8 state = enabled type = w declare @ '/ Users/zhaojing/Desktop/openGL/zhao silent test code/Example/ZJJAllModule LLDB/ZJJLLDBViewController. M: 29' watchpoint spec = 'p1->_name' new value: 0x000000010b2fa510 (lldb)Copy the code

The LLDB clearly tells us the address of the memory breakpoint and the size of the pointer (the OC object is 8 bytes).

When we get past the breakpoint, we click on the screen to trigger the p1.name = @”ABC” assignment method of touchesBegan, and a memory breakpoint is triggered. The two addresses printed at the top of the Po, we can see the old value and the new value. Then type BT to view the call stack to see the call queue stack clearly.

We can also use p1->_name memory pointer address to p1->_name memory breakpoint.

  • Get p1->_name memory address: &p1->_name
  • Down memory breakpoint: Use watchpoint set expression plus p1->_name memory address
  • Tap the screen to trigger assignment method validation
(lldb) p &p1->_name (NSString **) $0 = 0x000060000383a888 (lldb) watchpoint set expression 0x000060000383a888 Watchpoint  created: Watchpoint 1: addr = 0x60000383a888 size = 8 state = enabled type = w new value: 4551816464 Watchpoint 1 hit: old value: 4551816464 new value: 4551816560 (lldb) po 4551816464 111 (lldb) po 4551816560 ABC (lldb)Copy the code

Like symbolic breakpoints, memory breakpoints can be viewed and deleted

  • Check the memory breakpoint: Watchpoint List
  • To delete a memory breakpoint: watchpoint delete
(lldb) watchpoint list Number of supported hardware watchpoints: 4 Current watchpoints: Watchpoint 1: addr = 0x60000383a888 size = 8 state = enabled type = w old value: 4551816464 new value: 4551816560 (lldb) watchpoint delete About to delete all watchpoints, do you want to do that? : [Y/n] y All watchpoints removed. (1 watchpoints) (lldb)Copy the code

To add multiple instructions to a breakpoint: breakpoint Command add 1

Let’s add a breakpoint to the ‘touchesBegan’ and run the project

Breakpoint command add 1 breakpoint command add 1 breakpoint command add 1 breakpoint command add 1 Enter DONE.

(lldb) breakpoint list Current breakpoints: 1: The file = '/ Users/zhaojing/Desktop/openGL/zhao silent test code/Example/ZJJAllModule/LLDB/ZJJLLDBViewController m', the line = 49, Opact_match = 0, locations = 1, Resolved = 1, Hit count = 0 where = ZJJAllModule_Example`-[ZJJLLDBViewController touchesBegan:withEvent:] + 11 at ZJJLLDBViewController.m:49:27, address = 0x00000001063a8334, resolved, hit count = 0 (lldb) breakpoint command add 1 Enter your debugger command(s). Type 'DONE' to end. > po self > p self.view.backgroundColor > p self.view.backgroundColor = [UIColor redColor]; > DONECopy the code

After the breakpoint is dropped, the command is executed. After the breakpoint is dropped, the screen turns red.

As with breakpoints, you can view the instruction list and delete list:

  • Breakpoint command delete 1
  • Breakpoint Command List no longer exists.

Add instructions to all breakpoints

If we add multiple instructions to all breakpoints, we will execute our instructions as soon as any breakpoints come. For example, we often use the frame variable directive (view all the parameters of a method). Target stop-hook add -o “frame variable” to all breakpoints.

  • Target stop-hook The target is a breakpoint
  • Add to add
  • -o stands for –one, add an instruction
  • “Frame variable” needs to be added

Press enter, get over the breakpoint, add a breakpoint to the touchesBegan withEvent, click on the screen, enter the breakpoint, and execute the frame variable.

(lldb) target stop-hook add -o "frame variable"
Stop hook #1 added.
(ZJJLLDBViewController *const) self = <Could not evaluate DW_OP_entry_value.>

(SEL) _cmd = <Could not evaluate DW_OP_entry_value.>

(NSSet *) touches = <Could not evaluate DW_OP_entry_value.>

(UIEvent *) event = <Could not evaluate DW_OP_entry_value.>

(ZJJPerson *) p1 = <variable not available>


(lldb) 
Copy the code

Some other instructions for target stop-hook

  • Target stop-hook list View the list
  • Target stop-hook delete 1 Delete the first breakpoint
  • Target stop-hook delete Deletes all breakpoints
  • Target stop-hook disable 1 Disables the first set of breakpoints
  • Undisplay 1 Deletes the first set of breakpoints, the same as target stop-hook delete 1.

Add multiple instructions to all breakpoints using scripts

Every time Xcode is run, LLDB starts to load a file. Lldbinit. Type ls -a in the ~ directory (list all files, including hidden files,. Target stop-hook add -o “frame variable” target stop-hook add -o “frame variable” Press ESC and enter :wq to save the configuration and exit.

Since it is added to the LLDB of the system, it is valid for every project.

And then we go back to our Xcode and we just arbitrarily set a breakpoint.

Stop hook #1 added. ZJJAllModule_Example was compiled with optimization - stepping may behave oddly; variables may not be available. (ZJJLLDBViewController *const) self = <Could not evaluate DW_OP_entry_value.> (SEL) _cmd  = <Could not evaluate DW_OP_entry_value.> (NSSet *) touches = <Could not evaluate DW_OP_entry_value.> (UIEvent *) event  = <Could not evaluate DW_OP_entry_value.> (ZJJPerson *) p1 = <variable not available>Copy the code

Other instructions

  • Image List: View all libraries loaded by the current application

  • Image lookup -t Class name Displays header file information about a class

Reverse method breakpoint

There are no symbol files in reverse, so how do we break the method? The watchpoint set expression is used to set breakpoints in memory. Breakpoint is also used to set breakpoints in memory

b -a 0x100001980
Copy the code

To get the memory address of a method, use the Hopper Disassembler tool.

Let’s start with the following code

-(void)eatWithObject:(NSString *)objc{NSLog(@" eat %@",objc); } -(void) Touch began :(NSSet< touch *> *) Touches withEvent:(UIEvent *) Event {[self eatWithObject:@"! "] ; }Copy the code

Then compile, take the executable from the.app file, and drag it into the Hopper Disassembler.

From the list of methods on the left, we can see that the memory address of eatWithObject is 0x100002190, and we can add a breakpoint to that by saying B-a 0x100002190,

(lldb) b -a 0x100002190
warning: failed to set breakpoint site at 0x100002190 for breakpoint 1.1: error: 9 sending the breakpoint request
Breakpoint 1: address = 0x0000000100002190
(lldb) br list
Current breakpoints:
1: address = 0x0000000100002190, locations = 1
  1.1: address = 0x0000000100002190, unresolved, hit count = 0 

(lldb) 
Copy the code

We find that the breakpoint has downloaded successfully, and we already have a breakpoint in the breakpoint list, we click on it, but it doesn’t break, because 0x100002190 is just the offset of this method in machO, but it’s not the actual offset, we open the executable file of the project through machO, You can see from PAGEZERO in Load Commands that the VM Size is 4294967296

This starts with an empty address value, which on 64-bit systems is four gs, and doesn’t actually take up the real memory address, so the real offset is 0x100002190 minus this size, which is 0x100000000, which is 0x2190

So the actual memory address is going to be the memory address of the machO file, so let’s look at the memory address of the machO file through the image list

Add the two together to get the real memory address of the method. Let’s use our calculator to get the real memory address: 0x102B86190. Let’s test the breakpoint on this memory address

Then, by clicking on the screen, we see that the breakpoint has broken, and the technique is ASLR

ALSR

In computer science, Address Space Layout randomization (ASLR, also known as Address space configuration randomization, Address space layout randomization) is a computer security technology to prevent memory corruption vulnerability from being exploited.

Namely: physical address = ASLR + method virtual address

  • On iOS, ASLR is the memory address of image 0x0000000102b84000.
  • Because every time the application is loaded, the memory address of machO is different, which leads to the memory address of the real method, variable is also different, so that the hacker can not get the exact memory address, so as to prevent memory vulnerabilities.
  • The VM SIZE in PAGEZERO of Load Commands is 4 gigabytes on a 64-bit OS, which is virtual and does not take up real memory.
  • So for iOS, the real memory address is the memory address of the machO file plus the offset of the method relative to the machO file minus the VM SIZE, and you get the real memory address