iOS Swift

iOS LLDB常用调试技巧记录汇总

2018-07-26  本文已影响75人  史贵岭

1.单步调试

单步调试通常分为两大类,一类为源码级别(source level),一类为指令级别(instrution level)。一行源代码一般需要多行汇编才可以实现,所以当我们越狱开发调试汇编指令单步调试需要用到(instrution level)指令级别。而每一大类又分为step-in和step-over,step-in会进入函数调用,而step-over会跳过函数调用。

单步调试

1.1源码级别(source level)

1.1.1 step-in
(lldb) thread step-in
(lldb) step
(lldb) s

以上三条命令是等同的。假如我们在ViewController的第20行下了断点,每执行一次上述命令断点会跳转到下一行源代码位置,如果下一行是一个函数调用,会进入函数调用内部。比如当执行到23行时,输入s命令,会进入testMethod函数内部,跳转到39行。

1.1.2 step-over
(lldb) thread step-over
(lldb) next
(lldb) n

以上三条命令是等同的。假如我们在ViewController的第20行下了断点,每执行一次上述命令断点会跳转到下一行源代码位置,如果下一行是一个函数调用,则不会进入函数调用内部。比如当执行到23行时,输入n命令,却不会跳转到39行,而是45行(之所以会跳转到45行,因为在45行设置了断点)。

1.2指令级别(instrution level)

理解了s和n命令的区别。si和ni同理。假如汇编指令有一个bl跳转指令,si会单步进入bl指令的子函数内部,而ni就不会。

1.2.1 step-in
(lldb) thread step-inst
(lldb) si
1.1.2 step-over
(lldb) thread step-inst-over
(lldb) ni

1.3 step-out

(lldb) thread step-out
(lldb) finish

对于单步调试总结下:对于逆向开发si和ni命令会使用较多,正向App开发,s和n命令较多

1.4 s(si)、n(ni)和xcode调试工具对应关系

xcode调试工具
1.3.1xcode第二个图标
1.3.2xcode第三个图标
1.3.3xcode第四个图标
1.3.4xcode第五个图标

2.断点命令

2.1设置断点

(lldb) breakpoint set --name "-[NSString stringWithFormat:]"
(lldb) br s -n "-[NSString stringWithFormat:]"
(lldb) b -[NSString stringWithFormat:]
(lldb) breakpoint set --address 0x00000001c44441d0
(lldb) br s -a 0x00000001c44441d0

2.2列举所有断点

(lldb) breakpoint list
(lldb) br l

2.3删除断点

(lldb) breakpoint delete 1
(lldb) br del 1

3. expression命令

3.1打印变量

(lldb) expr -o -- [SomeClass returnAnObject]
or using the po alias:
(lldb) po [SomeClass returnAnObject]

以特定格式打印变量
下面分别以16进制(x),字符(c),二进制(t)打印变量

(lldb) p/x 2
(int) $0 = 0x00000002
(lldb) p/c (char)97
(char) $2 = 'a'
(lldb) p/t 2
(int) $4 = 0b00000000000000000000000000000010

3.2申明变量

(lldb) e NSString* abc = @"abc"
(lldb) po abc
abc

3.3修改变量

在如下函数设置断点


修改变量

如图所示,ii初始值为0,但是可以通过expression命令修改其初始化值为 10000

lldb) p ii
(int) $0 = 0
(lldb) e ii = 10000
(int) $1 = 10000
(lldb) p ii
(int) $2 = 10000

4.调试信息

