iOS逆向?qū)崙?zhàn)--023:lldb調(diào)試技巧

lldbLow Lever Debug):默認(rèn)內(nèi)置于Xcode中的動態(tài)調(diào)試工具。標(biāo)準(zhǔn)的lldb提供了一組廣泛的命令,旨在與老版本的GDB命令兼容。 除了使用標(biāo)準(zhǔn)配置外,還可以很容易地自定義lldb以滿足實(shí)際需要

lldb語法:

<command> [<subcommand> [<subcommand>...]] <action> [-options [option-value]] [argument [argument...]]
  • <command>(命令)和<subcommand>(子命令):lldb調(diào)試命令的名稱
  • <action>:執(zhí)行命令的操作
  • <options>:命令選項
  • <arguement>:命令的參數(shù)
  • []:表示命令是可選的,可以有也可以沒有

示例:

breakpoint set -n test
  • commandbreakpoint表示斷點(diǎn)命令
  • actionset表示設(shè)置斷點(diǎn)
  • option-n表示根據(jù)方法name設(shè)置斷點(diǎn)
  • arguementtest表示方法名為tset
斷點(diǎn)設(shè)置

日常開發(fā)中,最常用的是Xcode斷點(diǎn)

但是在逆向環(huán)境中,我們并沒有第三方應(yīng)用的源碼,也不可能通過界面設(shè)置斷點(diǎn)

這種情況,只能使用breakpoint指令,在Xcodelldb控制臺,或直接在終端進(jìn)行斷點(diǎn)設(shè)置

案例1:

breakpoint指令的使用

打開ViewController.m文件,寫入以下代碼:

#import "ViewController.h"

@implementation ViewController

void test1(){
   NSLog(@"3");
}

- (void)viewDidLoad {
   [super viewDidLoad];
}

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
   NSLog(@"1");
   NSLog(@"2");
   test1();
}

@end

test1函數(shù)設(shè)置斷點(diǎn)

breakpoint set -n test1
-------------------------
Breakpoint 2: where = 001--LLDB調(diào)試`test1 + 16 at ViewController.m:13:5, >address = 0x0000000102ef1cb4
  • 對符號設(shè)置斷點(diǎn)
  • set是子命令
  • -n是選項,是--name的縮寫
  • 顯示Breakpoint 2,說明在001--LLDB調(diào)試的進(jìn)程中,設(shè)置的第2個斷點(diǎn),第1個是使用XcodetouchesBegan中設(shè)置的

案例2:

對控制器的指定方法設(shè)置斷點(diǎn)

打開ViewController.m文件,寫入以下代碼:

#import "ViewController.h"

@implementation ViewController

- (void)viewDidLoad {
   [super viewDidLoad];
}

- (IBAction)save:(id)sender {
   NSLog(@"保存");
}

- (IBAction)pause:(id)sender {
   NSLog(@"暫停");
}

- (IBAction)continueGame:(id)sender {
   NSLog(@"繼續(xù)");
}

@end

在逆向環(huán)境中,運(yùn)行第三方程序,使用暫??蛇M(jìn)入lldb控制臺,相當(dāng)于Debug進(jìn)程附加

ViewController中的多個符號設(shè)置斷點(diǎn)

breakpoint set -n "-[ViewController save:]" -n "-[ViewController pause:]" -n "-[ViewController continueGame:]"
-------------------------
Breakpoint 1: 3 locations.
  • Breakpoint 1表示分組1
  • 3 locations表示分組1下設(shè)置了3個斷點(diǎn)

使用breakpoint list查看斷點(diǎn)

breakpoint list
-------------------------
Current breakpoints:
1: names = {'-[ViewController save:]', '-[ViewController pause:]', '-[ViewController continueGame:]'}, locations = 3, resolved = 3, hit count = 0
 1.1: where = 001--LLDB調(diào)試`-[ViewController save:] + 60 at ViewController.m:17:5, address = 0x0000000104995cd0, resolved, hit count = 0 
 1.2: where = 001--LLDB調(diào)試`-[ViewController pause:] + 60 at ViewController.m:21:5, address = 0x0000000104995d28, resolved, hit count = 0 
 1.3: where = 001--LLDB調(diào)試`-[ViewController continueGame:] + 60 at ViewController.m:25:5, address = 0x0000000104995d80, resolved, hit count = 0 

