lldb 入坑指北(2)- 15行代码搞定二进制与源码映射
时间:2022-07-28
本文章向大家介绍lldb 入坑指北(2)- 15行代码搞定二进制与源码映射,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
01
—
随着项目的扩大,为了提高开发效率、编译速度,组件化(二进制化)是一种不可避免的趋势。
大部分的公司都分享过相关文章,本文不再赘述。下面集中在二进制化带来的问题,以及相应的解决方案。
02
—
二进制在带来便利的同时,也带来一些新问题:
1、局部变量信息缺失
2、断点调试成本增加
3、汇编代码晦涩难懂
很多大厂都对此进行了研究,美团技术最近也做过一篇分享:
但是美中不足的是,文章中的解决方案存在以下问题:
- 强依赖 pod 相关组件,通用性较差
- 二进制组件编译路径需要保证相同
- 需要切换到 iTerm 等工具执行命令,破坏开发体验
03
—
为了解决以上问题,本文通过 lldb 提供的源码映射能力,实现了将任意的二进制文件映射到源码文件的通用方案。
ps.如果读者了解 lldb + python ,阅读以下代码会更加简单。
在 ~/.lldbinit (Xcode 启动时,会执行该脚本,所以新手请务必先关闭 Xcode 再进行操作)位置创建文件,并添加代码(文件路径可以根据自身情况调整)
command script import /Users/kukudeaidian/LLDB_MapFile.py
创建 /Users/kukudeaidian/LLDB_MapFile.py 文件,并添加下面的代码:
#encoding=utf-8
import lldb
import re
import os
# command 是用户输入的符号地址
def sun_map_address(debugger, command, result, internal_dict):
print(command)
# 获取 lldb 的命令交互环境,可以动态执行一些命令,比如 po obj
interpreter = lldb.debugger.GetCommandInterpreter()
# 创建一个对象,命令执行结果会通过该对象保存
returnObject = lldb.SBCommandReturnObject()
# 通过 image loopup 命令查找输入符号地址所在的编译模块信息
interpreter.HandleCommand('image lookup -v --address ' + command, returnObject)
# 获取返回结果
output = returnObject.GetOutput();
# 下面的代码设计思想是:
# 1、根据{地址}查找该地址所属的{源码编译路径}+{编译文件名}
# 2、通过{编译文件名}动态在{指定路径}查找相应的{源码路径}
# 3、将{源码编译路径}与{源码路径}映射
# 实际使用时,可以参考下面的方案。
# 1、根据{地址}查找该地址所属的{编译模块}。比如,SDWebImage
# 2、通过脚本动态下载{编译模块}的{源码仓库}
# 3、将{编译模块}与{源码仓库}映射
# 通过正则获取二进制编译时,源码的真正路径
filePath = re.match(r'(.|n)*file = "(.*?)".*', output,re.M).group(2)
# 通过真正路径获取编译源文件的文件名
fileName = re.match(r'/.*/(.*)', filePath).group(1)
# 通过文件名在 ~/MMAViewabilitySDK_iOS 目录(可以是任意的地址或者通过 git clone 动态下载)下查找源文件
sourcePath = os.popen('mdfind -onlyin ~/MMAViewabilitySDK_iOS '+fileName).read().replace('n','')
# 通过 lldb 提供的 settings set target.source-map 命令执行编译源码位置与当前源码位置的映射
interpreter.HandleCommand('settings set target.source-map ' + filePath + ' ' + sourcePath, returnObject)
# 添加一个 扩展命令。sun_map_address
# 在 lldb 输入 sun_map_address 0x10803839 时,会执行 lldb_MapFile.py 文件的 sun_map_address 方法
def __lldb_init_module(debugger, internal_dict):
debugger.HandleCommand('command script add sun_map_address -f lldb_MapFile.sun_map_address')
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法