CC的博客

  • 首页
  • iOS
  • Android
  • React-Native
  • 读书杂谈
  • About
CC
记录美好生活
  1. 首页
  2. 技术编程
  3. iOS
  4. 正文

动态调试-debugserver+LLDB

2021/06/19

动态调试

debugserver是Xcode自带的工具,默认放在/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/14.4/DeveloperDiskImage.dmg/usr/bin/debugserver

通过Xcode连接真机后,自动拷贝debugserver到越狱手机的/Developer/usr/bin/debugserver(此处是只读权限),一般情况下只能调试通过Xcode安装的App

image
默认只能调试Xcode安装的应用,需要给debugserver附上权限重新签名后可调试手机上的任意App。

对debugserver赋予权限

  1. 由于手机里的Developer目录是只读的权限无法直接操作debugserver,需要把debugserver拷贝到电脑上操作。
  2. 通过ldid命令导出原有的权限
ldid -e debugserver > debugserver.entitlements
  1. 修改debugserver.entitlements文件新增get-task-allow和task_for_pid-allow两个权限。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>com.apple.springboard.debugapplications</key>
    <true/>
    <key>get-task-allow</key>
    <true/>
    <key>task_for_pid-allow</key>
    <true/>
</dict>
</plist>
  1. 通过ldid命令进行重签名赋予权限
ldid -Sdebugserver.entitlements debugserver

或者通过codesign命令

//查看权限
$ codesign -d --entitlements - debugserver
//重签名
$ codesign -f -s - --entitlemetns debugserver.entitlements debugserver
//或者简写:
$ codesign -fs - --entitlemetns debugserver.entitlements debugserver

  1. 将处理过的debugserver放到手机/usr/bin/目录下

如果遇到 Permission denied执行
chmod +x /usr/bin/debugserver增加运行权限

使用debugserver

  1. 将debugserver附加到某App进程上
$ debugserver *:端口号 -a 进程
  • 端口号:使用iPhone的某个端口启动debugserver服务
  • 进程:App的进程信息(进程ID或进程名称)
  1. Mac上启动LLDB服务远程连接到iPhone上的debugserver

- 启动LLDB:lldb
- 连接debugserver服务:process connect connect://手机局域网IP:debugserver服务端口号
- 使用LLDB的c命令让程序继续运行

iPhone上

