前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >lldb 入坑指北(2) -​ 15行代码搞定二进制与源码映射

lldb 入坑指北(2) -​ 15行代码搞定二进制与源码映射

作者头像
酷酷的哀殿
发布2021-03-18 09:47:48
1.1K0
发布2021-03-18 09:47:48
举报
文章被收录于专栏:酷酷的哀殿酷酷的哀殿

前言

随着项目的扩大,为了提高开发效率、编译速度,组件化(二进制化)是一种不可避免的趋势。大部分的公司都分享过相关文章,本文不再赘述。下面集中在二进制化带来的问题,以及相应的解决方案。

业界方案

二进制在带来便利的同时,也带来一些新问题:

  • 局部变量信息缺失
  • 断点调试成本增加
  • 汇编代码晦涩难懂

很多大厂都对此进行了研究,美团技术最近也做过一篇分享:美团 iOS 工程 zsource 命令背后的那些事儿

但是美中不足的是,文章中的解决方案存在以下问题:

  • 强依赖 pod 相关组件,通用性较差
  • 二进制组件编译路径需要保证相同
  • 需要切换到 iTerm 等工具执行命令,破坏开发体验

完美方案(头条同款)

为了解决以上问题,本文通过 lldb 提供的源码映射能力,实现了将任意的二进制文件映射到源码文件的通用方案。ps.如果读者了解 lldb + python ,阅读以下代码会更加简单。

~/.lldbinit (Xcode 启动时,会执行该脚本)位置创建文件,并添加代码(文件路径可以根据自身情况调整)

代码语言:javascript
复制
   command script import /Users/kukudeaidian/LLDB_MapFile.py

创建 /Users/kukudeaidian/LLDB_MapFile.py 文件(和 lldbinit 中的路径保持一致即可),并添加下面的代码:

代码语言:javascript
复制
#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','')
    # 通过 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')
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-02-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 酷酷的哀殿 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
    • 业界方案
      • 完美方案(头条同款)
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档