美文网首页iOS 开发 Objective-C
iOS 底层 day 09 tweak %log logify

iOS 底层 day 09 tweak %log logify

作者: 望穿秋水小作坊 | 来源:发表于2020-08-01 15:28 被阅读0次

一、%log 的使用

%log 是 logo 的日志语法,可以 tweak 项目的方法内部,可以帮我们打印出许多信息

  • 方法调用者的详细信息
  • 方法名字
  • 方法参数的详细信息

比如编写如下 hook 代码:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
  %log;
  %orig;
}

我们可以得到如下日志,非常详细:

-[<QQRecommendViewController: 0x1160c5c00> tableView:<UITableView: 0x1169cf600; frame = (0 0; 375 667); clipsToBounds = YES; autoresize = H; gestureRecognizers = <NSArray: 0x2829c2250>; layer = <CALayer: 0x28276dca0>; contentOffset: {0, -16}; contentSize: {375, 602.5}; adjustedContentInset: {64, 0, 49, 0}> didSelectRowAtIndexPath:<NSIndexPath: 0xc000000000a00116> {length = 2, path = 1 - 5}]

从上面的日志,我们可以获得许多信息:

  • 方法调用者的详细信息 QQRecommendViewController
  • 方法名字 tableView: didSelectRowAtIndexPath:
  • 方法参数的详细信息 UITableView NSIndexPath

基于上面的效果,我们有一个大胆的想法,如果我们把一个 '控制器' 里面的所有方法像上面,调用的时候,把详细日志打印出来,那么是不是我们就非常方法追踪我们需要的信息了呢?

二、logify.pl 的使用

基于我们对 %log 的猜想,logify.pl 这个工具已经帮我们实现了该功能。

logify.pl 会把我们指定 .h 文件里面的所有方法,包装打印日志,并且用 %orig 维持原有功能,生成一个 tweak 文件。

执行 logify.pl QQChatViewController.h > QQChatViewController.x 指令,生成 tweak 文件,QQChatViewController.x 部分内容如下:

%hook QQChatViewController
- (void)setNewestFeedRequestID:(long long )newestFeedRequestID { %log; %orig; }
- (long long )newestFeedRequestID { %log; long long  r = %orig; NSLog(@" = %lld", r); return r; }
%end

我们发送一条信息,就能得到如下调用链:

QQChatViewController 调用链

QQChatViewController.x 可能make会遇到的编译错误,我们一般做如下操作:

  1. 删掉 _weak
  2. 删掉 inout
  3. 删掉或者声明协议 @protocol xxxDelegate;
  4. 删掉 -(void).css_destruct{%log;%orig;}
  5. 声明缺失的类信息 @class xxPerson, xxCar;

三、动态调试

  1. 关于 GCC、GDB、LLVM、LLDB
  • Xcode 的编译器发展历程: GCC → LLVM
  • Xcode 的调试器发展历程: GDB → LLDB
  1. debugserver
  • debugserver 一开始存放在 Xcode 里面 /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSuppor/9.1
  • 当 Xcode 识别到手机设备时,Xcode 会自动将 debugserver 安装到 iPhone 上 /developer/usr/bin/debugserver
  • Xcode 动态调试局限性:一般情况下,只能调试通过 Xcode 安装的 App
  1. Xcode 调试 App 的原理


    Xcode 调试 App 的原理

四、如何让 LLDB 和 debugserver 能调试所有 APP

  1. 找到手机上 /Developer/usr/bin 目录下的 debugserver 可执行文件,导入 Mac 电脑中。
  2. 创建如下授权文件:debugserver.entitlements
<?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>run-unsigned-code</key> <true/>
    <key>get-task-allow</key> <true/>
    <key>task_for_pid-allow</key> <true/>
</dict> 
</plist>
  1. 执行 ldid -Sdebugserver.entitlements debugserver 指令,把权限重新签名给 debugserver。
  2. 将 debugserver 放入 iPhone 的 /usr/local/bin 目录下,并 chmod +x debugserver 赋予可执行文件(为什么不覆盖原来 iPhone 上的呢?第一不影响原来 Xcode 的调用,第二该目录不能全局执行,第三该目录是只读目录)
  3. 至此,iPhone 上的 debugserver 配置完毕,原本逻辑是要使用 Xcode 调用 LLDB 来操纵 debugserver 的,但是 Xcode 的弊端是只能调试 Xcode 自己运行的项目,所以我们现在要使用 Mac 终端来控制 LLDB。
Mac 终端来控制 LLDB
  1. iPhone 终端执行 debugserver 192.168.0.187:10011 -a QQ 指令,命令行进入等待 192.168.0.187 来链接的提示:
iPhone:/usr/local/bin root# debugserver 192.168.0.187:10011 -a QQ
debugserver-@(#)PROGRAM:LLDB  PROJECT:lldb-900.3.87
 for arm64.
Attaching to process QQ...
Listening to port 10011 for a connection from 192.168.0.187...
  1. iPhone 终端执行lldb 进入 lldb 模式:成功链接会如下显示
carrotdeMacBook-Pro:~ carrot__lsp$ lldb
(lldb) process connect connect://192.168.0.67:10011
Process 21025 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
    frame #0: 0x000000019632f0f4 libsystem_kernel.dylib`mach_msg_trap + 8
libsystem_kernel.dylib`mach_msg_trap:
->  0x19632f0f4 <+8>: ret    

libsystem_kernel.dylib`mach_msg_overwrite_trap:
    0x19632f0f8 <+0>: mov    x16, #-0x20
    0x19632f0fc <+4>: svc    #0x80
    0x19632f100 <+8>: ret    
Target 0: (QQ) stopped.
(lldb)  

此时,debug 的应用程序会进入断点模式,会卡住。出入 c 回车,即继续。

五、debugserver 和 LLDB 链接可能遇到的问题

  1. debugserver 一输入监听指令,就退出:
iPhone:~ root# debugserver *:10011 -a ting
debugserver-@(#)PROGRAM:LLDB  PROJECT:lldb-900.3.87
 for arm64.
Attaching to process ting...
Listening to port 10011 for a connection from 127.0.01...
Failed to get connection from a remote gdb process.
Exiting.

解决方案:

  • debugserver *:10011 -a ting 不要填写 * 号,直接用 Mac 地址代替。
  • 授权有问题,请使用上面第四点给的授权文件给 debugserver 授权
  • 可能 usbmux 模式有问题,直接用 WiFi 模式链接。

相关文章

网友评论

    本文标题:iOS 底层 day 09 tweak %log logify

    本文链接:https://www.haomeiwen.com/subject/vtuyrktx.html