(lldb) frame info
frame #0: 0x0000000104cc6d1c TestPAD`-[ViewController testParam:b:c:d:](self=0x0000000149d0aaa0, _cmd="testParam:b:c:d:", a=10, b=20, c=30, d=40) at ViewController.m:31
(lldb) thread info 
thread #1: tid = 0xfb0ab5, 0x0000000104cc6d1c TestPAD`-[ViewController testParam:b:c:d:](self=0x0000000149d0aaa0, _cmd="testParam:b:c:d:", a=10, b=20, c=30, d=40) at ViewController.m:31, queue = 'com.apple.main-thread', stop reason = breakpoint 9.1
lldb) thread list
Process 29252 stopped
* thread #1: tid = 0xfb0ab5, 0x0000000104cc6d1c TestPAD`-[ViewController testParam:b:c:d:](self=0x0000000149d0aaa0, _cmd="testParam:b:c:d:", a=10, b=20, c=30, d=40) at ViewController.m:31, queue = 'com.apple.main-thread', stop reason = breakpoint 9.1
  thread #3: tid = 0xfb0ad8, 0x000000018608fdf4 libsystem_dnssd.dylib`ConvertHeaderBytes, queue = 'com.skyeye.analytics.network.queue'
  thread #4: tid = 0xfb0ad9, 0x00000001860f5dbc libsystem_kernel.dylib`__workq_kernreturn + 8
  thread #5: tid = 0xfb0ada, 0x0000000186206c1c libsystem_pthread.dylib`start_wqthread
  thread #6: tid = 0xfb0adb, 0x00000001860d4bc4 libsystem_kernel.dylib`mach_msg_trap + 8, queue = 'com.SkyEye.905541C85D654B539C85DEECF2689651.0x1c0462b00.network'
  thread #7: tid = 0xfb0adc, 0x00000001860d4bc4 libsystem_kernel.dylib`mach_msg_trap + 8, name = 'com.apple.uikit.eventfetch-thread'
  thread #8: tid = 0xfb0ade, 0x00000001860f5c1c libsystem_kernel.dylib`__ulock_wait + 8, queue = 'com.skyeye.analytics.interface.queue'
  thread #9: tid = 0xfb0ae0, 0x00000001860d4bc4 libsystem_kernel.dylib`mach_msg_trap + 8, name = 'com.apple.NSURLConnectionLoader'
  thread #10: tid = 0xfb0ae2, 0x0000000186206c1c libsystem_pthread.dylib`start_wqthread
(lldb) frame variable
(ViewController *) self = 0x0000000149d0aaa0
(SEL) _cmd = "testParam:b:c:d:"
(int) a = 10
(int) b = 20
(int) c = 30
(int) d = 40
(int) ii = 10000
 lldb) register read
