一、背景

在iOS开发中,我们经常会遇到各种各样的线上问题,为了能够定位线上问题发生位置,我们搭建了各种各样收集信息的框架,当线上发生问题时,会收集到发生问题的方法调用栈信息,这些信息可以帮助我们来解决相关问题。

无论是我们自己搭建的框架还是直接使用各种第三方收集框架,我们拿到的方法栈调用信息通常都是一些符号,为了能够从这些符号中获取正确的方法名,我们需要在线上包对应的dSYM文件帮助下进行符号化,进而得到明确的方法名。

对于如何使用dSYM文件来解析符号,网上已经有了很多质量很好的教程,推荐其中一个教程。

对于目前已有的符号化方法,无论是 symbolicatecrash还是 atos,均需要配置 Xcode环境,对于没有 XcodeMacOS环境的机器来说,符号化就变得毫无希望。

今天就来介绍一种无需特殊 XcodeMacOS环境即可解析iOS符号的方法。

二、前期准备

1. dSYM文件

为了解析符号,我们还是需要准备好对应的 dSYM文件,毕竟 dSYM文件中存储着程序中的符号信息。

2. dump_syms工具

dump_syms工具是谷歌 Breakpad项目中提供的一个工具,该工具可以将读取 dSYM文件中的符号信息,并将这些信息导出为文本文件。

dump_syms工具获取流程如下:

  1. 前往 https://github.com/google/breakpad 下载源码
  2. 进入 src/tools目录
  3. 根据平台进入对应目录
  4. 进入 dump_syms 目录,根据对应方法进行源码编译,生成 dump_syms 工具

3. 导出.sym文件

使用 dump_syms工具导出 dSYM文件中符号信息,命令如下: dump_syms [-a ARCHITECTURE] [dSYM path] > [output path],例如 dump_syms -a arm64 /Users/mademao/Desktop/SymbolDemo.app.dSYM/ > /Users/mademao/Desktop/arm64.sym

三、解析符号

对于如何解析符号,这里只介绍解析原理,具体可实现一个跨平台脚本,使用脚本来进行跨平台iOS符号解析。

1. .sym文件结构介绍

在上述步骤中导出的 .sym文件结构如下:

MODULE mac arm64 F14BC1FA245E3F84801872FB087F8FFA0 SymbolDemo
FILE 0 /Users/mademao/Desktop/SymbolDemo/SymbolDemo/AppDelegate.m
FILE 1 /Users/mademao/Desktop/SymbolDemo/SymbolDemo/SceneDelegate.h
FILE 2 /Users/mademao/Desktop/SymbolDemo/SymbolDemo/SceneDelegate.m
FILE 3 /Users/mademao/Desktop/SymbolDemo/SymbolDemo/ViewController.m
FILE 4 /Users/mademao/Desktop/SymbolDemo/SymbolDemo/main.m
FUNC 5f90 4c 0 -[ViewController viewDidLoad]
5f90 24 17 3
5fb4 1c 18 3
5fd0 c 20 3
FUNC 5fdc 88 0 -[AppDelegate application:didFinishLaunchingWithOptions:]
5fdc 4c 18 0
6028 3c 21 0
FUNC 6064 108 0 -[AppDelegate application:configurationForConnectingSceneSession:options:]
6064 74 27 0
60d8 c 30 0
60e4 4 30 0
60e8 1c 30 0
6104 2c 30 0
6130 10 30 0
6140 2c 31 0
FUNC 616c 80 0 -[AppDelegate application:didDiscardSceneSessions:]
616c 4c 34 0
61b8 34 38 0
FUNC 61ec a0 0 main
61ec 18 12 4
6204 8 13 4
620c c 14 4
6218 10 16 4
6228 4 16 4
622c 1c 16 4
6248 4 17 4
624c 4 18 4
6250 4 18 4
6254 4 18 4
6258 c 18 4
6264 4 18 4
6268 24 19 4
FUNC 628c b4 0 -[SceneDelegate scene:willConnectToSession:options:]
628c 6c 18 2
62f8 48 22 2
FUNC 6340 4c 0 -[SceneDelegate sceneDidDisconnect:]
6340 2c 25 2
636c 20 30 2
FUNC 638c 4c 0 -[SceneDelegate sceneDidBecomeActive:]
638c 2c 33 2
63b8 20 36 2
FUNC 63d8 4c 0 -[SceneDelegate sceneWillResignActive:]
63d8 2c 39 2
6404 20 42 2
FUNC 6424 4c 0 -[SceneDelegate sceneWillEnterForeground:]
6424 2c 45 2
6450 20 48 2
FUNC 6470 4c 0 -[SceneDelegate sceneDidEnterBackground:]
6470 2c 51 2
649c 20 55 2
FUNC 64bc 2c 0 -[SceneDelegate window]
64bc 14 13 1
64d0 18 13 1
FUNC 64e8 48 0 -[SceneDelegate setWindow:]
64e8 20 13 1
6508 1c 0 1
6524 c 13 1
FUNC 6530 44 0 -[SceneDelegate .cxx_destruct]
6530 1c 15 2
654c 28 15 2
PUBLIC 0 0 _mh_execute_header
PUBLIC 8028 0 OBJC_LABEL_CLASS_$
PUBLIC 8030 0 OBJC_LABEL_CLASS_$
PUBLIC 8038 0 OBJC_LABEL_CLASS_$
PUBLIC 8040 0 _OBJC_LABEL_PROTOCOL_$_NSObject
PUBLIC 8048 0 _OBJC_LABEL_PROTOCOL_$_UIApplicationDelegate
PUBLIC 8050 0 _OBJC_LABEL_PROTOCOL_$_UISceneDelegate
PUBLIC 8058 0 _OBJC_LABEL_PROTOCOL_$_UIWindowSceneDelegate
PUBLIC c060 0 _OBJC_METACLASS_RO_$_ViewController
PUBLIC c0a8 0 _OBJC_$_INSTANCE_METHODS_ViewController
PUBLIC c0c8 0 _OBJC_CLASS_RO_$_ViewController
PUBLIC c110 0 _OBJC_$_PROTOCOL_INSTANCE_METHODS_NSObject
PUBLIC c2e0 0 _OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_NSObject
PUBLIC c300 0 _OBJC_$_PROP_LIST_NSObject
PUBLIC c348 0 _OBJC_$_PROTOCOL_METHOD_TYPES_NSObject
PUBLIC c3e8 0 _OBJC_$_PROTOCOL_REFS_UIApplicationDelegate
PUBLIC c400 0 _OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_UIApplicationDelegate
PUBLIC c900 0 _OBJC_$_PROP_LIST_UIApplicationDelegate
PUBLIC c918 0 _OBJC_$_PROTOCOL_METHOD_TYPES_UIApplicationDelegate
PUBLIC cac0 0 _OBJC_CLASS_PROTOCOLS_$_AppDelegate
PUBLIC cad8 0 _OBJC_METACLASS_RO_$_AppDelegate
PUBLIC cb20 0 _OBJC_$_INSTANCE_METHODS_AppDelegate
PUBLIC cb70 0 _OBJC_$_PROP_LIST_AppDelegate
PUBLIC cbc8 0 _OBJC_CLASS_RO_$_AppDelegate
PUBLIC cc10 0 _OBJC_$_PROTOCOL_INSTANCE_METHODS_NSObject
PUBLIC cde0 0 _OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_NSObject
PUBLIC ce00 0 _OBJC_$_PROP_LIST_NSObject
PUBLIC ce48 0 _OBJC_$_PROTOCOL_METHOD_TYPES_NSObject
PUBLIC cee8 0 _OBJC_$_PROTOCOL_REFS_UISceneDelegate
PUBLIC cf00 0 _OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_UISceneDelegate
PUBLIC d028 0 _OBJC_$_PROTOCOL_METHOD_TYPES_UISceneDelegate
PUBLIC d088 0 _OBJC_$_PROTOCOL_REFS_UIWindowSceneDelegate
PUBLIC d0a0 0 _OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_UIWindowSceneDelegate
PUBLIC d120 0 _OBJC_$_PROP_LIST_UIWindowSceneDelegate
PUBLIC d138 0 _OBJC_$_PROTOCOL_METHOD_TYPES_UIWindowSceneDelegate
PUBLIC d160 0 _OBJC_CLASS_PROTOCOLS_$_SceneDelegate
PUBLIC d178 0 _OBJC_METACLASS_RO_$_SceneDelegate
PUBLIC d1c0 0 _OBJC_$_INSTANCE_METHODS_SceneDelegate
PUBLIC d2a0 0 _OBJC_$_INSTANCE_VARIABLES_SceneDelegate
PUBLIC d2c8 0 _OBJC_$_PROP_LIST_SceneDelegate
PUBLIC d320 0 _OBJC_CLASS_RO_$_SceneDelegate
PUBLIC d390 0 OBJC_CLASSLIST_SUP_REFS_$_
PUBLIC d398 0 OBJC_IVAR_$_SceneDelegate._window
PUBLIC d3a0 0 OBJC_CLASS_$_ViewController
PUBLIC d3c8 0 OBJC_METACLASS_$_ViewController
PUBLIC d3f0 0 OBJC_METACLASS_$_AppDelegate
PUBLIC d418 0 OBJC_CLASS_$_AppDelegate
PUBLIC d440 0 OBJC_METACLASS_$_SceneDelegate
PUBLIC d468 0 OBJC_CLASS_$_SceneDelegate
PUBLIC d490 0 _dyld_private
PUBLIC d498 0 _OBJC_PROTOCOL_$_NSObject
PUBLIC d4f8 0 _OBJC_PROTOCOL_$_UIApplicationDelegate
PUBLIC d558 0 _OBJC_PROTOCOL_$_UISceneDelegate
PUBLIC d5b8 0 _OBJC_PROTOCOL_$_UIWindowSceneDelegate