$ debugserver localhost:8888 -a HelloWorld
debugserver-@(#)PROGRAM:LLDB  PROJECT:lldb-900.3.106
 for arm64.
Attaching to process HelloWorld...
Listening to port 8888 for a connection from localhost...
Waiting for debugger instructions for process 0.

Mac上

$ lldb
(lldb) process connect connect://localhost:10020
Process 2147 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
    frame #0: 0x0000000198594198 libsystem_kernel.dylib`mach_msg_trap + 8
libsystem_kernel.dylib`mach_msg_trap:
->  0x198594198 <+8>: ret    

libsystem_kernel.dylib`mach_msg_overwrite_trap:
    0x19859419c <+0>: mov    x16, #-0x20
    0x1985941a0 <+4>: svc    #0x80
    0x1985941a4 <+8>: ret    
Target 0: (HelloWorld) stopped.
(lldb) c
Process 2147 resuming

也可以通过
debugserver -x auto *:端口号 App可执行文件路径:通过debugserver启动App

$ debugserver -x auto localhost:8888 /var/containers/Bundle/Application/A8673B49-C454-42EA-8D9D-357AAB67B8E7/HelloWorld.app/HelloWorld
debugserver-@(#)PROGRAM:LLDB  PROJECT:lldb-900.3.106
 for arm64.
Listening to port 8888 for a connection from localhost...

如果遇到下面的错误:

failed to attach to process named: "" unable to start the exception thread
或
Failed to get connection from a remote gdb process.

解决方案:检查权限文件里包含的权限是否正确。

遇到报错:

error: rejecting incoming connection from ::ffff:127.0.0.1 (expecting ::1)

解决方案:debugserver *:端口号 -a 进程改为debugserver localhost:端口号 -a 进程

LLDB

指令格式
<command> [<subcommand> [<subcommand>...]] <action> [-options [option-value]] [argument [argument...]]
  • command:命令
  • subcommand:子命令
  • action:命令操作
  • options:命令选项
  • arguments:命令参数

例如:给test函数设置断点

breakpoint set -n test

breakpoint是command;set是action;-n是options;test是arguments。

help <command>可查看命令帮助文档。
例如help breakpoint

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

expression <cmd-options> -- <expr>执行表达式

  • :命令选项
  • --:命令选项结束符,代表所有的命令选项都已设置完毕,如果没有命令选项可忽略。
  • :需要执行的表达式expression self.view.backgroundColor = [UIColor redColor]

expression和expression --与指令print、p、call效果一样

expression -O --和po效果一样

thread backtrace打印堆栈信息,和bt效果一样

thread return <expr>让函数直接返回某个值,不会执行断点之后的代码

frame variable [<variable-name>]打印当前栈帧的变量

thread continue continue c让程序继续运行

thread step-over next n单步运行,把子函数当做一步运行

thread step-in step s单步运行,遇到子函数进入子函数内部

thread step-out finish直接执行完当前函数的代码,返回到上一个函数

thread step-inst-over nexti ni

thread step-inst stepi si

si ni与s n类似 si ni是汇编指令级别 s n是源码级别

breakpoint set -n 函数名

breakpoint set -a 函数地址

breakpoint set -n test

breakpoint set -n test:some

breakpoint set "[someClass test]"

breakpoint set -r 正则表达式

breakpoint set -r tes

假如有两个函数:test和testNext,由于函数名都包含tes,所以两个函数都被设置上断点

breakpoint set -s 动态库 -n 函数名

breakpoint list:列出所有的断点,每个断点都有编号

breakpoint disable 断点编号:禁用断点

breakpoint enable 断点编号:启用断点

breakpoint delete 断点编号:删除断点

breakpoint command add 断点编号:给断点预先设置需要执行的命令,触发断点时就会按顺序执行。

$ breakpoint command add 2
Enter your debugger command(s).  Type 'DONE' to end.
> po self
> p self.view.backgroundColor = [UIColor redColor]
> DONE

breakpoint command list 断点编号:查看断点设置的命令

breakpoint command delect 断点编号:删除断点下的命令

内存断点

watchpoint set variable 变量 watchpoint set expression 地址:内存数据发生改变的时候触发

watchpoint set variable self->_age

watchpoint set expression &(self->_age)
watchpoint set variable self->_age
Watchpoint created: Watchpoint 1: addr = 0x7f8fff904c28 size = 8 state = enabled type = w
    watchpoint spec = 'self->_age'
    new value: 0
(lldb) c
Process 34409 resuming
2021-06-17 23:43:50.157314+0800 testlib[34409:7153831] screen parameters are unexpected: MGScreenClass1125x2436x3x495 SCREEN_TYPE(1125,2436,3,495)

Watchpoint 1 hit:
old value: 0
new value: 100

watchpoint list

watchpoint disable 断点编号

watchpoint enable 断点编号

watchpoint delect 断点编号

watchpoint command add 断点编号

watchpoint command list 断点编号

watchpoint command delect 断点编号

image lookup -t 类型:查找某个类型的信息

(lldb) image lookup -t NSString
Best match found in /Users/CC/Library/Developer/Xcode/DerivedData/testlib-dxolpnclkjwmjrgulkxqzmskrnlm/Build/Products/Debug-iphonesimulator/testlib.app/testlib:
id = {0x7fffffff000005a3}, name = "NSString", byte-size = 8, decl = NSString.h:99, compiler_type = "@interface NSString : NSObject
@property(readonly, getter = length, setter = <null selector>) NSUInteger length;
@end"

image lookup -a 地址:根据内存地址查找在模块里的信息

在viewController的touchesBegan:withEvent:方法里写入数组越界崩溃代码

#import "ViewController.h"
@interface ViewController ()

@end

@implementation ViewController

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

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    NSArray *someArray = @[];
    someArray[1];
}

程序报错信息如下所示:

*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArray0 objectAtIndex:]: index 1 beyond bounds for empty NSArray'
*** First throw call stack:
(
    0   CoreFoundation                      0x00007fff20421af6 __exceptionPreprocess + 242
    1   libobjc.A.dylib                     0x00007fff20177e78 objc_exception_throw + 48
    2   CoreFoundation                      0x00007fff20312243 -[__NSArray0 objectEnumerator] + 0
    3   testlib                             0x000000010fb507f5 -[ViewController touchesBegan:withEvent:] + 197
    4   UIKitCore                           0x00007fff246ca70f forwardTouchMethod + 321
    5   UIKitCore                           0x00007fff246ca5bd -[UIResponder touchesBegan:withEvent:] + 49
    6   UIKitCore                           0x00007fff246d95b5 -[UIWindow _sendTouchesForEvent:] + 622
    7   UIKitCore                           0x00007fff246db6c7 -[UIWindow sendEvent:] + 4774
    8   UIKitCore                           0x00007fff246b5466 -[UIApplication sendEvent:] + 633
    9   UIKitCore                           0x00007fff24745f04 __processEventQueue + 13895
    10  UIKitCore                           0x00007fff2473c877 __eventFetcherSourceCallback + 104
    11  CoreFoundation                      0x00007fff2039038a __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
    12  CoreFoundation                      0x00007fff20390282 __CFRunLoopDoSource0 + 180
    13  CoreFoundation                      0x00007fff2038f764 __CFRunLoopDoSources0 + 248
    14  CoreFoundation                      0x00007fff20389f2f __CFRunLoopRun + 878
    15  CoreFoundation                      0x00007fff203896d6 CFRunLoopRunSpecific + 567
    16  GraphicsServices                    0x00007fff2c257db3 GSEventRunModal + 139
    17  UIKitCore                           0x00007fff24696cf7 -[UIApplication _run] + 912
    18  UIKitCore                           0x00007fff2469bba8 UIApplicationMain + 101
    19  testlib                             0x000000010fb51002 main + 114
    20  libdyld.dylib                       0x00007fff2025a3e9 start + 1
)

