原文出自【听云技术博客】:http://blog.tingyun.com/web/article/detail/1342
序言
怎么在linux 平台下实现一个类似于mac 平台下的 atos 工具( iOS 符号化解析)?
分析问题
在github上找到了几年前的开源实现,[https://github.com/dechaoqiu/atosl](https://github.com/dechaoqiu/atosl)
编译出来的atosl工具平常很大几率是工作正常的,只有在特殊情况下会出现解析错误,主要表现为以下方式:
1、使用Swift 编写的app ,编译出来的 atosl 一定会解析错误(乱码形式)
2、使用C+ + 实现的一些函数,编译出来的 atosl 解析出来的字符串也是乱码
3、在解析 iOS 系统framwork 框架的时候 有几率会出现解析错误(乱码形式)
4、用户的某些崩溃信息不能定位到具体的 line no,编译出来的 atosl服务只能解析出来offset。
iOS dSYM 文件结构剖析
在 iOS App 开发过程中,我们会利用Xcode打包,生成.xarchive的包文件,通过Xcode 的Organizer 工具可以管理并导出发布文件,iOS 开发者对这些过程都是轻车熟路,这里不再重复阐述,主要想讲的是,打包之后生成的dSYM 文件。
dSYM 是一个目录,打开之后,我们会找到一个二进制文件如下图
可以看出iOS 使用的是DWARF文件结构 (Debug With Attributed RecordFormats) 是一种调试文件结构标准,结构相当复杂。
[https://www.prevanders.net/dwarf.html](https://www.prevanders.net/dwarf.html)
dSYM 文件的一个重要作用就在于,当我们的程序发生崩溃,通过crash log 或其他方式 ,会看到调用栈信息。 通过log信息,我们并不知道具体是在哪一个文件的哪一个位置出了问题, 这个时候这个二进制文件提供的信息就非常有用了,通过它我们可以通过工具 去符号化, Mac OS X 平台下 Xcode 自带了 atos 这样的工具,这样可以直接定位到某个文件的具体位置。 用法如下:
在 Mac OS 下有 dwarfdump 工具来解析DWARF文件,很显然解析出来的信息并不能满足我们的所有需求。
dwarfdump -a SwfitTest
如果要了解其内部结构,请参考《iOS系统分析(二)Mach-O二进制文件解析》。
思路
github 下载 atosl 源代码,C写的
添加Cxx 与 Swift的错误样例
make test 结果如下,很明显 Cxx 与 Swift 符号化有问题,这就是我要解决的问题。
返回到mac os x中利用xcode 提供的 xcrun atos 处理,能够正确解析,(所以我要做的事情就是在linux平台下实现一个 类似于mac os x 平台下的 atos -\>输入输出相同)
解决C+ + 乱码的思考过程,在前面学习分析 Mach-O 文件的时候 使用过一个 MachOView 工具,然后我用工具打开QuartzCore 这个dSYM 文件,发现在 SymTables 里面解析出来的 字符串也是乱码,但是神奇的事情发生了,当我鼠标停留在某一行乱码的时候 复出了正确的解析字符串,这说明 MachOView 是能够正确解析C + + 名字的。果断 github 搜源代码. 从这里知道了 编译器在编译过程中会对函数做一些手脚,下面分析编译器的行为。
mangled symbol names (重整符号名称)
C/Cxx
在C这样的语言中,任何给定的名字(符号)只能对应唯一的一个函数或数据,不需要名字重整(name mangling)。即便如此,如果你看一个典型的纯C二进制的符号表,你会发现每个函数名有一个 (下划线)的前缀,如下:
这种简单的“mangling”(重整)已有很长的历史,实际上没有多少用处,但仍为兼容性和一致性起到一些效果。按照惯例,C中定义的名字会有下划线,而纯汇编定义的全局符号则没有(尽管许多汇编语言的作者为了一致性,也会预先考虑下划线的定义)。
Objective-C
它的符号名字不会有异议或者说冲突;Objective-C的方法实现的形式是: -[class selector](#),并且objective - c不允许相同的类使用不同的参数来重载相同的selectors。
Cxx
一个没有额外信息的简单的名字可能会产生异议,所以必须做一些处理, 如下:
因为function对应两个包含不同参数的函数,这在cxx中是合法的定义,所以我们不能简单地生成两个\_ function符号,因为链接器会不知道如何链接,无法区分不同的函数实现。因此,cxx编译器使用一组严格的编码规则“mangles”(重整)了符号。
Swift
1. 最开始的字符’-‘对Swift符号是必须的
2. ‘-T’是Swift全局符号的标记
解决方法
按照这个规则自己去还原符号也是可行的,不过还是比较费时,还可能有bug。
幸好Xcode 自带了个工具, 可以查看这些 mangled name 的本来面目,就不需要自己重新去实现.
解决思路过程
既然apple 提供了工具,那么我就不需要去自己写了,直接调用即可,在xcode的目录中找到了工具地址如下:
第一种解决方法 :管道通信 atosl 直接调用 swift-demangle 。
第二种解决方法 : 将swift-demangle.dylib 链接到程序中。
正确解析。接下来要想办法将这个小程序移植到Linux 平台下。
我猜这是Swift提供的工具,Google 发现Swift是源代码级别开源,果然支持Linux。
在linux上编译 Swift
配置环境编译之(Ubuntu 14.04),编译过程中有坑(内存必须配置5GB以上,硬盘30GB 以上)
warning:如果你遇到类似 clang: error: unable to execute command: Killed 的报错,不要多想,就是内存爆了,多试几次也许就成功了。
如果一切正常1小时就能编译完毕(我的硬件环境 MacBookAir 1.4GHz CPU 8GB 内存 固态硬盘,用了将近1个小时)。
第一种解决方案:swift编译完成后 在build/xxx/xxx/xxx/bin 下果然有ELF这个可执行文件
第二种解决方案: 使用编译出来的库文件
在lib目录下 没有找到 .so动态库,纳闷很久(swift的 编译脚本使用的是Cmake) Darwin 这个术语是指 mac 系统内核核心 (包括 xnu kernel 与 Unix Shell 环境),注释掉这里就可以将(Linux 共享库) .so 编译出来,如果要编译静态库 则需要修改cmake脚本,如下图:
共享库编译出来了,则直接动态链接到 atosl中,swift 只能在Ubutun上编译,如果最终你的atosl 要在 Linux的其他发行版上运行,最好将所有的依赖库用静态链接。
2
make test
测试发现 cxx 与Swift的测试样例 的 offset(定位到的 line no 解析不出来),github上的代码已经很久没有人维护了,最后还是果断重写之。
end
(有任何问题请联系 email:liutianshxkernel@gmail.com)
相关推荐
《网络编程与分层协议设计基于Linux平台实现》.(刘飚).[PDF]
以下是对“网络编程与分层协议设计基于Linux平台实现”这一主题的详细解析。 首先,网络编程涉及的主要知识点包括套接字编程、TCP/IP协议族以及并发处理。套接字是网络编程的基本接口,通过创建、绑定、监听和接受...
在Linux平台上用多线程方法实现浮点向量的点积计算: 点积规则可以自己定,程序中采用的是ai=bi=-1/1/0(按3取余运算),另外,计算程序运行时间. 输入格式为: vec_mul thread_num N 参数: thread_num:线程数,从1到...
"在嵌入式Linux中实现TFTP Server" 本文档主要讨论了在嵌入式Linux中实现TFTP Server的方法和过程。TFTP(Trivial File Transfer Protocol)是一种简单的文件传输协议,常用于网络产品的软件或配置在线更新。在...
IPSec 在 Linux 平台上的实现框架 本文提出了一种在 Linux 平台上实现 IPSec 的框架,详细介绍了安全策略数据库 (SPD) 和安全关联数据库 (SAD) 的记录结构,分析了 Linux 的网络 IP 层代码,並給出了 IPSec 的原型...
"Linux 操作系统在 Windows 平台上运行的仿真系统研究的实现方法" 本文主要解决在 Windows 平台上实现 Linux 操作系统仿真运行的方法。该系统具有交互操作的功能,即使在没有 Linux 操作系统环境的情况下也能实现 ...
在Linux平台上实现DCS(分布式控制系统)画面的显示是一项技术挑战,主要涉及到操作系统、系统开发以及与DCS系统的集成。本文将深入探讨如何在Linux环境下,利用特定的技术和工具来展示DCS的画面。 首先,DCS是一种...
本科操作系统实验代码,使用多线程编程实现浮点向量的点积计算。
MiniGUI图形库在嵌入式Linux平台上的移植与实现 MiniGUI图形库是嵌入式Linux平台上的一种常用的图形库,具有良好的软件架构和可移植性。它能够提供对图形的支持,保证应用程序的顺利编译和实现。 1. MiniGUI的...
实验内容:在linux平台上实现1个TCP并发服务器,至少可以为10个客户端同时提供服务。 2. 进程间的协调通信(4学时) 掌握进程的概念、进程间通信的基本原理、集成间通信的主要类型和各自的特点。实验内容:在linux平台...
实验课linux下实现文件复制
在Linux平台上,使用C语言实现一个简单的HTTP服务器是一项基础但重要的技能,这涉及到网络编程、多线程处理以及文件操作等多个领域。以下是一些相关的知识点: 1. **TCP/IP协议与HTTP协议**: - TCP(传输控制协议...
"JavaWeb应用在ARMLinux平台上的实现" 本文主要讨论了在ARMLinux平台上实现JavaWeb应用的详细过程。首先,作者们完成了Java虚拟机JAMVM、Java Web容器Winstone和嵌入式数据库Sqhte的移植配置,并成功地在ARMLinux...
在实现身份证阅读器的USB驱动时,我们需要使用Linux平台提供的USB驱动框架,包括usb_register()函数、usb_deregister()函数和usb_set_intfdata()函数。其中,usb_register()函数用于注册USB设备,usb_deregister()...
开发者在实现XORFS时,需要将这些接口映射到XORFS的具体实现上,例如,如何在XORFS的数据结构中查找文件,如何分配和释放磁盘空间,以及如何处理文件的读写请求。 在`xorfs.c`中,开发者可能需要定义自己的超级块...
在实现过程中,服务器端需处理并发连接,确保同时连接的多个客户端能够稳定运行。这通常通过多线程或异步IO模型来实现,如Linux的epoll机制。客户端则主要负责用户界面的交互,提供友好且高效的图形用户界面(GUI)...
《实验物理和工业控制系统在Linux平台上的实现》这篇文章主要探讨了如何在Linux操作系统上构建实验物理和工业控制系统的实现方案。Linux作为一种开放源代码、免费的操作系统,已经被广泛应用于各个领域,包括工业...
在Linux环境下,使用C语言实现HTTPS(HTTP over SSL/TLS)请求是一项常见的任务,尤其对于系统编程和网络编程的学习者来说。HTTPS协议提供了安全的数据传输,确保了客户端和服务器之间的通信不被中间人攻击。本篇...
标题“rpmsg在Linux和Zephyr中的实现”指向了本文的中心议题——探讨rpmsg(Remote Processor Messaging)通信协议在Linux操作系统和Zephyr实时操作系统(RTOS)中的实现方式和应用。rpmsg是嵌入式系统中实现不同...
概述:在Linux平台下基于MPI的并行PC集群搭建的实现是高性能计算领域中的热点问题。该文主要介绍了基于Linux平台下的MPI并行PC集群搭建的实现,着重于介绍了集群系统和MPI的特点,并对基于Linux平台下的MPI并行PC...