Xcode如何找到FrameWork对应的源码的

背景描述:

在cocpoads管理下自研库和第三方的开源库可以使用frameWork的方式集成到主工程中,在我们编译过程中,只要不改动pod下集成的库代码,第一次编译后,第三方库会编译成frameWork,通过Xcode 的 buildSetting 的 framework search Path 记录所有生成的framework地址,在项目的编译后期去link这些framework 。在没有修改pod子工程的库文件前提下,之后的每一次build都直接link缓存中编译过的framework文件。但是当文件编译成framework,成为了可执行的二进制文件,我们却任然可以借助Xcode做源码调试。那么Xcode工具是如何通过一个二进制文件执行时找到它对应的源码文件的?

鉴于上个问题,我们可以先看看Xcode的编译过程

Xcode作为一个GUI工具,实际上是通过调用一系列的命令行工具,将命令行工具处理的结果汇总输出。Xcode 使用clang编译器进行编译 会使用一系列 xcrun clang 的命令来编译文件,xcrun是用来定位clang工具位置的

接着看编译过程中都经历了些什么?
大致过程如下:

1.文件预处理

符号化 (Tokenization)
宏定义的展开
include 的展开

2.语法语义分析

将符号化后的内容转化为一棵解析树 (parse tree)
解析树做语义分析
输出一棵抽象语法树(Abstract Syntax Tree* (AST))

3.代码生成和优化

将 AST 转换为更低级的中间码 (LLVM IR)
对生成的中间码做优化
生成特定目标代码
输出汇编代码

4.汇编器

将汇编代码转换为目标对象文件。

5.link文件

将多个目标对象文件合并为一个可执行文件 (或者一个动态库)

整个过程比较复杂,特别是语义分析,和代码优化过程,可以先简单的看一下与处理过程。clang 有很多命令,可以通过

`$xcrun clang —help `

查看提示信息

其中关于预编译的:

-c                      Only run preprocess, compile, and assemble steps
-E                      Only run the preprocessor

我尝试使用上面的命令预编译了main.c文件
main.c文件:

#include <stdio.h>
int main(int argc, char *argv[])
{
    printf("Hello World!\n");
    return 0;
}

在main.c当前目录下执行
xcrun clang -E main.c | open -f

Open -f 是将预编译结果在文件中打开,预编译部分结果截图如下:

1.png

2.png

预编译过程因为要展开所有的宏定义,inclue , import。 输出的文件中行前面的 “#”号 (hash) 接着的数字 代表的插入的源文件中的行号, 后面的文件路径代表的是需要引入的文件的路径 后面的数字代表的是引入的内容在新生成的文件所在的行数,hash下面跟的内容是指定文件 指定行数 所引入的内容,例如第二张图中
将 /Application/Xcode.app/Contents/Developer/platforms/MacOSX10.12.sdk/usr/include/machine/_types.h 文件中的第33行,34行,55行的代码段
插入新生成的文件中。

Xcode也支持查看文件的预编译结果 ,选中文件点击product—>perform Action —>preprocess,之后便能看到预编译的结果,可以对比所引入的文件所在行数和引入的内容是否对应。

Xcode基于预编译的结果去构建语法树,生成中间字节码,下面是hello world的LLVM中间字节码


3.png

可以简单了解一下上面llvm中间码的意思,@符号是LLVM中间字节码(IR)的变量前缀,@代表全局变量标志,%代表局部变量标志。@.str是全局变量名,%cast210 是局部变量的名称 。i8, i32,i64代表的存储字节类型,char是i8,一个字节,int是i32,4个字节。@main,@put,@puts是方法名,在IR中function和全局变量统称全局值(global values)都是@前缀标志。

根据中间字节码(LLVM的字节码)做代码优化,优化后输出汇编代码。

可以使用下面命令来查看生成的汇编代码:
xcrun clang -S -o - main.c | open -f
结果如下图:

4.png

按照上面说的步骤,就进入了调用汇编器编译汇编代码了,汇编器将汇编代码转换成机器码,称为目标对象文件,在MacOSX, ios下为 Mach-O文件格式下图是苹果官方文档对mach-o文件格式的介绍:

5.png

Mach-O 的组成结构如下图所示包括了Header、Load commands、Data(包含Segement的具体数据)
我们可以在工程的编译路径下找到编译后生成的可执行文件APP,我本地路径为~/Library/Developer/Xcode/DerivedData/App-ackwqnrbjrdvslercxzskjictqru/Build/Intermediates/App.build/Release-iphonesimulator/App.build/Objects-normal/i386
在此路径下使用size工具查看文件结构
xcrun size -x -l -m App
输出
6.png

刚好与苹果给出的结构图相匹配,可以暂时先简单的了解下,__TEXT segment 包含了被执行的代码,它被以只读和可执行的方式映射。__DATA segment 中包含了可读写数据, 以可读写和不可执行的方式映射,它包含了将会被更改的数据。__LINKEDIT segment 包含了动态链接器的原始数据,如符号,字符串和重定位的表的入口.

7.png

最后进入连接器连接的阶段
链接器解决了目标文件和库之间的链接,链接器需要将所需的lib函数(可以理解为系统提供的函数),库函文件的内存地址编码进最后的可执行文件中,接着链接器会输出可以运行的执行文件:a.out,得到a.out 命令为:
xcrun clang man.c
用size 工具查看a.out的文件结构

8.png

可以看到 main.c文件生成的可执行文件a.out 的虚拟地址空间从0x10000000 开始的,之前的地址是不可访问

此时在借助mac下可执行文件的阅读器。machOView工具,看生成的a.out的文件结构和内容,发现了一张叫symbols的表


9.png

这里面就很清楚的记录了,编译前的字符串,在编译成二进制可执行文件后的虚拟地址,和app打包生成的dsym基本类似,这就可以猜想,苹果是如何通过crash的二进制栈信息解析出可读性的程序代码调用栈的。借助symbols表给我的希望,我用machOView打开了我编译生成的frameWork

原谅我把图片糊得像翔。。。。因为是公司的项目的frameWork

首先第一张里表示了在不同平台下的可执行数据,当前frameWork可在ARM,X86,Arm64,X86_64平台下执行


一.png

第二张图是所有frameWork内的类名对应的编译生成的虚拟地址


二.png

第三张是挑了第二张图中的一个类的symbols表,记录的是当前文件编译后的字符对照表。


三.png

那么有了以上三张表的对比后我们很容易的了解到Xcode工具如何通过运行期间的二进制地址对应到具体文件的具体代码调用了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,372评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,368评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,415评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,157评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,171评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,125评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,028评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,887评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,310评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,533评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,690评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,411评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,004评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,812评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,693评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,577评论 2 353

推荐阅读更多精彩内容