General Purpose Registers:
        x0 = 0x0000000149d0aaa0
        x1 = 0x0000000104d9dd46  "testParam:b:c:d:"
        x2 = 0x000000000000000a
        x3 = 0x0000000000000014
        x4 = 0x000000000000001e
        x5 = 0x0000000000000028
        x6 = 0x0000000000000000
        x7 = 0x000000016b156808
        x8 = 0x0000000104dd9330  "testParam:b:c:d:"
        x9 = 0x0000000000000000
       x10 = 0x0086860100868680
       x11 = 0x0000000000868601
       x12 = 0x0000000000868500
       x13 = 0x0000000000000001
       x14 = 0x0000000000000000
       x15 = 0x00868601008686c0
       x16 = 0x0000000000000000
       x17 = 0x0000000104cc6cf4  TestPAD`-[ViewController testParam:b:c:d:] at ViewController.m:29
       x18 = 0x0000000000000000
       x19 = 0x00000001b70ab8c0  UIKit`_UIApplicationLinkedOnVersion
       x20 = 0x0000000149d0aaa0
       x21 = 0x0000000000000018
       x22 = 0x0000000190799d6a  "count"
       x23 = 0x0000000000000000
       x24 = 0x0000000000000000
       x25 = 0x000000014a017c00
       x26 = 0x0000000000000408
       x27 = 0x00000001c0099410
       x28 = 0x0000000000000000
        fp = 0x000000016b157f60
        lr = 0x0000000104cc6bbc  TestPAD`-[ViewController viewDidLoad] + 164 at ViewController.m:24
        sp = 0x000000016b157f30
        pc = 0x0000000104cc6d1c  TestPAD`-[ViewController testParam:b:c:d:] + 40 at ViewController.m:31
      cpsr = 0x20000000
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 9.1
  * frame #0: 0x0000000104cc6d1c TestPAD`-[ViewController testParam:b:c:d:](self=0x0000000149d0aaa0, _cmd="testParam:b:c:d:", a=10, b=20, c=30, d=40) at ViewController.m:31
    frame #1: 0x0000000104cc6bbc TestPAD`-[ViewController viewDidLoad](self=0x0000000149d0aaa0, _cmd="viewDidLoad") at ViewController.m:24
    frame #2: 0x000000018fa14efc UIKit`-[UIViewController loadViewIfRequired] + 1040
    frame #3: 0x000000018fabc5ec UIKit`-[UINavigationController _updateScrollViewFromViewController:toViewController:] + 76
    frame #4: 0x000000018fabba8c UIKit`-[UINavigationController _startTransition:fromViewController:toViewController:] + 196
    frame #5: 0x000000018fabb490 UIKit`-[UINavigationController _startDeferredTransitionIfNeeded:] + 1168
    frame #6: 0x000000018fabaf0c UIKit`-[UINavigationController __viewWillLayoutSubviews] + 164
    frame #7: 0x000000018fabae0c UIKit`-[UILayoutContainerView layoutSubviews] + 188
    frame #8: 0x000000018fa122f8 UIKit`-[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1276
    frame #9: 0x000000018a5cbec8 QuartzCore`-[CALayer layoutSublayers] + 184
    frame #10: 0x000000018a5cffa8 QuartzCore`CA::Layer::layout_if_needed(CA::Transaction*) + 332
    frame #11: 0x000000018a53ea98 QuartzCore`CA::Context::commit_transaction(CA::Transaction*) + 336
    frame #12: 0x000000018a564eb4 QuartzCore`CA::Transaction::commit() + 540
    frame #13: 0x000000018fc90174 UIKit`__34-[UIApplication _firstCommitBlock]_block_invoke_2 + 140
    frame #14: 0x00000001865860fc CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 20
    frame #15: 0x00000001865859cc CoreFoundation`__CFRunLoopDoBlocks + 288
    frame #16: 0x00000001865836dc CoreFoundation`__CFRunLoopRun + 1068
    frame #17: 0x00000001864a3fb8 CoreFoundation`CFRunLoopRunSpecific + 436
    frame #18: 0x000000018833bf84 GraphicsServices`GSEventRunModal + 100
    frame #19: 0x000000018fa782e8 UIKit`UIApplicationMain + 208
    frame #20: 0x0000000104cd5d14 TestPAD`main(argc=1, argv=0x000000016b15b9c8) at main.m:14
    frame #21: 0x0000000185fc656c libdyld.dylib`start + 4
(lldb) memory read -f s $x1
或者
(lldb) x -f s $x1
或者
(lldb) x/s $x1
输出为:
0x104d9dd46: "testParam:b:c:d:"

(2)读取栈中所有值,即sp和fp连续内存区域值。

(lldb) x -f A $sp $fp

(3) 读取目标内存指令,比如x/10xg sp 。10后面的x代表用16进制来显示结果,g代表giant word(8字节)大小。所以x/10xgsp就是用16进制显示栈区10个64位元素内容。常见的大小格式为"b-byte"(1字节) "h-half word"(2字节) "w-word"(4字节) "g-giant word"(8字节)

(lldb)  di -n "-[ViewController testParam:b:c:d:]"