案例3:

斷點(diǎn)的禁用、啟動和刪除

禁用斷點(diǎn)

breakpoint disable 1
-------------------------
1 breakpoints disabled.
  • 分組1下的所有斷點(diǎn)禁用

啟用斷點(diǎn)

breakpoint enable 1
-------------------------
1 breakpoints enabled.
  • 分組1下的所有斷點(diǎn)啟用

也可以對單一斷點(diǎn)禁用或啟用,例如:

breakpoint disable 1.1
-------------------------
1 breakpoints disabled.

刪除分組1下的所有斷點(diǎn)

breakpoint delete 1
-------------------------
1 breakpoints deleted; 0 breakpoint locations disabled.

刪除全部斷點(diǎn)

breakpoint delete
-------------------------
About to delete all breakpoints, do you want to do that?: [Y/n] y
All breakpoints removed. (1 breakpoint)

不支持刪除某單一斷點(diǎn),例如:

breakpoint delete 4.1
-------------------------
0 breakpoints deleted; 1 breakpoint locations disabled.

案例4:

了解更多breakpoint指令

使用help指令

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>'.

也可以了解更多選項的參數(shù)設(shè)置,例如:

help breakpoint set
-------------------------
    Sets a breakpoint or set of breakpoints in the executable.

Syntax: breakpoint set <cmd-options>

Command Options Usage:
 breakpoint set [-DHd] -l <linenum> [-G <boolean>] [-C <command>] [-c <expr>] [-i <count>] [-o <boolean>] [-q <queue-name>] [-t <thread-id>] [-x <thread-index>] [-T <thread-name>] [-R <address>] [-N <breakpoint-name>] [-u <column>] [-f <filename>] [-m <boolean>] [-s <shlib-name>] [-K <boolean>]
 breakpoint set [-DHd] -a <address-expression> [-G <boolean>] [-C <command>] [-c <expr>] [-i <count>] [-o <boolean>] [-q <queue-name>] [-t <thread-id>] [-x <thread-index>] [-T <thread-name>] [-N <breakpoint-name>] [-s <shlib-name>]
...

案例5:

對包含字符串的符號設(shè)置斷點(diǎn)

使用breakpoint set -n,對touchesBegan方法設(shè)置斷點(diǎn)

breakpoint set -n touchesBegan:
-------------------------
Breakpoint 5: no locations (pending).
WARNING:  Unable to resolve breakpoint to any actual locations.
  • 并沒有設(shè)置上斷點(diǎn),因?yàn)橥暾姆枮?code>touchesBegan:withEvent:

使用breakpoint set -r,對包含touchesBegan的符號設(shè)置斷點(diǎn)

breakpoint set -r touchesBegan:
-------------------------
Breakpoint 7: 101 locations.

使用breakpoint set --selector,對項目內(nèi)指定名稱的selector設(shè)置斷點(diǎn)

breakpoint set --selector touchesBegan:withEvent:
-------------------------
Breakpoint 9: 96 locations.

案例6:

指定文件設(shè)置斷點(diǎn)

使用breakpoint set --file,在指定文件內(nèi)設(shè)置斷點(diǎn)