利用LLDB查看具体报错代码在ViewController类中的详细信息

(lldb) image lookup -a 0x000000010fb507f5
      Address: testlib[0x00000001000017f5] (testlib.__TEXT.__text + 261)
      Summary: testlib`-[ViewController touchesBegan:withEvent:] + 197 at ViewController.m:14:5

可以看到ViewController.m中的第14行代码报错导致。

image lookup -n 符号或函数名:查找某个符号或函数的位置

(lldb) image lookup -n touchesBegan:withEvent:
1 match found in /Users/CC/Library/Developer/Xcode/DerivedData/testlib-dxolpnclkjwmjrgulkxqzmskrnlm/Build/Products/Debug-iphonesimulator/testlib.app/testlib:
        Address: testlib[0x0000000100001800] (testlib.__TEXT.__text + 64)
        Summary: testlib`-[ViewController touchesBegan:withEvent:] at ViewController.m:12
86 matches found in /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/PrivateFrameworks/UIKitCore.framework/UIKitCore:
        Address: UIKitCore[0x000000000002bec2] (UIKitCore.__TEXT.__text + 168786)
        Summary: UIKitCore`-[UIInterfaceActionGroupView touchesBegan:withEvent:]        Address: UIKitCore[0x000000000003280e] (UIKitCore.__TEXT.__text + 195742)

image list:列出所加载的模块信息

(lldb) image list
[  0] B6671BA2-2011-342C-8DD0-B99756A4416F 0x000000010be28000 /Users/CC/Library/Developer/Xcode/DerivedData/testlib-dxolpnclkjwmjrgulkxqzmskrnlm/Build/Products/Debug-iphonesimulator/testlib.app/testlib 
[  1] DEA51514-B4E8-3368-979B-89D0F8397ABC 0x000000011162d000 /usr/lib/dyld 

image list -o -f:打印所加载模块的偏移地址、全路径

(lldb) image list -o -f
[  0] 0x000000000be28000 /Users/CC/Library/Developer/Xcode/DerivedData/testlib-dxolpnclkjwmjrgulkxqzmskrnlm/Build/Products/Debug-iphonesimulator/testlib.app/testlib
[  1] 0x000000011162d000 /usr/lib/dyld

tips

敲Enter键会自动执行上一条指令

标签: 暂无
最后更新:2024/07/06

CC

这个人很懒,什么都没留下

点赞
< 上一篇
下一篇 >

文章评论

取消回复

COPYRIGHT © 2020 CC的博客. ALL RIGHTS RESERVED.

Theme Kratos

豫ICP备2023032048号