TestPAD`-[ViewController testParam:b:c:d:]:
    0x104cc6cf4 <+0>:   sub    sp, sp, #0x40             ; =0x40 
    0x104cc6cf8 <+4>:   stp    x29, x30, [sp, #0x30]
    0x104cc6cfc <+8>:   add    x29, sp, #0x30            ; =0x30 
    0x104cc6d00 <+12>:  stur   x0, [x29, #-0x8]
    0x104cc6d04 <+16>:  stur   x1, [x29, #-0x10]
    0x104cc6d08 <+20>:  stur   w2, [x29, #-0x14]
    0x104cc6d0c <+24>:  str    w3, [sp, #0x18]
    0x104cc6d10 <+28>:  str    w4, [sp, #0x14]
    0x104cc6d14 <+32>:  str    w5, [sp, #0x10]
    0x104cc6d18 <+36>:  str    wzr, [sp, #0xc]
->  0x104cc6d1c <+40>:  ldur   w2, [x29, #-0x14]
    0x104cc6d20 <+44>:  ldr    w3, [sp, #0xc]
    0x104cc6d24 <+48>:  add    w2, w3, w2
    0x104cc6d28 <+52>:  str    w2, [sp, #0xc]
    0x104cc6d2c <+56>:  ldr    w2, [sp, #0x18]
    0x104cc6d30 <+60>:  ldr    w3, [sp, #0xc]
    0x104cc6d34 <+64>:  add    w2, w3, w2
    0x104cc6d38 <+68>:  str    w2, [sp, #0xc]
    0x104cc6d3c <+72>:  ldr    w2, [sp, #0x14]
    0x104cc6d40 <+76>:  ldr    w3, [sp, #0xc]
    0x104cc6d44 <+80>:  add    w2, w3, w2
    0x104cc6d48 <+84>:  str    w2, [sp, #0xc]
    0x104cc6d4c <+88>:  ldr    w2, [sp, #0x10]
    0x104cc6d50 <+92>:  ldr    w3, [sp, #0xc]
    0x104cc6d54 <+96>:  add    w2, w3, w2
    0x104cc6d58 <+100>: str    w2, [sp, #0xc]
    0x104cc6d5c <+104>: ldr    w2, [sp, #0xc]
    0x104cc6d60 <+108>: mov    x0, x2
    0x104cc6d64 <+112>: mov    x1, sp
    0x104cc6d68 <+116>: str    x0, [x1]
    0x104cc6d6c <+120>: adrp   x0, 249
    0x104cc6d70 <+124>: add    x0, x0, #0xc68            ; =0xc68 
    0x104cc6d74 <+128>: bl     0x104d9a9b4               ; symbol stub for: NSLog
    0x104cc6d78 <+132>: ldp    x29, x30, [sp, #0x30]
    0x104cc6d7c <+136>: add    sp, sp, #0x40             ; =0x40 
    0x104cc6d80 <+140>: ret    

4.Match-O可执行文件及Shared库查询命令

(lldb) image list -o -f "TestPAD"
[  0] 0x0000000004ca4000 /Users/shiguiling063/Library/Developer/Xcode/DerivedData/TestPAD-bpwpvzedhypusjgfujyksktehppj/Build/Products/Debug-iphoneos/TestPAD.app/TestPAD
(lldb) image  lookup -r -n "testParam"
或者
(lldb) im  loo -r -n "testParam"
2 matches found in /Users/shiguiling063/Library/Developer/Xcode/DerivedData/TestPAD-bpwpvzedhypusjgfujyksktehppj/Build/Products/Debug-iphoneos/TestPAD.app/TestPAD:
        Address: TestPAD[0x0000000100022cf4] (TestPAD.__TEXT.__text + 118184)
        Summary: TestPAD`-[ViewController testParam:b:c:d:] at ViewController.m:29        Address: TestPAD[0x0000000100022cf4] (TestPAD.__TEXT.__text + 118184)
        Summary: TestPAD`-[ViewController testParam:b:c:d:] at ViewController.m:29
(lldb)  image lookup --type ViewController
或者
(lldb) im loo -t ViewController
Best match found in /Users/shiguiling063/Library/Developer/Xcode/DerivedData/TestPAD-bpwpvzedhypusjgfujyksktehppj/Build/Products/Debug-iphoneos/TestPAD.app/TestPAD:
id = {0xb00000042}, name = "ViewController", byte-size = 16, decl = ViewController.h:11, compiler_type = "@interface ViewController : UITableViewController{
    NSArray * _dataArr;
}
@property ( getter = dataArr,setter = setDataArr:,readwrite,copy,nonatomic ) NSArray * dataArr;
@end"
(lldb)  image dump symtab -m TestPAD
Symtab, file = /Users/shiguiling063/Library/Developer/Xcode/DerivedData/TestPAD-bpwpvzedhypusjgfujyksktehppj/Build/Products/Debug-iphoneos/TestPAD.app/TestPAD, num_symbols = 4121:
               Debug symbol
               |Synthetic symbol
               ||Externally Visible
               |||
Index   UserID DSX Type            File Address/Value Load Address       Size               Flags      Name
------- ------ --- --------------- ------------------ ------------------ ------------------ ---------- ----------------------------------
[    0]      0 D   SourceFile      0x0000000000000000                    Sibling -> [   19] 0x00640000 /Users/shiguiling063/Downloads/越狱开发相关/TestPADSource/TestPAD/PAD/PADSource/TalkingData/SkyEyeData/Codeless/SEObjectSerializer.m
[    1]      2 D   ObjectFile      0x000000005b55a875                    0x0000000000000000 0x00660001 /Users/shiguiling063/Library/Developer/Xcode/DerivedData/TestPAD-bpwpvzedhypusjgfujyksktehppj/Build/Intermediates.noindex/TestPAD.build/Debug-iphoneos/TestPAD.build/Objects-normal/arm64/SEObjectSerializer.o
[    2]      4 D   Code            0x0000000100006028                    0x0000000000000140 0x000e0000 -[SEObjectSerializer initWithConfiguration:objectIdentityProvider:]
[    3]      8 D   Code            0x0000000100006168                    0x000000000000035c 0x000e0000 -[SEObjectSerializer serializedObjectsWithRootObject:]
[    4]     12 D   Code            0x00000001000064c4                    0x0000000000000c00 0x000e0000 -[SEObjectSerializer visitObject:withContext:]
[    5]     16 D   Code            0x00000001000070c4                    0x0000000000000120 0x000e0000 -[SEObjectSerializer classHierarchyArrayForObject:]
[    6]     20 D   Code            0x00000001000071e4                    0x000000000000027c 0x000e0000 -[SEObjectSerializer allValuesForType:]
[    7]     24 D   Code            0x0000000100007460                    0x000000000000053c 0x000e0000 -[SEObjectSerializer parameterVariationsForPropertySelector:]
[    8]     28 D   Code            0x000000010000799c                    0x0000000000000968 0x000e0000 -[SEObjectSerializer instanceVariableValueForObject:propertyDescription:]
[    9]     32 D   Code            0x0000000100008304                    0x000000000000040c 0x000e0000 -[SEObjectSerializer invocationForObject:withSelectorDescription:]
[   10]     36 D   Code            0x0000000100008710                    0x0000000000000578 0x000e0000 -[SEObjectSerializer propertyValue:propertyDescription:context:]
[   11]     40 D   Code            0x0000000100008c88                    0x000000000000099c 0x000e0000 -[SEObjectSerializer propertyValueForObject:withPropertyDescription:context:]
[   12]     44 D   Code            0x0000000100009624                    0x000000000000009c 0x000e0000 -[SEObjectSerializer isNestedObjectType:]
[   13]     48 D   Code            0x00000001000096c0                    0x0000000000000264 0x000e0000 -[SEObjectSerializer classDescriptionForObject:]
[   14]     52 D   Code            0x0000000100009924                    0x0000000000000070 0x000e0000 -[SEObjectSerializer .cxx_destruct]
[   15]     55 D X ObjCIVar        0x00000001001372f0                    0x0000000000000004 0x001e0000 

5.Script & Chisel

LLDB 有内建的,完整的 Python支持。在LLDB中输入 script,会打开一个 Python REPL。你也可以输入一行 python 语句作为 script 命令的参数,这可以运行 python 语句而不进入REPL

(lldb) script print 'Hello World'
Hello World

Facebook开源的Chisel就是基于此实现
Facebook通过python脚本扩展和丰富了lldb命令,具体以Chisel文档为准

Chisel 扩展LLDB命令

6. watchpoint命令

(lldb) watchpoint set variable global_var
或者
(lldb) wa s v global_var
(lldb) watchpoint set expression -- my_ptr
或者
(lldb) wa s e -- my_ptr
(lldb) watch set var global
(lldb) watchpoint modify -c '(global==5)'
(lldb) c
(lldb) watchpoint list
或者
(lldb) watch l
(lldb) watchpoint delete 1
或者
(lldb) watch del 1

7.其他命令补充

(lldb) register write pc `$pc+8`
(lldb)  target stop-hook add --one-liner "frame variable"

8.更多

更多LLDB命令请参照LLDB官网公布资料:http://lldb.llvm.org/lldb-gdb.html

上一篇 下一篇

猜你喜欢

热点阅读