breakpoint set --file ViewController.m --selector touchesBegan:withEvent:
-------------------------
Breakpoint 2: where = 001--LLDB調(diào)試`-[ViewController touchesBegan:withEvent:] + 92 at ViewController.m:30:4, address = 0x0000000100745d44

案例7:

lldb強(qiáng)大的縮寫功能

對包含touchesBegan的符號設(shè)置斷點(diǎn)

b -r touchesBegan
-------------------------
Breakpoint 3: 105 locations.

查看斷點(diǎn)的列表

break list

更簡單的寫法:

br list

對禁用斷點(diǎn)disable選項的簡寫:

br dis 1
-------------------------
1 breakpoints disabled.

對啟用斷點(diǎn)enable選項的簡寫:

br en 1
-------------------------
1 breakpoints enabled.
代碼執(zhí)行

expression指令,用于執(zhí)行代碼,縮寫指令為p、exp

配合p指令使用的po指令,意思是print object,用于打印對象,本質(zhì)上調(diào)用了對象的description

案例1:

使用expression指令執(zhí)行代碼

ViewController中的touchesBegan設(shè)置斷點(diǎn)

br set -f ViewController.m -r touchesBegan
-------------------------
Breakpoint 2: where = 001--LLDB調(diào)試`-[ViewController touchesBegan:withEvent:] + 92 at ViewController.m:30:4, address = 0x0000000102de5d44

點(diǎn)擊屏幕,進(jìn)入斷點(diǎn),使用expression指令執(zhí)行代碼

expression self.view.subviews
-------------------------
(__NSArrayM *) $0 = 0x00000002822eaee0 @"3 elements"

案例2:

設(shè)置背景色

使用expression指令,設(shè)置self.view的背景色

expression self.view.backgroundColor = [UIColor redColor]
-------------------------
error: <user expression 16>:1:11: property 'backgroundColor' not found on object of type 'UIView *'
  • 報錯,無法直接修改backgroundColor屬性

換一種方式,修改layer下的backgroundColor屬性

expression self.view.layer.backgroundColor = [UIColor yellowColor].CGColor
-------------------------
(CGColorRef) $7 = 0x00000002808a0d20

案例3:

對數(shù)組追加元素

打開ViewController.m文件,寫入以下代碼:

#import "ViewController.h"
#import "Person.h"

@interface ViewController ()
@property(nonatomic, strong) NSMutableArray<Person *> * models;
@end

@implementation ViewController

- (void)viewDidLoad {
   [super viewDidLoad];
   
   Person * p1 = [[Person alloc] initWithName:@"one" age:1];
   Person * p2 = [[Person alloc] initWithName:@"two" age:2];
   Person * p3 = [[Person alloc] initWithName:@"three" age:3];
    
   [self.models addObject:p1];
   [self.models addObject:p2];
   [self.models addObject:p3];
}

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
  NSLog(@"models:%@",self.models);
}

-(NSMutableArray<Person *> *)models {
   if (!_models) {
       _models = [NSMutableArray array];
   }
   return _models;
}

@end

ViewController中的touchesBegan設(shè)置斷點(diǎn)