该文件以行为单位,每一行记录一条信息,其中记录格式分为以下5种:

(1) MODULE标识行

MODULE标识行在整个.sym文件中只有一行,且位于第一行。

该行记录提供有关符号文件描述的模块的元信息。它具有以下形式:

MODULE 操作系统 架构 ID 可执行文件或库的基础名称

(2) FILE标识行

FILE标识行在整个.sym文件中包含多行,且位于MODULE标识行之后。

每一行FILE标识行记录了一个源文件路径。它具有以下形式:

FILE 编号 源文件路径

其中编号从0开始递增。

(3) FUNC标识行

FUNC标识行在整个.sym文件中包含多行。

该行用来描述源语言方法。它具有以下形式:

FUNC 地址 大小 参数尺寸 名称

  • 地址表示该方法的起始偏移位置的十六进制;
  • 大小表示该方法对应机器指令占用的长度的十六进制;
  • 参数尺寸表示方法需要在堆栈上参数占用大小的十六进制,iOS方法该值均为0;
  • 名称表示该方法名称;
(4) 无标识行

该类型行在某个FUNC标识行下存在,同时每个FUNC标识行下可能有多个该类型标识行。

每一行表示在机器指令下所属FUNC指定方法所属的文件下标及行号。它具有以下形式:

地址 大小 行号 文件下标

  • 地址表示该机器代码起始偏移位置的十六进制;
  • 大小表示该机器代码占用的长度的十六进制;
  • 行号表示该机器代码在文件中的行号;
  • 文件下标表示该机器代码所在文件的下标,该下标对应FILE标识行中编号;
(5) PUBLIC标识行

PUBLIC标识行在.sym文件中包含多行,且位于所有FUNC及无标识行之后。

每一行PUBLIC标识行记录了一个公共可见的链接符号,可包括类名信息、公共变量名等,其中有偏移地址但行号数据不确定的函数也会指定为PUBLIC标识行。它具有以下形式:

PUBLIC 地址 参数尺寸 名称

此处我们仅对指定为PUBLIC的函数做介绍:

  • 地址表示该机器代码其实偏移位置的十六进制;
  • 名称表示该函数名称;

以上就是整个.sym文件所包含的信息,其中不难看到对于程序方法来说,他的偏移位置等及所处文件均有信息记录。

2. 解析iOS符号思路

对于获取到的iOS符号,格式通常为如下所示:

5 SymbolDemo 0x00000001000d5fb4 0x1000d0000 + 24501

对于以上信息,SymbolDemo表示指令所在镜像的bundle,0x00000001000d5fb4表示程序运行时指令位置偏移量,0x1000d0000表示指令所在镜像通过 ASLR随机出来的偏移量,245001表示指令在镜像中的真正偏移量。

以上符号的解析过程如下:

  • 通过bunlde为 SymbolDemo得到对应的.sym文件
  • 通过偏移量 245001找到.sym中对应的FUNC或PUBLIC,即 FUNC 5f90 4c 0 -[ViewController viewDidLoad]行,原因为 5f90 < 245001 < 5f90 + 4c,从而确定该指令所属方法为 -[ViewController viewDidLoad]
  • 通过 245000得到具体的无标识行,即 5fb4 1c 18 3,原因为 5fb4 < 245001 < 5fb4 + 1c,从而确定该指令在文件中行号为18,文件下标为3
  • 通过文件下标3得到所属文件为 ViewController.m
  • 最终得到符号化后的信息为 -[ViewController viewDidLoad] (ViewController.m:18)

以上即是通过.sym文件解析iOS符号的原理及流程,对应的可实现一个可跨平台的脚本,即可完成不受XcodeMacOS限制的iOS解析工具。

