zoukankan      html  css  js  c++  java
  • 在linux平台实现atosl

    更多技术干货请戳:听云博客

    序言

    怎么在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)

     原文链接:http://blog.tingyun.com/web/article/detail/1342

  • 相关阅读:
    SqlServer 查看数据库中所有存储过程
    SqlServer 查看数据库中所有视图
    SqlServer 查询表的详细信息
    SqlServer 遍历修改字段长度
    net core 操作Redis
    Tuning SharePoint Workflow Engine
    Open With Explorer
    Download language packs for SharePoint 2013
    Change Maximum Size For SharePoint List Template when Saving
    Six ways to store settings in SharePoint
  • 原文地址:https://www.cnblogs.com/TingyunAPM/p/6075219.html
Copyright © 2011-2022 走看看