br set -f ViewController.m -r touchesBegan
-------------------------
Breakpoint 1: where = 001--LLDB調(diào)試`-[ViewController touchesBegan:withEvent:] + 84 at ViewController.m:33:25, address = 0x0000000100cc5a6c

點(diǎn)擊屏幕,進(jìn)入touchesBegan方法的斷點(diǎn),追加數(shù)組元素

p [self.models addObject:[[Person alloc] initWithName:@"haha" age:4]]

使用ccontinue)指令,繼續(xù)執(zhí)行

c
-------------------------
001--LLDB調(diào)試[12107:2333568] models:(
   "<Person: 0x281043640>",
   "<Person: 0x281043680>",
   "<Person: 0x2810436a0>",
   "<Person: 0x2810591e0>"
)

輸出的models數(shù)組中存儲了4個對象,元素追加成功

案例4:

修改數(shù)組中對象的屬性

點(diǎn)擊屏幕,進(jìn)入touchesBegan方法的斷點(diǎn),獲取數(shù)組的第一個元素

p (Person *)self.models.firstObject
-------------------------
(Person *) $4 = 0x0000000281043640
  • $4為標(biāo)號,代表Person對象,可以使用

使用標(biāo)號,修改對象name屬性

p $4.name=@"123"
-------------------------
(NSTaggedPointerString *) $5 = 0xb868e91f5b072f35 @"123"

驗(yàn)證name屬性是否修改成功

po self.models.firstObject
-------------------------
<Person: 0x281043640>
p ((Person *)0x281043640).name
-------------------------
(NSTaggedPointerString *) $10 = 0xb868e91f5b072f35 @"123"

案例5:

執(zhí)行多行代碼

點(diǎn)擊屏幕,進(jìn)入touchesBegan方法的斷點(diǎn)

通過Option+Enter進(jìn)行換行,在lldb控制臺寫入以下代碼:

p Person * $tmp = self.models.firstObject;
p $tmp.name = @"Zang";
p $tmp.age = 18;
-------------------------
(NSTaggedPointerString *) $6 = 0x996ea49769521a4e @"Zang"
(int) $7 = 18

案例6:

其他流程控制的指令

使用ccontinue)指令,繼續(xù)執(zhí)行

c

使用nnext)指令,單步運(yùn)行,將子函數(shù)當(dāng)做整體一步執(zhí)行

n

使用s指令,單步運(yùn)行,遇到子函數(shù)會進(jìn)去

s
堆棧信息

案例1:

查看函數(shù)調(diào)用棧

使用bt指令,查看函數(shù)調(diào)用棧

  • *指向當(dāng)前的函數(shù)調(diào)用棧

使用up指令,查看上一個函數(shù)

up
-------------------------
frame #1: 0x0000000100151c68 001--LLDB調(diào)試`test1 at >ViewController.m:22:5
  19      }
  20      
  21      void test1(){
-> 22          test2();
          ^
  23      }
  24      
  25      void test2(){

同時*也指向上一個函數(shù)

使用down指令,查看下一個函數(shù)

down
-------------------------
frame #0: 0x0000000100151c80 001--LLDB調(diào)試`test2 at >ViewController.m:26:4
  23      }
  24      
  25      void test2(){
-> 26         NSLog(@"test2");
         ^
  27      }
  28      
  29      @end

使用frame select指令,選擇指定函數(shù)