利用.sym跨平台解析iOS符号相关推荐

  1. 解析IOS控制台利用GDB命令查看报错堆栈

    解析IOS控制台利用GDB命令查看报错堆栈是本文要介绍的内容,在ios开发中,如果提前释放一个指针的内存,在以后还继续使用这个指针,那么程序会立刻crash掉,而且很难有报错信息,我以前都是靠猜测去判 ...

  2. 利用反汇编手段解析C语言函数

    利用反汇编手段解析C语言函数 通过在 Visual C++6.0 下反汇编一个 32 位 C语言程序的部分代码来解析解释函数调用的具体过程. 函数调用过程 函数调用过程主要由参数传递.地址跳转.局部变 ...

  3. 私有云方案——利用阿里云云解析实现DDNS

    各位都是程序员,工作中是不是遇到个类似情况.在家里研究的一些开源代码或写的一些demo或试验代码,在工作中正好需要参考一下,但是在家里的电脑上. 虽然这些都可以用云盘/网盘之类的来完成,源代码也可以托 ...

  4. 如何利用Pre.im分发iOS测试包

    大众创新万众创业,在移动互联网的风口,移动APP开发与测试发展方兴未艾,受到了越来越多的重视.相较 iOS,Android 的开发环境更加开放.Android 开发者要测试应用时,只需发个 APK 安 ...

  5. 利用tftp服务器进行IOS备份升级

    利用tftp服务器进行IOS备份升级 准备工作: 1.配置线.网线(pc和路由器使用交叉线,PC和交换机使用直连线) 2.准备模拟TFTP Server的软件 3.准备升级的IOS,一定注意和设备型号 ...

  6. 华为表哥手把手教你利用Jenkins持续集成iOS项目,教不会我花式拉翔!!!

    手把手教你利用Jenkins持续集成iOS项目: 前言 众所周知,现在App的竞争已经到了用户体验为王,质量为上的白热化阶段.用户们都是很挑剔的.如果一个公司的推广团队好不容易砸了重金推广了一个APP ...

  7. matlab sym t,matlab的符号变量sym,syms-Go语言中文社区

    sym与syms 区别1:如果定义变量x,syms x:当用sym生成多个符号变量时,MATLAB要报错 syms函数的功能比sym函数更为强大,它可以一次创建任意多个符号变量.而且,syms函数的使 ...

  8. 【Java 解析全国地址】Java 利用正则表达式完美解析全国省市区地址

    Java 利用正则表达式完美解析全国省市区地址 一.问题场景描述 最近在项目中遇到了一个全国地址解析的一个场景,前端会传来一个字符串,后端需自动解析出 xx省xx市xx区+详细地址 的这种格式. 因为 ...

  9. 【python脚本系列】利用mido库解析midi文件

    [python脚本系列]利用mido库解析midi文件       Hallo大家好~~我是Lampard猿奋       昨天写了关于Midi数字化乐器接口的文章,介绍了midi是一组代表音乐参数( ...

  10. 无法找到CCTV直播MP4地址?七十行代码,简单使用FFplay直接观看还是下载CCTV栏目都轻松搞定(Python利用FLVCD硕鼠解析CCTV直播,FFplay播放并下载视频)

    我们在每天使用新闻的时候大都会以CCTV发布的新闻为准,我们的每天新闻收视率最高的还是我们的总台,大家闲来无事可能也会看一下央视网提供视频直播吧,看看还可以,但是我们可以发现我们完全解析不了,大家看一 ...

最新文章

  1. RTX 3090的深度学习环境配置指南:Pytorch、TensorFlow、Keras
  2. Nature封面,硅量子计算达到99%的准确率
  3. Qt的4个图像类QImage/QPixmap/QBitmap/QPicture 转
  4. 深度学习cnn人脸检测_用于对象检测的深度学习方法:解释了R-CNN
  5. 4本数据库新书,大神都在追着看
  6. 扭曲效果 效率优化 GrapPass,CommandBuffer对比
  7. iOS 5与iOS 6的 low-memory 处理
  8. AcWing 4247. 糖果(差分约束最短路)
  9. nginx+php+mysql环境
  10. C# Revit二次开发
  11. 【程序设计入门-C语言】翁凯——初学者视角1
  12. matlab保存tif图片
  13. 塑料齿轮模具设计指南
  14. 禅与摩托车维修艺术 摘选
  15. 电路基础(3)电阻电路等效变换的经典例题
  16. 微信小程序云开发支付
  17. idea使用账号不能登录
  18. vue使用element-ui的el-date-picker设置样式无效
  19. 用U盘给服务器做系统用在pe里分区吗,如何用U盘装系统并给硬盘分区
  20. 使用位运算实现乘法和乘方运算

热门文章

  1. Python操作wifi进行数据传输
  2. python中render是什么意思_Django中render_to_response和render的区别(转载)
  3. 刚申请的博客,就发一个老师让做的“一分钟打动面试官”作业做为纪念吧!!!...
  4. 爬取分析拉勾网招聘信息
  5. Lvgl7 基础对象(lv_obj)
  6. 视频转mp4格式转换器如何把其他格式的视频转换成mp4格式
  7. 微信端input输入框在ios手机上连续输入卡顿
  8. oracle 按天数统计数据
  9. AR涂涂乐⭐六、 UGUI精灵格式、自动延迟截图、优化“4”、移出扫描框终止截图进程
  10. 国际商业分析师CBAP认证与PMI-PBA认证的区别——上海信息化培训中心