frame select 10
-------------------------
frame #10: 0x000000019ef67480 UIKitCore`__eventFetcherSourceCallback + 156
UIKitCore`__eventFetcherSourceCallback:
->  0x19ef67480 <+156>: ldr    x0, [x19, #0x10]
   0x19ef67484 <+160>: mov    x1, x21
   0x19ef67488 <+164>: bl     0x19c2d1e28
   0x19ef6748c <+168>: mov    x1, x0

使用上述指令,可以將斷點(diǎn)定位到指定函數(shù)。它的作用可以查看函數(shù)的調(diào)用者,通過匯編代碼分析參數(shù)的傳遞。但寄存器的環(huán)境并不會發(fā)生變化,數(shù)據(jù)保存的還是最后一個函數(shù)執(zhí)行完畢的結(jié)果

案例2:

查看方法的參數(shù)和局部變量

打開ViewController.m文件,寫入以下代碼:

#import "ViewController.h"

@implementation ViewController

- (void)viewDidLoad {
   [super viewDidLoad];
}

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
   [self lalala1:@"HAHA"];
}

-(void)lalala1:(NSString *)str{
   [self lalala2:str];
}

-(void)lalala2:(NSString *)str{
   NSString *str1 = @"Zang";
   NSLog(@"%@:%@",str1, str);
}

@end

點(diǎn)擊屏幕,進(jìn)入lalala2方法的斷點(diǎn),使用frame variable指令,查看方法的參數(shù)和局部變量

frame variable
-------------------------
(ViewController *) self = 0x0000000105506860
(SEL) _cmd = "lalala2:"
(__NSCFConstantString *) str = 0x0000000104f94080 @"HAHA"
(__NSCFConstantString *) str1 = 0x0000000104f940a0 @"Zang"

在逆向過程中,進(jìn)入一個方法,最想看到的就是該方法的調(diào)用者、方法名稱、參數(shù)等信息,我們可以使用frame variable指令進(jìn)行查看。還可以配合up、downframe select指令,查看調(diào)用棧中其他方法的信息

案例3:

修改方法的參數(shù)

上述案例,點(diǎn)擊屏幕,進(jìn)入lalala2方法的斷點(diǎn)

使用frame variable指令,查看方法的參數(shù)和局部變量

frame variable
-------------------------
(ViewController *) self = 0x0000000100708b60
(SEL) _cmd = "lalala2:"
(__NSCFConstantString *) str = 0x0000000100124080 @"HAHA"
(__NSCFConstantString *) str1 = 0x00000001001240a0 @"Zang"

使用p指令,修改str的值

p str = @"COOL"
-------------------------
(NSTaggedPointerString *) $0 = 0xb4f673513386c4f4 @"COOL"

使用c指令,繼續(xù)運(yùn)行

c
-------------------------
001--LLDB調(diào)試[13539:2617881] Zang:COOL

輸出結(jié)果變?yōu)樾薷暮蟮膬?nèi)容,只針對當(dāng)前未執(zhí)行完的方法有效。對于已經(jīng)執(zhí)行完的方法,修改里面的內(nèi)容,并不影響最終的結(jié)果

案例4:

讓方法直接返回,不執(zhí)行里面的代碼

打開ViewController.m文件,寫入以下代碼:

#import "ViewController.h"

@implementation ViewController

- (void)viewDidLoad {
   [super viewDidLoad];
}

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
   [self check:@"HOOK"];
   NSLog(@"一切正常~");
}

-(void)check:(NSString *)str{
   
   if([str isEqualToString:@"HOOK"]){
       NSLog(@"有人HOOK我...");
       exit(0);
   }
}

@end

點(diǎn)擊屏幕,進(jìn)入check方法的斷點(diǎn)

使用thread return指令,讓check方法直接返回,不執(zhí)行里面的代碼

thread return

使用frame variable指令,查看thread return指令執(zhí)行后的函數(shù)

frame variable
-------------------------
(ViewController *) self = 0x0000000100e07ee0
(SEL) _cmd = "touchesBegan:withEvent:"
(__NSSetM *) touches = 0x0000000283e4dbc0 1 element
(UITouchesEvent *) event = 0x0000000280b61200
  • 已經(jīng)回到touchesBegan:withEvent:方法

使用c指令,繼續(xù)運(yùn)行

c
-------------------------
001--LLDB調(diào)試[13574:2625998] 一切正常~
  • check方法直接返回,方法內(nèi)驗(yàn)證str參數(shù)的代碼沒有被觸發(fā)

thread return指令,可用于調(diào)試階段,繞過指定方法

使用場景:原本執(zhí)行到某方法,執(zhí)行就會中斷。使用thread return指令繞過方法,如果可以正常執(zhí)行,證明此方法為檢測方法。后續(xù)可針對不同情況,選擇Method Swizzle、fishHookInlineHook對其進(jìn)行HOOK,將方法直接return

內(nèi)存斷點(diǎn)

案例1:

在對象的屬性上設(shè)置斷點(diǎn)

p1修改name屬性時,設(shè)置斷點(diǎn)

進(jìn)入斷點(diǎn),使用watchpoint指令,在p1對象的name上設(shè)置斷點(diǎn)

watchpoint set variable p1->_name
-------------------------
Watchpoint created: Watchpoint 1: addr = 0x280207570 size = 8 state = enabled type = w
   declare @ '/Users/zang/Zang/Spark/LG/14/LLDB/001--LLDB調(diào)試/ViewController.m:13'
   watchpoint spec = 'p1->_name'
   new value: 0x0000000102404088

使用c指令,繼續(xù)運(yùn)行

c
-------------------------
Watchpoint 1 hit:
old value: 0x0000000102404088
new value: 0x00000001024040a8

使用po指令

po 0x0000000102404088
-------------------------
one
po 0x00000001024040a8
-------------------------
new

當(dāng)調(diào)用name屬性的get/set方法,都會觸發(fā)此斷點(diǎn)??色@取到name屬性的原始值,和即將修改的值。配合bt指令,查看函數(shù)調(diào)用棧,可以跟蹤name屬性的修改是由哪個方法觸發(fā)的

案例2:

對屬性地址設(shè)置內(nèi)存斷點(diǎn)

進(jìn)入斷點(diǎn),獲取name屬性的地址

p &p1->_name
-------------------------
(NSString **) $0 = 0x0000000281e2ebb0

使用watchpoint指令,對屬性地址設(shè)置內(nèi)存斷點(diǎn)

watchpoint set expression 0x0000000281e2ebb0
-------------------------
Watchpoint created: Watchpoint 1: addr = 0x281e2ebb0 size = 8 state = enabled type = w
   new value: 4371808392

使用c指令,繼續(xù)運(yùn)行

c
-------------------------
Watchpoint 1 hit:
old value: 4371808392
new value: 4371808424

使用po指令

po 4371808392
-------------------------
one
po 4371808424
-------------------------
new
其他指令

案例1:

當(dāng)分組下斷點(diǎn)被觸發(fā),自動執(zhí)行指令

touchesBegan方法設(shè)置斷點(diǎn)

br set -f ViewController.m -r touchesBegan:
-------------------------
Breakpoint 3: where = 001--LLDB調(diào)試`-[ViewController touchesBegan:withEvent:] + 84 at ViewController.m:20:26, address = 0x0000000104945a6c

分組3斷點(diǎn),設(shè)置進(jìn)入斷點(diǎn)后的執(zhí)行的指令

br command add 3
-------------------------
Enter your debugger command(s).  Type 'DONE' to end.
> 

輸入指令

> frame variable
> DONE

使用c指令,繼續(xù)運(yùn)行

c

點(diǎn)擊屏幕,進(jìn)入touchesBegan方法的斷點(diǎn),同時輸出以下信息:

frame variable
(ViewController *) self = 0x0000000103507fc0
(SEL) _cmd = "touchesBegan:withEvent:"
(__NSSetM *) touches = 0x0000000282cea2e0 1 element
(UITouchesEvent *) event = 0x00000002819c6640
(Person *) p1 = 0x00000001e3fe2f18

案例2:

當(dāng)任何斷點(diǎn)被觸發(fā),自動執(zhí)行指令

target stop-hook add -o "frame variable"
-------------------------
Stop hook #1 added.

查看stop-hook的指令列表

target stop-hook list
-------------------------
Hook: 1
 State: enabled
 Commands: 
   frame variable

刪除某一條指令

target stop-hook delete 1
undisplay 1

刪除全部指令

target stop-hook delete
-------------------------
Delete all stop hooks?: [Y/n] y

禁用某一條指令

target stop-hook disable 1

啟用某一條指令

target stop-hook enable 1

添加執(zhí)行代碼

display self.view
  • 等同于expr -- self.view

對于frame variable指令,基本上每個斷點(diǎn)觸發(fā)后都要使用。但lldb每次啟動都要重新配置命令,有沒有一勞永逸的方法呢?

案例3:

配置lldb初始化文件

在家目錄下,存儲了lldb的初始化文件

cd /
ls

lldbinit文件的作用,當(dāng)lldb啟動,就會加載此文件,執(zhí)行文件內(nèi)的指令

使用vi ~/.lldbinit,寫入以下指令:

target stop-hook add -o "frame variable"

運(yùn)行項目,lldb啟動,輸出以下內(nèi)容:

Stop hook #1 added.

進(jìn)入viewDidLoad斷點(diǎn),輸出以下內(nèi)容:

(ViewController *) self = 0x0000000135f093a0
(SEL) _cmd = "viewDidLoad"

總結(jié)

斷點(diǎn)設(shè)置

  • breakpoint set -n xxx:對方法/函數(shù)名稱設(shè)置斷點(diǎn)
  • breakpoint set -r xxx:對包含字符串的符號設(shè)置斷點(diǎn)
  • breakpoint set --selector xxx:對項目內(nèi)指定名稱的selector設(shè)置斷點(diǎn)
  • breakpoint set --file xxx:在指定文件中設(shè)置斷點(diǎn)
  • breakpoint list:查看斷點(diǎn)列表
  • breakpoint disable:禁用斷點(diǎn)
  • breakpoint enable:啟用斷點(diǎn)
  • breakpoint delete:刪除斷點(diǎn)
  • 縮寫:break、br,設(shè)置斷點(diǎn)可縮寫指令:b

代碼執(zhí)行

  • po指令:意思是print object,用于打印對象,本質(zhì)上調(diào)用了對象的description
  • expression指令:用于執(zhí)行代碼
    ? 縮寫:exp、p
    ? 可以使用標(biāo)號
    ? 可執(zhí)行多行代碼
  • 流程控制
    ? ccontinue)指令:繼續(xù)執(zhí)行
    ? nnext)指令:單步運(yùn)行,將子函數(shù)當(dāng)做整體一步執(zhí)行
    ? ni指令:單步運(yùn)行匯編級別
    ? s指令:單步運(yùn)行,遇到子函數(shù)會進(jìn)去
    ? si指令:單步運(yùn)行可跳轉(zhuǎn)指令內(nèi)部,匯編級別
    ? finish指令:直接走完當(dāng)前方法,返回到上層frame

堆棧信息

  • bt指令:查看函數(shù)調(diào)用棧
  • up指令:查看上一個函數(shù)
  • down指令:查看下一個函數(shù)
  • frame select指令:選擇指定函數(shù)
  • frame variable指令:查看方法調(diào)用者、方法名稱、參數(shù)和局部變量
  • thread return指令:讓方法直接返回,不執(zhí)行里面的代碼

內(nèi)存斷點(diǎn):

  • watchpoint指令,設(shè)置內(nèi)存斷點(diǎn)

其他指令

  • br command add指令:給斷點(diǎn)添加命令的命令
  • target stop-hook add -o "xxx":每次stop的時候去執(zhí)行一些命令,針對breadpointwatchpoint
  • 配置lldb初始化文件,當(dāng)lldb啟動,就會加載此文件,執(zhí)行文件內(nèi)的指令,一勞永逸

lldb更多文檔

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 斷點(diǎn) 1.添加斷點(diǎn) 1.給test1函數(shù)添加斷點(diǎn)(C函數(shù))set 是子命令, -n 是選項,是--name 的縮寫...
    小寶_ab67閱讀 3,066評論 0 1
  • 一 利用class-dump導(dǎo)出所有頭文件 1. 安裝class-dunmp 可以直接安裝class-dump 或...
    meryin閱讀 2,160評論 0 6
  • 接下來上今天的干貨LLDB調(diào)試部分。日常的正向開發(fā),Xcode提供了多種快捷鍵以及快捷方式方便我們開發(fā)者進(jìn)行LLD...
    溪浣雙鯉閱讀 1,009評論 0 1
  • 常用指令 continue / c 執(zhí)行到下一個斷點(diǎn) next / n 單步運(yùn)行 把子函數(shù)當(dāng)作整體 st...
    小狼_zy閱讀 496評論 0 1
  • 一、簡介 LLDB全稱是Low Lever Debug。 下斷點(diǎn)快捷鍵command + \ 二、LLDB斷點(diǎn)設(shè)置...
    可惜你不是我的雙子座閱讀 625評論 1 0

友情鏈接更多精彩內(nèi)容