about the r_address feild
82 | * in images for used with the dynamic linker.
83 | *
84 | * In 4.3BSD a.out objects if r_extern is zero then r_symbolnum is an ordinal
85 | * for the segment the symbol being relocated is in. These ordinals are the
86 | * symbol types N_TEXT, N_DATA, N_BSS or N_ABS. In Mach-O object files these
87 | * ordinals refer to the sections in the object file in the order their section
88 | * structures appear in the headers of the object file they are in. The first
89 | * section has the ordinal 1, the second 2, and so on. This means that the
90 | * same ordinal in two different object files could refer to two different
91 | * sections. And further could have still different ordinals when combined
92 | * by the link-editor. The value R_ABS is used for relocation entries for
93 | * absolute symbols which need no further relocation.
94 | */
95 |
96 | /*
97 | * For RISC machines some of the references are split across two instructions
98 | * and the instruction does not contain the complete value of the reference.
99 | * In these cases a second, or paired relocation entry, follows each of these
100 | * relocation entries, using a PAIR r_type, which contains the other part of the
101 | * reference not contained in the instruction. This other part is stored in the
102 | * pair's r_address field. The exact number of bits of the other part of the
103 | * reference store in the r_address field is dependent on the particular
104 | * relocation type for the particular architecture.
105 | */
106 |
107 | /*
108 | * To make scattered loading by the link editor work correctly "local"
109 | * relocation entries can't be used when the item to be relocated is the value
110 | * of a symbol plus an offset (where the resulting expresion is outside the
111 | * block the link editor is moving, a blocks are divided at symbol addresses).
112 | * In this case. where the item is a symbol value plus offset, the link editor
113 | * needs to know more than just the section the symbol was defined. What is
114 | * needed is the actual value of the symbol without the offset so it can do the
115 | * relocation correctly based on where the value of the symbol got relocated to
116 | * not the value of the expression (with the offset added to the symbol value).
117 | * So for the NeXT 2.0 release no "local" relocation entries are ever used when
118 | * there is a non-zero offset added to a symbol. The "external" and "local"
119 | * relocation entries remain unchanged.
120 | *
121 | * The implemention is quite messy given the compatibility with the existing
122 | * relocation entry format. The ASSUMPTION is that a section will never be
123 | * bigger than 2**24 - 1 (0x00ffffff or 16,777,215) bytes. This assumption
124 | * allows the r_address (which is really an offset) to fit in 24 bits and high
125 | * bit of the r_address field in the relocation_info structure to indicate
126 | * it is really a scattered_relocation_info structure. Since these are only
127 | * used in places where "local" relocation entries are used and not where
128 | * "external" relocation entries are used the r_extern field has been removed.
129 | *
130 | * For scattered loading to work on a RISC machine where some of the references
131 | * are split across two instructions the link editor needs to be assured that
132 | * each reference has a unique 32 bit reference (that more than one reference is
133 | * NOT sharing the same high 16 bits for example) so it move each referenced
134 | * item independent of each other. Some compilers guarantees this but the
135 | * compilers don't so scattered loading can be done on those that do guarantee
136 | * this.
137 | */
138 | #if defined(__BIG_ENDIAN__) || defined(__LITTLE_ENDIAN__)
139 | /*
140 | * The reason for the ifdef's of __BIG_ENDIAN__ and __LITTLE_ENDIAN__ are that
141 | * when stattered relocation entries were added the mistake of using a mask
142 | * against a structure that is made up of bit fields was used. To make this
143 | * design work this structure must be laid out in memory the same way so the
144 | * mask can be applied can check the same bit each time (r_scattered).
145 | */
146 | #endif /* defined(__BIG_ENDIAN__) || defined(__LITTLE_ENDIAN__) */
147 | #define R_SCATTERED 0x80000000 /* mask to be applied to the r_address field
148 | of a relocation_info structure to tell that
149 | is is really a scattered_relocation_info
150 | stucture */
151 | struct scattered_relocation_info {
152 | #ifdef __BIG_ENDIAN__
153 | uint32_t r_scattered:1, /* 1=scattered, 0=non-scattered (see above) */
154 | r_pcrel:1, /* was relocated pc relative already */
155 | r_length:2, /* 0=byte, 1=word, 2=long, 3=quad */
156 | r_type:4, /* if not 0, machine specific relocation type */
157 | r_address:24; /* offset in the section to what is being
158 | relocated */
159 | int32_t r_value; /* the value the item to be relocated is
160 | refering to (without any offset added) */
161 | #endif /* __BIG_ENDIAN__ */
162 | #ifdef __LITTLE_ENDIAN__
163 | uint32_t
164 | r_address:24, /* offset in the section to what is being
165 | relocated */
166 | r_type:4, /* if not 0, machine specific relocation type */
167 | r_length:2, /* 0=byte, 1=word, 2=long, 3=quad */
168 | r_pcrel:1, /* was relocated pc relative already */
169 | r_scattered:1; /* 1=scattered, 0=non-scattered (see above) */
170 | int32_t r_value; /* the value the item to be relocated is
171 | refering to (without any offset added) */
172 | #endif /* __LITTLE_ENDIAN__ */
173 | };
174 |
175 | /*
176 | * Relocation types used in a generic implementation. Relocation entries for
177 | * normal things use the generic relocation as discribed above and their r_type
178 | * is GENERIC_RELOC_VANILLA (a value of zero).
179 | *
180 | * Another type of generic relocation, GENERIC_RELOC_SECTDIFF, is to support
181 | * the difference of two symbols defined in different sections. That is the
182 | * expression "symbol1 - symbol2 + constant" is a relocatable expression when
183 | * both symbols are defined in some section. For this type of relocation the
184 | * both relocations entries are scattered relocation entries. The value of
185 | * symbol1 is stored in the first relocation entry's r_value field and the
186 | * value of symbol2 is stored in the pair's r_value field.
187 | *
188 | * A special case for a prebound lazy pointer is needed to beable to set the
189 | * value of the lazy pointer back to its non-prebound state. This is done
190 | * using the GENERIC_RELOC_PB_LA_PTR r_type. This is a scattered relocation
191 | * entry where the r_value feild is the value of the lazy pointer not prebound.
192 | */
193 | enum reloc_type_generic
194 | {
195 | GENERIC_RELOC_VANILLA, /* generic relocation as discribed above */
196 | GENERIC_RELOC_PAIR, /* Only follows a GENERIC_RELOC_SECTDIFF */
197 | GENERIC_RELOC_SECTDIFF,
198 | GENERIC_RELOC_PB_LA_PTR, /* prebound lazy pointer */
199 | GENERIC_RELOC_LOCAL_SECTDIFF,
200 | GENERIC_RELOC_TLV /* thread local variables */
201 | };
202 |
203 | #endif /* _MACHO_RELOC_H_ */
204 |
--------------------------------------------------------------------------------
/doc/all.md:
--------------------------------------------------------------------------------
1 | # 高效逆向 - 为任意iOS App生成符号表
2 | ---
3 |
4 | ## 缘起
5 |
6 | 1. 如果你有研究其他`App`的习惯,那你一定已经知道了以下这些信息。
7 | 1. 总体来说,研究方法分为`静态分析`和`运行分析`两种。前者对可执行二进制文件本身进行分析,无需运行程序,工具如`class-dump`, `IDA Pro`等, 后者对运行起来的『进程』(而非『程序』)进行分析,工具如`Reveal`, `cycript`, `jailbreak Tweak`, `lldb`等。`IDA Pro`与`lldb`分别是两大阵营的大杀器。
8 | 2. 一般情况下,大家会先通过`Reveal`,`class-dump`等工具大致的猜测下,缩小想要重点研究的目标范围。当确认可以深入研究的时候,就可以进入`IDA Pro` + `lldb`结合分析的方式了。`IDA Pro`用来白盒观察完整逻辑,而`lldb`则可以通过**断点**, **调用堆栈**, **输出参数与返回值**等方式黑盒观察完整逻辑(并可以验证白盒下的推测,毕竟对着`IDA Pro`看上几天难免会犯一些错误)
9 | 3. 但使用`lldb`有个问题,即调试过程中你会发现如果调试的对象是系统组件,如`MessageUI.framework`(主要用于发送信息和邮件), 调用堆栈可以正常显示方法名,简单易懂。但如果你调试一个**非系统应用**,如`微信`,那么`lldb`中只会出现``MicroMessage`___lldb_unnamed_symbol36$$MicroMessage + 70`` 之类的字样,完全不知道这个函数做了什么事情,要知道**一个有意义的名字对于逆向是多么多么的重要!!**
10 | 4. 可是`IDA Pro`却可以从多个角度分析二进制文件,猜测出很多结果(比如根据`classname`与`selector`自动给对应的实现函数命名;根据函数调用指令,自动识别函数开始位置;以及通过对相关指令监控,从而确定函数的结束位置等)。这些猜测结果如果我们善加利用,便可以辅助我们的`lldb`调试过程。这个借鉴有很多思路,可以侵入,也可以外挂,本文尝试通过**将`IDA Pro`数据库内容导出成符号表**这一思路将`IDA Pro`的信息带入到`lldb`中来。
11 | 2. `2016-08-08`, `IDA Pro 6.95`发布,在 [What's new in IDA 6.95.160808](https://www.hex-rays.com/products/ida/6.95/index.shtml) 中,作者提到了其重新加入了`iOS debugger`, 真是让人眼馋的功能。从此`IDA Pro`动态分析的功能又回到了`iOS`世界中。但`IDA Pro`的授权费确实太贵,实在是买不起,怎么办呢?『自己动手,丰衣足食』,那就我们自己构建一个『简易的iOS调试器』吧(当然还是基于`lldb`)。这其中就需要我们自行讲`IDA Pro`的信息桥接到`lldb`中,本文重建符号表便是这个思路下的第一步尝试。
12 | 3. 即使你不搞逆向,也对研究其他`App`没啥兴趣。但有一种事件你要预防,虽然他是小概率事件,但一旦发生便很惨。这就是**线上版本符号表信息丢失**。我们知道现在有很多团队是自行分析崩溃日志的(而不是借助`iTunes Connect`),这就需要自己托管符号信息,上传到崩溃分析系统。而符号表信息一旦丢失,线上的崩溃便无法解开,此时如果有大面积的崩溃出现,你就只能对着一串串的内存地址干瞪眼,毫无办法。那本文提供的重建符号表的方式,也可以解决你的燃眉之急。
13 |
14 | 综上所述,便是这篇文章的成因。
15 |
16 | ## 过程简述
17 | 要实现符号表的重建,换言之,要实现从`IDA Pro`数据库到创建`dSYM`,我们按照以下内容去将整个思路走通。
18 |
19 | 1. 首先要搞清楚符号表需要什么信息,由于我们要创建的符号表内容仅仅是函数,那么其实我们只需要三个东西: `函数名称`, `起始地址`, `结束地址` 就可以了。
20 | 1. 搞清楚符号表需要什么信息之后,接下来就是`IDA Pro`数据库的信息怎么导出来的问题了。`IDA Pro`是支持编程接口的,所以我们可以写一个自动化的脚本导出我们想要的信息。在完整版`IDA Pro`中,官方提供了`Python`接口,大家可以开开心心的用`Python`来写这个自动化的脚本。
21 | 1. 但是大家还记得上文里我们提到过一个很重要的问题么?那就是**我们买不起完整版啊!!**难道这篇文章到这里就神奇般的结束了?不不,怎么可能?虽然完整版我们买不起,但是官方放出来一个[评估版](https://www.hex-rays.com/products/ida/support/download_demo.shtml)给我们使用,虽然它有很多限制,以及用着用着就弹出个框告诉你你现在用的是`demo`版本,但是最重要的是**它是免费的!!**同时它竟然还带了原生的`IDC`语言支持,虽然是精简版的,但好歹可以用。于是我们终于可以通过这个要吐槽我能吐槽它一天不带重样的语言来编写自动化脚本了。
22 | 1. `IDA Pro`的事情搞定,接下来要看看那头:`dSYM`文件到底是什么。这个很快便能发现,一个`dSYM`实际上是个`bundle`,里面除了一个简单的`plist`,最重要的就是一个二进制文件,里面存放了符号信息。
23 | 2. 那我们既然要重建符号信息,那总得知道这个符号文件是啥格式吧。观察文件的`Magic Number`(一般是起始的一两个字节),发现是`CE FA ED FE`, 即`FEEDFACE`, 是我们熟知的`Mach-O`文件格式(即使不了解通过简单的搜索也可以获取)。
24 | 3. 既然是`Mach-O`文件,那么我们就通过 [`MachOView`](https://sourceforge.net/projects/machoview/) 工具来学习一个已有的`dSYM`吧。它大概看起来是这样的。
25 |
26 | 
27 |
28 | 1. 眼尖的我们很快就发现一个名字叫`Symbol Table`部分,这看起来就是我们要找的符号表了,简单的分析了下(感谢`MachOView`的直观展示),其由文件头部的名为`LC_SYMTAB`的`Load Command`定义,表示一个函数符号的列表,每个符号包含如下信息:
29 | 1. **名称**。要注意,它的名称并不是直接存在`Symbol Table`中的。相替代的,它将所有的名称都存在了一个名字叫做`String Table`的部分里,然后`Symbol Table`引用了其偏移量。
30 | 1. **Section Index**。我们知道无论是`mach-o`,还是`PE`,或者是`Elf`,都是将一个可执行文件分为多个`Segment`,每个`Segment`分为多个`Section`,代码和数据便根据自己的特点放在了许多`Section`中。这里的`Section Index`即标示了这个函数代码是放在了哪个`Section`中。
31 | 1. **起始地址**。函数代码的起始地址,这里要注意的是,实际上其记录的是函数代码在**可执行文件**的偏移量,并不是进程内存的偏移量。
32 |
33 | 
34 |
35 | 1. 对上一步骤得到的三个数据一一攻克。
36 | 1. 首先是名称,这个没啥难度,将所有函数名称收集一下,依次以`0`分割放在`String Table`中,同时记录下偏移量以备`Symbol Table`使用即可。
37 | 2. 接下来是`Section Index`。这里有两个选择,第一,照着可执行文件抄一份`Segment`和`Section`的声明,然后建立`Symbol Table`的时候函数地址落在哪个`Section`便使用哪个`Section Index`。还有个方式就是只建立一个`Section`,然后声明下我们的函数都落在这个`Section`中,这个方法需要验证`lldb`的兼容性(毕竟符号文件和可执行文件不一致了)。
38 | 3. 最后是`起始地址`。这里没啥问题。
39 | 1. 好,`IDA Pro`数据来源搞清楚了,也理解了`dSYM`如何格式化了,那接下来是不是就可以开始重建符号表了呢?不不,还差最后一个问题要搞清楚,即**lldb如何确定一个可执行文件和一个符号文件是相符的**。如果不了解这个问题,即使我们重建了符号表,`lldb`不认我们也没办法。不过这个问题倒是不难解决,这个奥秘就在一个叫做`LC_UUID`的`Load Command`中,当`lldb`在寻找符号表时要验证这个地方记录的`UUID`,只有可执行文件和符号文件的`UUID`相同,`lldb`才会『尝试』去加载这个符号表。
40 |
41 | 
42 |
43 | # 实现
44 |
45 | 搞定所有事情,接下来就是实现代码将其串联起来了。代码放在了[https://github.com/imoldman/DSYMCreator](https://github.com/imoldman/DSYMCreator),简要介绍下代码组成。
46 |
47 | - `doc`内是文档,`test`是一个测试工程,这些不是主要代码部分。
48 |
49 | - `toolchain`放置了我们整个过程使用到的工具。
50 | - 其中`IDAScript`目录放置了给`IDA Pro`使用的自动化脚本。 `all.idc`就是那个将`IDA Pro`结果导出的自动化脚本,其接收一个表示存放地址的路径,然后会将每个函数的名称,起始地址,结束地址都输出到这个文件上。
51 |
52 | - 需要详细介绍的是`DSYMCreator`工具,其源码位于`src`内,我将其`build`的结果放了一份在`toolchain`里,其工作就是本文上面描述的内容。其命令行大概看起来是这样的。
53 |
54 | ```shell
55 | $ ./DSYMCreator --uuid "14494083-a184-31e2-946b-3f942a402952" --raw_ida_symbol "/tmp/symbols.txt" --dwarf_section_vmbase 0x40000 --output /path/to/save/loadable_symbol
56 | ```
57 |
58 | 大致解释一下。
59 | - `uuid`, 即为上文中提到的可执行文件的`uuid`, 构建符号表要用到
60 | - `raw_ida_symbol` 即为从`IDA Pro`中获取的符号数据
61 | - `dwarf_section_vmbase`, 这个稍微有点复杂。由于符号文件和可执行文件描述的实际是一个程序,因此他们的`segment`和`section`要保证兼容。其中这里的一条要求就是`dwarf`数据不能跟代码数据覆盖,此参数就是用来指定`dwarf`在进程内存中的起始地址的。
62 | - `output` 顾名思义,即为导出的符号表文件。
63 | - 根目录的`main.py`是一个整合脚本,下文详述。
64 |
65 | # 如何重建
66 | 大家估计一听上面介绍就疯了,这都是啥跟啥啊?这工具到底咋用啊?
67 |
68 | 不要着急,为了照顾大家的心情,本工具在有限的条件下做足了优化,使得大家**根本就不用关心IDA Pro**是怎么使用的,所有过程都是**自动化或半自动化完成的**(之所以还有『半自动化』的,实在是条件有限,`IDA Pro`评估版限制太多,大家多体谅。。。)
69 |
70 | **以下是最终使用方式**。
71 |
72 | > 0. 如果二进制文件有壳,先将其砸掉,注意取`armv7`版本
73 | > 1. `$ ./main.py --input /path/to/binary/xxx`
74 | > 2. 其实你的工作已经基本结束了,`IDA Pro`会自动打开并自动开始工作,然后可能需要你点两三次`OK`(这就是前面提到的『半自动化』部分),之后等待`IDA Pro`自动退出。
75 | > 3. 此时在与输入的可执行文件`xxx`同级目录下会生成一个名为`xxx.symbol`的文件,这个文件即为我们重建的符号文件。
76 |
77 | # 验证
78 | 生成了符号文件,测试一下是不是可以正常使用呢?简单期间,本文就不采用真实案例作为目标对象了。相替代的,我在`test`目录下放置了一个小工程,其中模拟了一个登陆操作,其会将密码做一定校验,如果校验出错会弹框提醒,如果校验成功,会什么都不做,我们的目标就是搞定这个函数。
79 |
80 | 0. 提前找台`32`位的越狱机器(由于`IDA Pro`评估版只支持`32`位,因此此处必须找一个`32`位的越狱机器),并提前部署好响应版本的`debugserver`。
81 | 1. 使用该越狱设备去[http://fir.im/dsymtest](http://fir.im/dsymtest) 安装这个示例工程(已经`strip`过`debug info`)。
82 | 2. 在设备上启动这个应用。`ssh`登录这台设备,并输入如下命令,让`debugserver`监听`1234`接口,等待我们连入。
83 |
84 | ```shell
85 | $ ./debugserver *:1234 -a "TestApp" #假设debugserver在当前目录
86 | ```
87 |
88 | 2. 在`mac`上使用`lldb`,输入如下命令
89 |
90 | ```shell
91 | $ lldb
92 | (lldb) platform select remote-ios
93 | (lldb) process connect connect://192.168.2.6:1234 #假设192.168.2.6是设备的ip,输入完这个命令后需要等待一些时间
94 | (lldb) bt # 输入当前堆栈
95 | ```
96 |
97 | 3. 在上一步骤的堆栈中,你会看到类似这样的内容。
98 |
99 | 
100 |
101 | 显然`main`函数没有被识别出来。这个时候我们使用下面的命令设置`UIAlertController`的断点(想观察密码校验出错弹框的调用堆栈)。
102 |
103 | ```shell
104 | (lldb) br s -r ".*UIAlertController alertControllerWithTitle.*" #给名称中包含UIAlertController alertControllerWithTitle的函数都加上断点
105 | (lldb) c # 继续执行,让程序跑起来
106 | ```
107 |
108 | 此时我们在密码框里输入`1`(为什么要输入`1`,是因为代码是我写的,我知道怎样会验证失败,哈哈。其实这里就是一个重现步骤的问题,在真实案例中需要大家自行准备)。调试器会停下来,并提示我们命中了断点,此时我们输入如下命令
109 |
110 | ```shell
111 | (lldb) bt #观察当前的堆栈
112 | ```
113 |
114 | 此时你会得到类似这样的结果。
115 |
116 | 
117 |
118 | 很明显,以`TestApp`开头的符号没有被正常解析出来。
119 |
120 | 4. 现在该我们的主角登场了,新开一个终端,`ssh`到设备,输入如下命令
121 |
122 | ```shell
123 | $ ps aux | grep TestApp
124 | ```
125 |
126 | 这一步的目的是为了获取`TestApp`的二进制文件路径,获取到了之后退出`ssh`,使用如下命令讲可执行文件复制到本地(我在仓库里放了一份二进制文件,大家也可以用这份`/test/bin/TestApp`),并重建符号表
127 |
128 | ```shell
129 | $ scp root@192.168.2.6:/var/mobile/Containers/Bundle/Application/E3636785-6885-4193-B740-D7E39F9C85BD/TestApp.app/TestApp /path/to/TestApp
130 | $ ./main.py --input /path/to/TestApp
131 | ```
132 |
133 | 这样一个名为`/path/to/TestApp.symbol`的文件就产生了,此即为重建好的符号文件
134 |
135 | 5. 将符号文件加载到`lldb`中, 并观察调用堆栈验证。使用如下命令。
136 |
137 | ```shell
138 | (lldb) target symbols add /path/to/TestApp.symbol
139 | (lldb) bt
140 | ```
141 |
142 | 6. 此时输入结果中包含了符号化的信息,如下图,我们的重建过程成功。
143 |
144 | 
145 |
146 | 7. 调用堆栈搞定了,很明显是这个 `-[ViewController foo3:]` 搞的鬼,打个断点看看他输入参数是啥吧,恩。
147 |
148 | ```shell
149 | (lldb) br s -n "-[ViewController foo3:]"
150 | Breakpoint 2: no locations (pending).
151 | WARNING: Unable to resolve breakpoint to any actual locations.
152 | ```
153 |
154 | 我擦,什么情况?!断点打不上?什么鬼?哪里出问题了?
155 |
156 | 其实问题的原因是:**我们刚才重建的符号表根本就不是完整的,跟lldb无法完美兼容**。哪怎样才能兼容呢,这还是要从『为什么要打断点』说起。
157 |
158 | ## 为什么要打断点
159 |
160 | 我们千辛万苦制作的符号表文件可以使得`lldb`显示堆栈时正确显示函数名,但是却不能设置断点。要知道不能设置断点是个很大的遗憾。逆向时,我们常常需要在某个函数开始时设置断点。这样设置断点主要有以下几个好处。
161 |
162 | - **观察传入参数**。虽然我们可以通过`class-dump`获取函数名,也可以顺带获取函数的参数类型,但如果参数都`OC`对象,由于所有`OC`对象本质上都是一样的,所以`class-dump`只会弱弱的显示一个`id`,如下例。
163 |
164 | ```Objective-C
165 | - (id)formatUser:(id)arg1 withOptions:(id)arg2;
166 | ```
167 |
168 | 一个`id`用处有限,比如上例,根本无法获知这个函数的参数和返回值类型是什么,那我们逆向的思路就断在这里了。此时通过`cycript`, `jailbreak tweak`, `lldb`等方式动态调试一下就很有必要。
169 | 另外,有时候只知道参数类型是没有用的,这个时候还需要知道参数的值,在函数开始时设置断点也很有用。
170 |
171 | - **观察调用堆栈**。有时候你察觉到某个函数是整个逆向过程的关键,你通过`IDA Pro`查阅了其逻辑代码,大致理解了它做什么事情之后,现在你的任务是观察它的上下游,搞定整个流程。此时你在这个函数开始的位置打个断点,然后观察其调用堆栈,就知道了到底是哪些函数调用了它,为进一步的逆向做好准备。
172 | - **找delegate**。很多时候,我们通过`IDA Pro`看代码,发现某个地方有个对`XXXDelegate`的调用,我们想深入这个里面看看,但是由于`delegate`是运行时设置进去的,所以静态分析无法直接跳转进入到`delegate`的实现。相替代的,我们可以去`class-dump`中搜索有哪些类实现了这个名为`XXXDelegate`的`Protocol`,如果这个`Protocol`实现的类的个数比较少还好说,可以一个一个的设置断点,命中哪个就是哪个。但如果这个`Protocol`实现的类的个数特别多,依次设置断点根本不可能;或者根本找不到任何一个实现了这个`Protocol`的类,断点无法设置,这两种情况都会使我们陷入困境。此时你需要使用下面的命令设置断点。
173 |
174 | ```shell
175 | (lldb) breakpoint set --selector "downloader:downloadImageFinished:"
176 | # 或简写为
177 | (lldb) br s -S "downloader:downloadImageFinished:"
178 | ```
179 |
180 | 该命令是告诉`lldb`将『所有』`downloader:downloadImageFinished:`的`selector`对应的实现函数全部打上断点。打上断点之后,我们运行程序,触发重现流程,断点即会命中,这个时候观察下调用堆栈,就知道到底是哪个类实现了这个`Protocol`
181 |
182 | 说一千道一万,吹了这么多,还是要搞定『为什么做好符号表但是断点无法打上』的问题。
183 |
184 | ## 理论准备
185 |
186 | 先考虑下从理论上我们是不是漏掉了什么。猜测一下,当我们打断点的时候发生什么事情呢?
187 |
188 | 显然我们这里的断点都不是直接打给内存地址的,即`address breakpoint`。相反,我们打断点的时候使用了函数名,也就是说调试器在真正打断点前需要先将我们给定的函数名转化为内存地址,也就是有一个`name -> address`的对应关系。
189 |
190 | 这个过程一共有两步。
191 |
192 | 1. 从符号表中查询该`name`对应的记录,要注意,这里的记录其实是代码在可执行文件的偏移量。
193 | 2. 讲上一步骤得到的结果映射成进程内的内存地址`address`。
194 |
195 | 接下来`lldb`对这个内存打断点就可以了。
196 |
197 | 整个过程用到符号表的只有第一步,换言之只要我们有一个『存储了函数名称和代码地址』的符号表,整个问题就搞定了,我们的断点应该就可以打上了。
198 |
199 | 可现在的情况是我们确实有符号表,但也确实打不上断点。
200 |
201 | 哪里出问题了呢?
202 |
203 | ## DWARF
204 |
205 | 『解铃还须系铃人』,既然是`lldb`告诉我们断点打不上,那就看下到底它的逻辑是啥吧。所幸`lldb`全部开源,『源码面前,了无秘密』。
206 |
207 | 如何获取和构建`lldb`,大家可以在[官网](http://lldb.llvm.org/build.html)找到。这里就不详述了。总之经过大致的浏览,很快就会发现,我们的问题多半跟一个类型名称叫做`DWARF`的符号表有关。
208 |
209 | 那什么是`DWARF`呢?如果你注意观察的话,其实平时我们接触过这个名词。一个`dSYM Bundle`文件组成看起来是这样的。
210 |
211 | ```shell
212 | $ tree
213 | .
214 | └── TestApp.app.dSYM
215 | └── Contents
216 | ├── Info.plist
217 | └── Resources
218 | └── DWARF
219 | └── TestApp
220 | ```
221 |
222 | 这里就有一个名字叫做`DWARF`的目录,暗示了`TestApp.app.dSYM`中的符号表就是`DWARF`格式。那么他跟我们自行创建的符号表有啥区别呢?我们还是通过`MachOView`来看一下。
223 |
224 | 
225 |
226 | 很明显,它多了一个名字叫`__DWARF`的`segment`, 其下有一堆的`section`: `__debug_info`, `__debug_line`, `__debug_str`等等。看样子这确实是跟调试有关的东西。会不会是我们缺少这些信息导致我们无法打断点呢?
227 |
228 | 还是得先搞清楚`DWARF`到底是什么东西。
229 |
230 | 经过简单的搜索,我们得知,`DWARF`实际上是一种符号表的格式,苹果的开发人员借用了这个格式来放放置调试符号。[这里](http://wiki.dwarfstd.org/index.php?title=Apple%27s_%22Lazy%22_DWARF_Scheme)还简要记录了当年他们的『心路历程』。
231 |
232 | ## 不可或缺的sections
233 |
234 | 了解完`DWARF`是什么东西,那么我们回过来看下`lldb`是怎么使用的。经过一番查阅,发现原来**必须包含`__debug_str`, `__debug_line`, `__debug_abbrev`, `__debug_info`四个`section`,`lldb`才认为这是一个合法的`DWARF`符号表**(相关代码见注1)。
235 |
236 | 那就来看看这几个`section`分别代表啥意思吧。经过源码和多种工具(如`dwarfdump`)相结合的方式,最终得到如下的成果。
237 |
238 | - **`__debug_line`**, 这个记录了源代码的行号。我们从可执行文件中显然是分析不出啥行号的,这个`section`留空就好了,反正只是骗骗`lldb`用。
239 | - **`__debug_str`**, 这个跟上一篇提到的`String Table`比较像,记录了所有需要用到的字符串,然后其他`section`使用偏移量来引用字符串。
240 | - **`__debug_abbrev`**和**`__debug_info`**。这俩是一个整体,共同合作来记录调试需要的数据,需要一起解释。
241 |
242 | 通俗的来讲,`__debug_abbrev`中记录的是`key`, `__debug_info`中记录的是`value`。我们以代码作为例子类比下,对于`uint32_t foo = 42;`, 这里可以看做是有一个名字叫做`foo`并占用了`4`字节的`key`,其`value`是`42`。那么我们可以将`foo`和`4`写入`__debug_abbrev`中,将`42`写入`__debug_abbrev`中。
243 |
244 | ## 最终实现
245 |
246 | 罗里吧嗦说了一堆,再加上根本不知道怎么说的数据结构细节,我们最终将符号表写了一份到`DWARF`段中。代码还是放在了[GitHub](https://github.com/imoldman/DSYMCreator)上,使用前文提到的方式生成符号表并导入。
247 |
248 | 现在可以打断点拉。
249 |
250 | 来张最终的符号表结构。
251 |
252 | 
253 |
254 | ---
255 | 注:
256 |
257 | 1. 如果真的发生了**线上版本符号文件丢失**,除了本文的工具,还有个办法。
258 | 1. 用当时的代码当时的环境,一样的配置参数,再打一个包
259 | 2. 把`UUID`改成和线上版本的一致,记得`armv7`与`arm64`位分别有一个独立的`UUID`,都要改下。这样符号表就可以直接用了
260 |
261 | 1. `lldb`中如何判断一个`DWARF`符号表文件是合法的,相关代码如下。
262 |
263 | - [SymbolFileDWARF.cpp:584-647](https://github.com/llvm-mirror/lldb/blob/master/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp#L584-L647), 这段代码枚举符号文件里的`section`,然后根据有哪些`section`来判断这个符号表支持哪些特性(这里面就是探测了正文部分提到的四个`section`)。
264 | - [SymbolFile.cpp:58-66](https://github.com/llvm-mirror/lldb/blob/master/source/Symbol/SymbolFile.cpp#L58-L66),这段代码生成了一个符号表,然后判断一下是不是支持了`kAllAbilities`(即所有特性),那到底这个`kAllAbilities`包含哪些特性呢?
265 | - [SymbolFile.h:36-45](https://github.com/llvm-mirror/lldb/blob/master/include/lldb/Symbol/SymbolFile.h#L36-L45),原来`kAllAbilities`即包含`SymbolFileDWARF.cpp`中所列的所有特性,所以,我们要支持`__debug_str`, `__debug_line`, `__debug_abbrev`, `__debug_info`四个`section`,缺一不可。
--------------------------------------------------------------------------------
/test/TestApp/TestApp.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 7F3E867E1D79D22400379E6B /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F3E867D1D79D22400379E6B /* main.m */; };
11 | 7F3E86811D79D22400379E6B /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F3E86801D79D22400379E6B /* AppDelegate.m */; };
12 | 7F3E86841D79D22400379E6B /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F3E86831D79D22400379E6B /* ViewController.m */; };
13 | 7F3E86871D79D22400379E6B /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7F3E86851D79D22400379E6B /* Main.storyboard */; };
14 | 7F3E86891D79D22400379E6B /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7F3E86881D79D22400379E6B /* Assets.xcassets */; };
15 | 7F3E868C1D79D22400379E6B /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7F3E868A1D79D22400379E6B /* LaunchScreen.storyboard */; };
16 | /* End PBXBuildFile section */
17 |
18 | /* Begin PBXFileReference section */
19 | 7F3E86791D79D22400379E6B /* TestApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TestApp.app; sourceTree = BUILT_PRODUCTS_DIR; };
20 | 7F3E867D1D79D22400379E6B /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
21 | 7F3E867F1D79D22400379E6B /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
22 | 7F3E86801D79D22400379E6B /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
23 | 7F3E86821D79D22400379E6B /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; };
24 | 7F3E86831D79D22400379E6B /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; };
25 | 7F3E86861D79D22400379E6B /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
26 | 7F3E86881D79D22400379E6B /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
27 | 7F3E868B1D79D22400379E6B /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
28 | 7F3E868D1D79D22400379E6B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
29 | /* End PBXFileReference section */
30 |
31 | /* Begin PBXFrameworksBuildPhase section */
32 | 7F3E86761D79D22400379E6B /* Frameworks */ = {
33 | isa = PBXFrameworksBuildPhase;
34 | buildActionMask = 2147483647;
35 | files = (
36 | );
37 | runOnlyForDeploymentPostprocessing = 0;
38 | };
39 | /* End PBXFrameworksBuildPhase section */
40 |
41 | /* Begin PBXGroup section */
42 | 7F3E86701D79D22400379E6B = {
43 | isa = PBXGroup;
44 | children = (
45 | 7F3E867B1D79D22400379E6B /* TestApp */,
46 | 7F3E867A1D79D22400379E6B /* Products */,
47 | );
48 | sourceTree = "";
49 | };
50 | 7F3E867A1D79D22400379E6B /* Products */ = {
51 | isa = PBXGroup;
52 | children = (
53 | 7F3E86791D79D22400379E6B /* TestApp.app */,
54 | );
55 | name = Products;
56 | sourceTree = "";
57 | };
58 | 7F3E867B1D79D22400379E6B /* TestApp */ = {
59 | isa = PBXGroup;
60 | children = (
61 | 7F3E867F1D79D22400379E6B /* AppDelegate.h */,
62 | 7F3E86801D79D22400379E6B /* AppDelegate.m */,
63 | 7F3E86821D79D22400379E6B /* ViewController.h */,
64 | 7F3E86831D79D22400379E6B /* ViewController.m */,
65 | 7F3E86851D79D22400379E6B /* Main.storyboard */,
66 | 7F3E86881D79D22400379E6B /* Assets.xcassets */,
67 | 7F3E868A1D79D22400379E6B /* LaunchScreen.storyboard */,
68 | 7F3E868D1D79D22400379E6B /* Info.plist */,
69 | 7F3E867C1D79D22400379E6B /* Supporting Files */,
70 | );
71 | path = TestApp;
72 | sourceTree = "";
73 | };
74 | 7F3E867C1D79D22400379E6B /* Supporting Files */ = {
75 | isa = PBXGroup;
76 | children = (
77 | 7F3E867D1D79D22400379E6B /* main.m */,
78 | );
79 | name = "Supporting Files";
80 | sourceTree = "";
81 | };
82 | /* End PBXGroup section */
83 |
84 | /* Begin PBXNativeTarget section */
85 | 7F3E86781D79D22400379E6B /* TestApp */ = {
86 | isa = PBXNativeTarget;
87 | buildConfigurationList = 7F3E86901D79D22400379E6B /* Build configuration list for PBXNativeTarget "TestApp" */;
88 | buildPhases = (
89 | 7F3E86751D79D22400379E6B /* Sources */,
90 | 7F3E86761D79D22400379E6B /* Frameworks */,
91 | 7F3E86771D79D22400379E6B /* Resources */,
92 | );
93 | buildRules = (
94 | );
95 | dependencies = (
96 | );
97 | name = TestApp;
98 | productName = TestApp;
99 | productReference = 7F3E86791D79D22400379E6B /* TestApp.app */;
100 | productType = "com.apple.product-type.application";
101 | };
102 | /* End PBXNativeTarget section */
103 |
104 | /* Begin PBXProject section */
105 | 7F3E86711D79D22400379E6B /* Project object */ = {
106 | isa = PBXProject;
107 | attributes = {
108 | LastUpgradeCheck = 0730;
109 | ORGANIZATIONNAME = oldman;
110 | TargetAttributes = {
111 | 7F3E86781D79D22400379E6B = {
112 | CreatedOnToolsVersion = 7.3.1;
113 | DevelopmentTeam = T3GF4E8HBP;
114 | };
115 | };
116 | };
117 | buildConfigurationList = 7F3E86741D79D22400379E6B /* Build configuration list for PBXProject "TestApp" */;
118 | compatibilityVersion = "Xcode 3.2";
119 | developmentRegion = English;
120 | hasScannedForEncodings = 0;
121 | knownRegions = (
122 | en,
123 | Base,
124 | );
125 | mainGroup = 7F3E86701D79D22400379E6B;
126 | productRefGroup = 7F3E867A1D79D22400379E6B /* Products */;
127 | projectDirPath = "";
128 | projectRoot = "";
129 | targets = (
130 | 7F3E86781D79D22400379E6B /* TestApp */,
131 | );
132 | };
133 | /* End PBXProject section */
134 |
135 | /* Begin PBXResourcesBuildPhase section */
136 | 7F3E86771D79D22400379E6B /* Resources */ = {
137 | isa = PBXResourcesBuildPhase;
138 | buildActionMask = 2147483647;
139 | files = (
140 | 7F3E868C1D79D22400379E6B /* LaunchScreen.storyboard in Resources */,
141 | 7F3E86891D79D22400379E6B /* Assets.xcassets in Resources */,
142 | 7F3E86871D79D22400379E6B /* Main.storyboard in Resources */,
143 | );
144 | runOnlyForDeploymentPostprocessing = 0;
145 | };
146 | /* End PBXResourcesBuildPhase section */
147 |
148 | /* Begin PBXSourcesBuildPhase section */
149 | 7F3E86751D79D22400379E6B /* Sources */ = {
150 | isa = PBXSourcesBuildPhase;
151 | buildActionMask = 2147483647;
152 | files = (
153 | 7F3E86841D79D22400379E6B /* ViewController.m in Sources */,
154 | 7F3E86811D79D22400379E6B /* AppDelegate.m in Sources */,
155 | 7F3E867E1D79D22400379E6B /* main.m in Sources */,
156 | );
157 | runOnlyForDeploymentPostprocessing = 0;
158 | };
159 | /* End PBXSourcesBuildPhase section */
160 |
161 | /* Begin PBXVariantGroup section */
162 | 7F3E86851D79D22400379E6B /* Main.storyboard */ = {
163 | isa = PBXVariantGroup;
164 | children = (
165 | 7F3E86861D79D22400379E6B /* Base */,
166 | );
167 | name = Main.storyboard;
168 | sourceTree = "";
169 | };
170 | 7F3E868A1D79D22400379E6B /* LaunchScreen.storyboard */ = {
171 | isa = PBXVariantGroup;
172 | children = (
173 | 7F3E868B1D79D22400379E6B /* Base */,
174 | );
175 | name = LaunchScreen.storyboard;
176 | sourceTree = "";
177 | };
178 | /* End PBXVariantGroup section */
179 |
180 | /* Begin XCBuildConfiguration section */
181 | 7F3E868E1D79D22400379E6B /* Debug */ = {
182 | isa = XCBuildConfiguration;
183 | buildSettings = {
184 | ALWAYS_SEARCH_USER_PATHS = NO;
185 | CLANG_ANALYZER_NONNULL = YES;
186 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
187 | CLANG_CXX_LIBRARY = "libc++";
188 | CLANG_ENABLE_MODULES = YES;
189 | CLANG_ENABLE_OBJC_ARC = YES;
190 | CLANG_WARN_BOOL_CONVERSION = YES;
191 | CLANG_WARN_CONSTANT_CONVERSION = YES;
192 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
193 | CLANG_WARN_EMPTY_BODY = YES;
194 | CLANG_WARN_ENUM_CONVERSION = YES;
195 | CLANG_WARN_INT_CONVERSION = YES;
196 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
197 | CLANG_WARN_UNREACHABLE_CODE = YES;
198 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
199 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
200 | COPY_PHASE_STRIP = NO;
201 | DEBUG_INFORMATION_FORMAT = dwarf;
202 | ENABLE_STRICT_OBJC_MSGSEND = YES;
203 | ENABLE_TESTABILITY = YES;
204 | GCC_C_LANGUAGE_STANDARD = gnu99;
205 | GCC_DYNAMIC_NO_PIC = NO;
206 | GCC_NO_COMMON_BLOCKS = YES;
207 | GCC_OPTIMIZATION_LEVEL = 0;
208 | GCC_PREPROCESSOR_DEFINITIONS = (
209 | "DEBUG=1",
210 | "$(inherited)",
211 | );
212 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
213 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
214 | GCC_WARN_UNDECLARED_SELECTOR = YES;
215 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
216 | GCC_WARN_UNUSED_FUNCTION = YES;
217 | GCC_WARN_UNUSED_VARIABLE = YES;
218 | IPHONEOS_DEPLOYMENT_TARGET = 9.3;
219 | MTL_ENABLE_DEBUG_INFO = YES;
220 | ONLY_ACTIVE_ARCH = YES;
221 | SDKROOT = iphoneos;
222 | };
223 | name = Debug;
224 | };
225 | 7F3E868F1D79D22400379E6B /* Release */ = {
226 | isa = XCBuildConfiguration;
227 | buildSettings = {
228 | ALWAYS_SEARCH_USER_PATHS = NO;
229 | CLANG_ANALYZER_NONNULL = YES;
230 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
231 | CLANG_CXX_LIBRARY = "libc++";
232 | CLANG_ENABLE_MODULES = YES;
233 | CLANG_ENABLE_OBJC_ARC = YES;
234 | CLANG_WARN_BOOL_CONVERSION = YES;
235 | CLANG_WARN_CONSTANT_CONVERSION = YES;
236 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
237 | CLANG_WARN_EMPTY_BODY = YES;
238 | CLANG_WARN_ENUM_CONVERSION = YES;
239 | CLANG_WARN_INT_CONVERSION = YES;
240 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
241 | CLANG_WARN_UNREACHABLE_CODE = YES;
242 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
243 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
244 | COPY_PHASE_STRIP = NO;
245 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
246 | ENABLE_NS_ASSERTIONS = NO;
247 | ENABLE_STRICT_OBJC_MSGSEND = YES;
248 | GCC_C_LANGUAGE_STANDARD = gnu99;
249 | GCC_NO_COMMON_BLOCKS = YES;
250 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
251 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
252 | GCC_WARN_UNDECLARED_SELECTOR = YES;
253 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
254 | GCC_WARN_UNUSED_FUNCTION = YES;
255 | GCC_WARN_UNUSED_VARIABLE = YES;
256 | IPHONEOS_DEPLOYMENT_TARGET = 9.3;
257 | MTL_ENABLE_DEBUG_INFO = NO;
258 | SDKROOT = iphoneos;
259 | VALIDATE_PRODUCT = YES;
260 | };
261 | name = Release;
262 | };
263 | 7F3E86911D79D22400379E6B /* Debug */ = {
264 | isa = XCBuildConfiguration;
265 | buildSettings = {
266 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
267 | CODE_SIGN_IDENTITY = "iPhone Developer";
268 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
269 | ENABLE_BITCODE = NO;
270 | INFOPLIST_FILE = TestApp/Info.plist;
271 | IPHONEOS_DEPLOYMENT_TARGET = 8;
272 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
273 | PRODUCT_BUNDLE_IDENTIFIER = li.oldman.TestApp2;
274 | PRODUCT_NAME = "$(TARGET_NAME)";
275 | PROVISIONING_PROFILE = "";
276 | };
277 | name = Debug;
278 | };
279 | 7F3E86921D79D22400379E6B /* Release */ = {
280 | isa = XCBuildConfiguration;
281 | buildSettings = {
282 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
283 | CODE_SIGN_IDENTITY = "iPhone Developer";
284 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
285 | DEPLOYMENT_POSTPROCESSING = YES;
286 | ENABLE_BITCODE = NO;
287 | INFOPLIST_FILE = TestApp/Info.plist;
288 | IPHONEOS_DEPLOYMENT_TARGET = 8;
289 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
290 | PRODUCT_BUNDLE_IDENTIFIER = li.oldman.TestApp2;
291 | PRODUCT_NAME = "$(TARGET_NAME)";
292 | PROVISIONING_PROFILE = "";
293 | };
294 | name = Release;
295 | };
296 | /* End XCBuildConfiguration section */
297 |
298 | /* Begin XCConfigurationList section */
299 | 7F3E86741D79D22400379E6B /* Build configuration list for PBXProject "TestApp" */ = {
300 | isa = XCConfigurationList;
301 | buildConfigurations = (
302 | 7F3E868E1D79D22400379E6B /* Debug */,
303 | 7F3E868F1D79D22400379E6B /* Release */,
304 | );
305 | defaultConfigurationIsVisible = 0;
306 | defaultConfigurationName = Release;
307 | };
308 | 7F3E86901D79D22400379E6B /* Build configuration list for PBXNativeTarget "TestApp" */ = {
309 | isa = XCConfigurationList;
310 | buildConfigurations = (
311 | 7F3E86911D79D22400379E6B /* Debug */,
312 | 7F3E86921D79D22400379E6B /* Release */,
313 | );
314 | defaultConfigurationIsVisible = 0;
315 | };
316 | /* End XCConfigurationList section */
317 | };
318 | rootObject = 7F3E86711D79D22400379E6B /* Project object */;
319 | }
320 |
--------------------------------------------------------------------------------
/src/DSYMCreator/DSYMCreator/mach-o/nlist.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
3 | *
4 | * @APPLE_LICENSE_HEADER_START@
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apple Public Source License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://www.opensource.apple.com/apsl/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | *
21 | * @APPLE_LICENSE_HEADER_END@
22 | */
23 | #ifndef _MACHO_NLIST_H_
24 | #define _MACHO_NLIST_H_
25 | /* $NetBSD: nlist.h,v 1.5 1994/10/26 00:56:11 cgd Exp $ */
26 |
27 | /*-
28 | * Copyright (c) 1991, 1993
29 | * The Regents of the University of California. All rights reserved.
30 | * (c) UNIX System Laboratories, Inc.
31 | * All or some portions of this file are derived from material licensed
32 | * to the University of California by American Telephone and Telegraph
33 | * Co. or Unix System Laboratories, Inc. and are reproduced herein with
34 | * the permission of UNIX System Laboratories, Inc.
35 | *
36 | * Redistribution and use in source and binary forms, with or without
37 | * modification, are permitted provided that the following conditions
38 | * are met:
39 | * 1. Redistributions of source code must retain the above copyright
40 | * notice, this list of conditions and the following disclaimer.
41 | * 2. Redistributions in binary form must reproduce the above copyright
42 | * notice, this list of conditions and the following disclaimer in the
43 | * documentation and/or other materials provided with the distribution.
44 | * 3. All advertising materials mentioning features or use of this software
45 | * must display the following acknowledgement:
46 | * This product includes software developed by the University of
47 | * California, Berkeley and its contributors.
48 | * 4. Neither the name of the University nor the names of its contributors
49 | * may be used to endorse or promote products derived from this software
50 | * without specific prior written permission.
51 | *
52 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
53 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
56 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62 | * SUCH DAMAGE.
63 | *
64 | * @(#)nlist.h 8.2 (Berkeley) 1/21/94
65 | */
66 | #include
67 |
68 | /*
69 | * Format of a symbol table entry of a Mach-O file for 32-bit architectures.
70 | * Modified from the BSD format. The modifications from the original format
71 | * were changing n_other (an unused field) to n_sect and the addition of the
72 | * N_SECT type. These modifications are required to support symbols in a larger
73 | * number of sections not just the three sections (text, data and bss) in a BSD
74 | * file.
75 | */
76 | struct nlist {
77 | union {
78 | #ifndef __LP64__
79 | char *n_name; /* for use when in-core */
80 | #endif
81 | uint32_t n_strx; /* index into the string table */
82 | } n_un;
83 | uint8_t n_type; /* type flag, see below */
84 | uint8_t n_sect; /* section number or NO_SECT */
85 | int16_t n_desc; /* see */
86 | uint32_t n_value; /* value of this symbol (or stab offset) */
87 | };
88 |
89 | /*
90 | * This is the symbol table entry structure for 64-bit architectures.
91 | */
92 | struct nlist_64 {
93 | union {
94 | uint32_t n_strx; /* index into the string table */
95 | } n_un;
96 | uint8_t n_type; /* type flag, see below */
97 | uint8_t n_sect; /* section number or NO_SECT */
98 | uint16_t n_desc; /* see */
99 | uint64_t n_value; /* value of this symbol (or stab offset) */
100 | };
101 |
102 | /*
103 | * Symbols with a index into the string table of zero (n_un.n_strx == 0) are
104 | * defined to have a null, "", name. Therefore all string indexes to non null
105 | * names must not have a zero string index. This is bit historical information
106 | * that has never been well documented.
107 | */
108 |
109 | /*
110 | * The n_type field really contains four fields:
111 | * unsigned char N_STAB:3,
112 | * N_PEXT:1,
113 | * N_TYPE:3,
114 | * N_EXT:1;
115 | * which are used via the following masks.
116 | */
117 | #define N_STAB 0xe0 /* if any of these bits set, a symbolic debugging entry */
118 | #define N_PEXT 0x10 /* private external symbol bit */
119 | #define N_TYPE 0x0e /* mask for the type bits */
120 | #define N_EXT 0x01 /* external symbol bit, set for external symbols */
121 |
122 | /*
123 | * Only symbolic debugging entries have some of the N_STAB bits set and if any
124 | * of these bits are set then it is a symbolic debugging entry (a stab). In
125 | * which case then the values of the n_type field (the entire field) are given
126 | * in
127 | */
128 |
129 | /*
130 | * Values for N_TYPE bits of the n_type field.
131 | */
132 | #define N_UNDF 0x0 /* undefined, n_sect == NO_SECT */
133 | #define N_ABS 0x2 /* absolute, n_sect == NO_SECT */
134 | #define N_SECT 0xe /* defined in section number n_sect */
135 | #define N_PBUD 0xc /* prebound undefined (defined in a dylib) */
136 | #define N_INDR 0xa /* indirect */
137 |
138 | /*
139 | * If the type is N_INDR then the symbol is defined to be the same as another
140 | * symbol. In this case the n_value field is an index into the string table
141 | * of the other symbol's name. When the other symbol is defined then they both
142 | * take on the defined type and value.
143 | */
144 |
145 | /*
146 | * If the type is N_SECT then the n_sect field contains an ordinal of the
147 | * section the symbol is defined in. The sections are numbered from 1 and
148 | * refer to sections in order they appear in the load commands for the file
149 | * they are in. This means the same ordinal may very well refer to different
150 | * sections in different files.
151 | *
152 | * The n_value field for all symbol table entries (including N_STAB's) gets
153 | * updated by the link editor based on the value of it's n_sect field and where
154 | * the section n_sect references gets relocated. If the value of the n_sect
155 | * field is NO_SECT then it's n_value field is not changed by the link editor.
156 | */
157 | #define NO_SECT 0 /* symbol is not in any section */
158 | #define MAX_SECT 255 /* 1 thru 255 inclusive */
159 |
160 | /*
161 | * Common symbols are represented by undefined (N_UNDF) external (N_EXT) types
162 | * who's values (n_value) are non-zero. In which case the value of the n_value
163 | * field is the size (in bytes) of the common symbol. The n_sect field is set
164 | * to NO_SECT. The alignment of a common symbol may be set as a power of 2
165 | * between 2^1 and 2^15 as part of the n_desc field using the macros below. If
166 | * the alignment is not set (a value of zero) then natural alignment based on
167 | * the size is used.
168 | */
169 | #define GET_COMM_ALIGN(n_desc) (((n_desc) >> 8) & 0x0f)
170 | #define SET_COMM_ALIGN(n_desc,align) \
171 | (n_desc) = (((n_desc) & 0xf0ff) | (((align) & 0x0f) << 8))
172 |
173 | /*
174 | * To support the lazy binding of undefined symbols in the dynamic link-editor,
175 | * the undefined symbols in the symbol table (the nlist structures) are marked
176 | * with the indication if the undefined reference is a lazy reference or
177 | * non-lazy reference. If both a non-lazy reference and a lazy reference is
178 | * made to the same symbol the non-lazy reference takes precedence. A reference
179 | * is lazy only when all references to that symbol are made through a symbol
180 | * pointer in a lazy symbol pointer section.
181 | *
182 | * The implementation of marking nlist structures in the symbol table for
183 | * undefined symbols will be to use some of the bits of the n_desc field as a
184 | * reference type. The mask REFERENCE_TYPE will be applied to the n_desc field
185 | * of an nlist structure for an undefined symbol to determine the type of
186 | * undefined reference (lazy or non-lazy).
187 | *
188 | * The constants for the REFERENCE FLAGS are propagated to the reference table
189 | * in a shared library file. In that case the constant for a defined symbol,
190 | * REFERENCE_FLAG_DEFINED, is also used.
191 | */
192 | /* Reference type bits of the n_desc field of undefined symbols */
193 | #define REFERENCE_TYPE 0x7
194 | /* types of references */
195 | #define REFERENCE_FLAG_UNDEFINED_NON_LAZY 0
196 | #define REFERENCE_FLAG_UNDEFINED_LAZY 1
197 | #define REFERENCE_FLAG_DEFINED 2
198 | #define REFERENCE_FLAG_PRIVATE_DEFINED 3
199 | #define REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY 4
200 | #define REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY 5
201 |
202 | /*
203 | * To simplify stripping of objects that use are used with the dynamic link
204 | * editor, the static link editor marks the symbols defined an object that are
205 | * referenced by a dynamicly bound object (dynamic shared libraries, bundles).
206 | * With this marking strip knows not to strip these symbols.
207 | */
208 | #define REFERENCED_DYNAMICALLY 0x0010
209 |
210 | /*
211 | * For images created by the static link editor with the -twolevel_namespace
212 | * option in effect the flags field of the mach header is marked with
213 | * MH_TWOLEVEL. And the binding of the undefined references of the image are
214 | * determined by the static link editor. Which library an undefined symbol is
215 | * bound to is recorded by the static linker in the high 8 bits of the n_desc
216 | * field using the SET_LIBRARY_ORDINAL macro below. The ordinal recorded
217 | * references the libraries listed in the Mach-O's LC_LOAD_DYLIB,
218 | * LC_LOAD_WEAK_DYLIB, LC_REEXPORT_DYLIB, LC_LOAD_UPWARD_DYLIB, and
219 | * LC_LAZY_LOAD_DYLIB, etc. load commands in the order they appear in the
220 | * headers. The library ordinals start from 1.
221 | * For a dynamic library that is built as a two-level namespace image the
222 | * undefined references from module defined in another use the same nlist struct
223 | * an in that case SELF_LIBRARY_ORDINAL is used as the library ordinal. For
224 | * defined symbols in all images they also must have the library ordinal set to
225 | * SELF_LIBRARY_ORDINAL. The EXECUTABLE_ORDINAL refers to the executable
226 | * image for references from plugins that refer to the executable that loads
227 | * them.
228 | *
229 | * The DYNAMIC_LOOKUP_ORDINAL is for undefined symbols in a two-level namespace
230 | * image that are looked up by the dynamic linker with flat namespace semantics.
231 | * This ordinal was added as a feature in Mac OS X 10.3 by reducing the
232 | * value of MAX_LIBRARY_ORDINAL by one. So it is legal for existing binaries
233 | * or binaries built with older tools to have 0xfe (254) dynamic libraries. In
234 | * this case the ordinal value 0xfe (254) must be treated as a library ordinal
235 | * for compatibility.
236 | */
237 | #define GET_LIBRARY_ORDINAL(n_desc) (((n_desc) >> 8) & 0xff)
238 | #define SET_LIBRARY_ORDINAL(n_desc,ordinal) \
239 | (n_desc) = (((n_desc) & 0x00ff) | (((ordinal) & 0xff) << 8))
240 | #define SELF_LIBRARY_ORDINAL 0x0
241 | #define MAX_LIBRARY_ORDINAL 0xfd
242 | #define DYNAMIC_LOOKUP_ORDINAL 0xfe
243 | #define EXECUTABLE_ORDINAL 0xff
244 |
245 | /*
246 | * The bit 0x0020 of the n_desc field is used for two non-overlapping purposes
247 | * and has two different symbolic names, N_NO_DEAD_STRIP and N_DESC_DISCARDED.
248 | */
249 |
250 | /*
251 | * The N_NO_DEAD_STRIP bit of the n_desc field only ever appears in a
252 | * relocatable .o file (MH_OBJECT filetype). And is used to indicate to the
253 | * static link editor it is never to dead strip the symbol.
254 | */
255 | #define N_NO_DEAD_STRIP 0x0020 /* symbol is not to be dead stripped */
256 |
257 | /*
258 | * The N_DESC_DISCARDED bit of the n_desc field never appears in linked image.
259 | * But is used in very rare cases by the dynamic link editor to mark an in
260 | * memory symbol as discared and longer used for linking.
261 | */
262 | #define N_DESC_DISCARDED 0x0020 /* symbol is discarded */
263 |
264 | /*
265 | * The N_WEAK_REF bit of the n_desc field indicates to the dynamic linker that
266 | * the undefined symbol is allowed to be missing and is to have the address of
267 | * zero when missing.
268 | */
269 | #define N_WEAK_REF 0x0040 /* symbol is weak referenced */
270 |
271 | /*
272 | * The N_WEAK_DEF bit of the n_desc field indicates to the static and dynamic
273 | * linkers that the symbol definition is weak, allowing a non-weak symbol to
274 | * also be used which causes the weak definition to be discared. Currently this
275 | * is only supported for symbols in coalesed sections.
276 | */
277 | #define N_WEAK_DEF 0x0080 /* coalesed symbol is a weak definition */
278 |
279 | /*
280 | * The N_REF_TO_WEAK bit of the n_desc field indicates to the dynamic linker
281 | * that the undefined symbol should be resolved using flat namespace searching.
282 | */
283 | #define N_REF_TO_WEAK 0x0080 /* reference to a weak symbol */
284 |
285 | /*
286 | * The N_ARM_THUMB_DEF bit of the n_desc field indicates that the symbol is
287 | * a defintion of a Thumb function.
288 | */
289 | #define N_ARM_THUMB_DEF 0x0008 /* symbol is a Thumb function (ARM) */
290 |
291 | /*
292 | * The N_SYMBOL_RESOLVER bit of the n_desc field indicates that the
293 | * that the function is actually a resolver function and should
294 | * be called to get the address of the real function to use.
295 | * This bit is only available in .o files (MH_OBJECT filetype)
296 | */
297 | #define N_SYMBOL_RESOLVER 0x0100
298 |
299 | #ifndef __STRICT_BSD__
300 | #ifdef __cplusplus
301 | extern "C" {
302 | #endif /* __cplusplus */
303 | /*
304 | * The function nlist(3) from the C library.
305 | */
306 | extern int nlist (const char *filename, struct nlist *list);
307 | #ifdef __cplusplus
308 | }
309 | #endif /* __cplusplus */
310 | #endif /* __STRICT_BSD__ */
311 |
312 | #endif /* _MACHO_LIST_H_ */
313 |
--------------------------------------------------------------------------------
/src/DSYMCreator/DSYMCreator.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 7F0C95A01D77C77C0066A1F4 /* dwarf_dummy_debug_line_section.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7F0C959E1D77C77C0066A1F4 /* dwarf_dummy_debug_line_section.cpp */; };
11 | 7F0C95A31D77D4C40066A1F4 /* dwarf_debug_abbrev_section.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7F0C95A11D77D4C40066A1F4 /* dwarf_debug_abbrev_section.cpp */; };
12 | 7F0C95AB1D78340A0066A1F4 /* exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7F0C95A91D78340A0066A1F4 /* exception.cpp */; };
13 | 7F39B0181E1F9BB100859541 /* string_table.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7F39B0171E1F9BB100859541 /* string_table.cpp */; };
14 | 7F866B621D76A1430028592C /* libgflags.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F866B431D76A1430028592C /* libgflags.a */; };
15 | 7F866B671D76A1430028592C /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7F866B5B1D76A1430028592C /* main.mm */; };
16 | 7F866B681D76A1430028592C /* util.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7F866B5D1D76A1430028592C /* util.cpp */; };
17 | /* End PBXBuildFile section */
18 |
19 | /* Begin PBXFileReference section */
20 | 7F0C959E1D77C77C0066A1F4 /* dwarf_dummy_debug_line_section.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf_dummy_debug_line_section.cpp; path = DSYMCreator/dwarf_dummy_debug_line_section.cpp; sourceTree = ""; };
21 | 7F0C959F1D77C77C0066A1F4 /* dwarf_dummy_debug_line_section.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf_dummy_debug_line_section.h; path = DSYMCreator/dwarf_dummy_debug_line_section.h; sourceTree = ""; };
22 | 7F0C95A11D77D4C40066A1F4 /* dwarf_debug_abbrev_section.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf_debug_abbrev_section.cpp; path = DSYMCreator/dwarf_debug_abbrev_section.cpp; sourceTree = ""; };
23 | 7F0C95A21D77D4C40066A1F4 /* dwarf_debug_abbrev_section.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf_debug_abbrev_section.h; path = DSYMCreator/dwarf_debug_abbrev_section.h; sourceTree = ""; };
24 | 7F0C95A61D77D9CD0066A1F4 /* dwarf_debug_info_section.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf_debug_info_section.h; path = DSYMCreator/dwarf_debug_info_section.h; sourceTree = ""; };
25 | 7F0C95A81D77D9DE0066A1F4 /* dwarf.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = dwarf.h; path = DSYMCreator/dwarf.h; sourceTree = ""; };
26 | 7F0C95A91D78340A0066A1F4 /* exception.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = exception.cpp; path = DSYMCreator/exception.cpp; sourceTree = SOURCE_ROOT; };
27 | 7F0C95AA1D78340A0066A1F4 /* exception.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = exception.h; path = DSYMCreator/exception.h; sourceTree = SOURCE_ROOT; };
28 | 7F39B00F1E1E4E0F00859541 /* common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = common.h; path = DSYMCreator/common.h; sourceTree = ""; };
29 | 7F39B0101E1F2F3B00859541 /* macho_type_wrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = macho_type_wrapper.h; path = DSYMCreator/macho_type_wrapper.h; sourceTree = ""; };
30 | 7F39B0171E1F9BB100859541 /* string_table.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = string_table.cpp; path = DSYMCreator/string_table.cpp; sourceTree = ""; };
31 | 7F866B2B1D76A0E20028592C /* DSYMCreator */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = DSYMCreator; sourceTree = BUILT_PRODUCTS_DIR; };
32 | 7F866B3B1D76A1430028592C /* gflags.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gflags.h; sourceTree = ""; };
33 | 7F866B3C1D76A1430028592C /* gflags_completions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gflags_completions.h; sourceTree = ""; };
34 | 7F866B3D1D76A1430028592C /* gflags_declare.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gflags_declare.h; sourceTree = ""; };
35 | 7F866B3F1D76A1430028592C /* gflags.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gflags.h; sourceTree = ""; };
36 | 7F866B401D76A1430028592C /* gflags_completions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gflags_completions.h; sourceTree = ""; };
37 | 7F866B421D76A1430028592C /* libgflags.2.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libgflags.2.dylib; sourceTree = ""; };
38 | 7F866B431D76A1430028592C /* libgflags.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgflags.a; sourceTree = ""; };
39 | 7F866B441D76A1430028592C /* libgflags.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libgflags.dylib; sourceTree = ""; };
40 | 7F866B451D76A1430028592C /* libgflags_nothreads.2.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libgflags_nothreads.2.dylib; sourceTree = ""; };
41 | 7F866B461D76A1430028592C /* libgflags_nothreads.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgflags_nothreads.a; sourceTree = ""; };
42 | 7F866B471D76A1430028592C /* libgflags_nothreads.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libgflags_nothreads.dylib; sourceTree = ""; };
43 | 7F866B491D76A1430028592C /* libgflags.pc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = libgflags.pc; sourceTree = ""; };
44 | 7F866B4A1D76A1430028592C /* libgflags_nothreads.pc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = libgflags_nothreads.pc; sourceTree = ""; };
45 | 7F866B4C1D76A1430028592C /* arch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = arch.h; sourceTree = ""; };
46 | 7F866B4E1D76A1430028592C /* reloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = reloc.h; sourceTree = ""; };
47 | 7F866B501D76A1430028592C /* reloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = reloc.h; sourceTree = ""; };
48 | 7F866B511D76A1430028592C /* compact_unwind_encoding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = compact_unwind_encoding.h; sourceTree = ""; };
49 | 7F866B521D76A1430028592C /* fat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fat.h; sourceTree = ""; };
50 | 7F866B531D76A1430028592C /* loader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = loader.h; sourceTree = ""; };
51 | 7F866B541D76A1430028592C /* nlist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = nlist.h; sourceTree = ""; };
52 | 7F866B551D76A1430028592C /* ranlib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ranlib.h; sourceTree = ""; };
53 | 7F866B561D76A1430028592C /* reloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = reloc.h; sourceTree = ""; };
54 | 7F866B571D76A1430028592C /* swap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = swap.h; sourceTree = ""; };
55 | 7F866B591D76A1430028592C /* reloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = reloc.h; sourceTree = ""; };
56 | 7F866B5B1D76A1430028592C /* main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = main.mm; path = DSYMCreator/main.mm; sourceTree = ""; };
57 | 7F866B5D1D76A1430028592C /* util.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = util.cpp; path = DSYMCreator/util.cpp; sourceTree = ""; };
58 | 7F866B5E1D76A1430028592C /* util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = util.h; path = DSYMCreator/util.h; sourceTree = ""; };
59 | 7F866B6B1D76A5020028592C /* string_table.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = string_table.h; path = DSYMCreator/string_table.h; sourceTree = ""; };
60 | 7F866B6D1D76B2BD0028592C /* symbol_table.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = symbol_table.h; path = DSYMCreator/symbol_table.h; sourceTree = ""; };
61 | 7F866B751D76BC0F0028592C /* macho.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = macho.h; path = DSYMCreator/macho.h; sourceTree = ""; };
62 | 7F866B781D76BF1A0028592C /* symbol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = symbol.h; path = DSYMCreator/symbol.h; sourceTree = ""; };
63 | /* End PBXFileReference section */
64 |
65 | /* Begin PBXFrameworksBuildPhase section */
66 | 7F866B281D76A0E20028592C /* Frameworks */ = {
67 | isa = PBXFrameworksBuildPhase;
68 | buildActionMask = 2147483647;
69 | files = (
70 | 7F866B621D76A1430028592C /* libgflags.a in Frameworks */,
71 | );
72 | runOnlyForDeploymentPostprocessing = 0;
73 | };
74 | /* End PBXFrameworksBuildPhase section */
75 |
76 | /* Begin PBXGroup section */
77 | 7F866B221D76A0E20028592C = {
78 | isa = PBXGroup;
79 | children = (
80 | 7F866B381D76A1430028592C /* gflags */,
81 | 7F866B4B1D76A1430028592C /* mach-o */,
82 | 7F0C95A91D78340A0066A1F4 /* exception.cpp */,
83 | 7F0C95AA1D78340A0066A1F4 /* exception.h */,
84 | 7F866B5B1D76A1430028592C /* main.mm */,
85 | 7F866B5D1D76A1430028592C /* util.cpp */,
86 | 7F866B5E1D76A1430028592C /* util.h */,
87 | 7F866B781D76BF1A0028592C /* symbol.h */,
88 | 7F866B6B1D76A5020028592C /* string_table.h */,
89 | 7F39B0171E1F9BB100859541 /* string_table.cpp */,
90 | 7F866B6D1D76B2BD0028592C /* symbol_table.h */,
91 | 7F39B00F1E1E4E0F00859541 /* common.h */,
92 | 7F0C95A81D77D9DE0066A1F4 /* dwarf.h */,
93 | 7F0C959E1D77C77C0066A1F4 /* dwarf_dummy_debug_line_section.cpp */,
94 | 7F0C959F1D77C77C0066A1F4 /* dwarf_dummy_debug_line_section.h */,
95 | 7F0C95A11D77D4C40066A1F4 /* dwarf_debug_abbrev_section.cpp */,
96 | 7F0C95A21D77D4C40066A1F4 /* dwarf_debug_abbrev_section.h */,
97 | 7F0C95A61D77D9CD0066A1F4 /* dwarf_debug_info_section.h */,
98 | 7F866B751D76BC0F0028592C /* macho.h */,
99 | 7F39B0101E1F2F3B00859541 /* macho_type_wrapper.h */,
100 | 7F866B2C1D76A0E20028592C /* Products */,
101 | );
102 | sourceTree = "";
103 | };
104 | 7F866B2C1D76A0E20028592C /* Products */ = {
105 | isa = PBXGroup;
106 | children = (
107 | 7F866B2B1D76A0E20028592C /* DSYMCreator */,
108 | );
109 | name = Products;
110 | sourceTree = "";
111 | };
112 | 7F866B381D76A1430028592C /* gflags */ = {
113 | isa = PBXGroup;
114 | children = (
115 | 7F866B391D76A1430028592C /* include */,
116 | 7F866B411D76A1430028592C /* lib */,
117 | );
118 | name = gflags;
119 | path = DSYMCreator/gflags;
120 | sourceTree = "";
121 | };
122 | 7F866B391D76A1430028592C /* include */ = {
123 | isa = PBXGroup;
124 | children = (
125 | 7F866B3A1D76A1430028592C /* gflags */,
126 | 7F866B3E1D76A1430028592C /* google */,
127 | );
128 | path = include;
129 | sourceTree = "";
130 | };
131 | 7F866B3A1D76A1430028592C /* gflags */ = {
132 | isa = PBXGroup;
133 | children = (
134 | 7F866B3B1D76A1430028592C /* gflags.h */,
135 | 7F866B3C1D76A1430028592C /* gflags_completions.h */,
136 | 7F866B3D1D76A1430028592C /* gflags_declare.h */,
137 | );
138 | path = gflags;
139 | sourceTree = "";
140 | };
141 | 7F866B3E1D76A1430028592C /* google */ = {
142 | isa = PBXGroup;
143 | children = (
144 | 7F866B3F1D76A1430028592C /* gflags.h */,
145 | 7F866B401D76A1430028592C /* gflags_completions.h */,
146 | );
147 | path = google;
148 | sourceTree = "";
149 | };
150 | 7F866B411D76A1430028592C /* lib */ = {
151 | isa = PBXGroup;
152 | children = (
153 | 7F866B421D76A1430028592C /* libgflags.2.dylib */,
154 | 7F866B431D76A1430028592C /* libgflags.a */,
155 | 7F866B441D76A1430028592C /* libgflags.dylib */,
156 | 7F866B451D76A1430028592C /* libgflags_nothreads.2.dylib */,
157 | 7F866B461D76A1430028592C /* libgflags_nothreads.a */,
158 | 7F866B471D76A1430028592C /* libgflags_nothreads.dylib */,
159 | 7F866B481D76A1430028592C /* pkgconfig */,
160 | );
161 | path = lib;
162 | sourceTree = "";
163 | };
164 | 7F866B481D76A1430028592C /* pkgconfig */ = {
165 | isa = PBXGroup;
166 | children = (
167 | 7F866B491D76A1430028592C /* libgflags.pc */,
168 | 7F866B4A1D76A1430028592C /* libgflags_nothreads.pc */,
169 | );
170 | path = pkgconfig;
171 | sourceTree = "";
172 | };
173 | 7F866B4B1D76A1430028592C /* mach-o */ = {
174 | isa = PBXGroup;
175 | children = (
176 | 7F866B4C1D76A1430028592C /* arch.h */,
177 | 7F866B4D1D76A1430028592C /* arm */,
178 | 7F866B4F1D76A1430028592C /* arm64 */,
179 | 7F866B511D76A1430028592C /* compact_unwind_encoding.h */,
180 | 7F866B521D76A1430028592C /* fat.h */,
181 | 7F866B531D76A1430028592C /* loader.h */,
182 | 7F866B541D76A1430028592C /* nlist.h */,
183 | 7F866B551D76A1430028592C /* ranlib.h */,
184 | 7F866B561D76A1430028592C /* reloc.h */,
185 | 7F866B571D76A1430028592C /* swap.h */,
186 | 7F866B581D76A1430028592C /* x86_64 */,
187 | );
188 | name = "mach-o";
189 | path = "DSYMCreator/mach-o";
190 | sourceTree = "";
191 | };
192 | 7F866B4D1D76A1430028592C /* arm */ = {
193 | isa = PBXGroup;
194 | children = (
195 | 7F866B4E1D76A1430028592C /* reloc.h */,
196 | );
197 | path = arm;
198 | sourceTree = "";
199 | };
200 | 7F866B4F1D76A1430028592C /* arm64 */ = {
201 | isa = PBXGroup;
202 | children = (
203 | 7F866B501D76A1430028592C /* reloc.h */,
204 | );
205 | path = arm64;
206 | sourceTree = "";
207 | };
208 | 7F866B581D76A1430028592C /* x86_64 */ = {
209 | isa = PBXGroup;
210 | children = (
211 | 7F866B591D76A1430028592C /* reloc.h */,
212 | );
213 | path = x86_64;
214 | sourceTree = "";
215 | };
216 | /* End PBXGroup section */
217 |
218 | /* Begin PBXNativeTarget section */
219 | 7F866B2A1D76A0E20028592C /* DSYMCreator */ = {
220 | isa = PBXNativeTarget;
221 | buildConfigurationList = 7F866B321D76A0E20028592C /* Build configuration list for PBXNativeTarget "DSYMCreator" */;
222 | buildPhases = (
223 | 7F866B271D76A0E20028592C /* Sources */,
224 | 7F866B281D76A0E20028592C /* Frameworks */,
225 | 7F9554E61D87D78300207AEB /* ShellScript */,
226 | );
227 | buildRules = (
228 | );
229 | dependencies = (
230 | );
231 | name = DSYMCreator;
232 | productName = DSYMCreator;
233 | productReference = 7F866B2B1D76A0E20028592C /* DSYMCreator */;
234 | productType = "com.apple.product-type.tool";
235 | };
236 | /* End PBXNativeTarget section */
237 |
238 | /* Begin PBXProject section */
239 | 7F866B231D76A0E20028592C /* Project object */ = {
240 | isa = PBXProject;
241 | attributes = {
242 | LastUpgradeCheck = 0800;
243 | TargetAttributes = {
244 | 7F866B2A1D76A0E20028592C = {
245 | CreatedOnToolsVersion = 7.3.1;
246 | };
247 | };
248 | };
249 | buildConfigurationList = 7F866B261D76A0E20028592C /* Build configuration list for PBXProject "DSYMCreator" */;
250 | compatibilityVersion = "Xcode 3.2";
251 | developmentRegion = English;
252 | hasScannedForEncodings = 0;
253 | knownRegions = (
254 | en,
255 | );
256 | mainGroup = 7F866B221D76A0E20028592C;
257 | productRefGroup = 7F866B2C1D76A0E20028592C /* Products */;
258 | projectDirPath = "";
259 | projectRoot = "";
260 | targets = (
261 | 7F866B2A1D76A0E20028592C /* DSYMCreator */,
262 | );
263 | };
264 | /* End PBXProject section */
265 |
266 | /* Begin PBXShellScriptBuildPhase section */
267 | 7F9554E61D87D78300207AEB /* ShellScript */ = {
268 | isa = PBXShellScriptBuildPhase;
269 | buildActionMask = 2147483647;
270 | files = (
271 | );
272 | inputPaths = (
273 | );
274 | outputPaths = (
275 | );
276 | runOnlyForDeploymentPostprocessing = 0;
277 | shellPath = /bin/sh;
278 | shellScript = "echo \"cp -f \\\"${CONFIGURATION_BUILD_DIR}/DSYMCreator\\\" \\\"${SRCROOT}/../../toolchain/\\\"\"\ncp -f \"${CONFIGURATION_BUILD_DIR}/DSYMCreator\" \"${SRCROOT}/../../toolchain/\"";
279 | };
280 | /* End PBXShellScriptBuildPhase section */
281 |
282 | /* Begin PBXSourcesBuildPhase section */
283 | 7F866B271D76A0E20028592C /* Sources */ = {
284 | isa = PBXSourcesBuildPhase;
285 | buildActionMask = 2147483647;
286 | files = (
287 | 7F866B671D76A1430028592C /* main.mm in Sources */,
288 | 7F0C95A01D77C77C0066A1F4 /* dwarf_dummy_debug_line_section.cpp in Sources */,
289 | 7F39B0181E1F9BB100859541 /* string_table.cpp in Sources */,
290 | 7F866B681D76A1430028592C /* util.cpp in Sources */,
291 | 7F0C95A31D77D4C40066A1F4 /* dwarf_debug_abbrev_section.cpp in Sources */,
292 | 7F0C95AB1D78340A0066A1F4 /* exception.cpp in Sources */,
293 | );
294 | runOnlyForDeploymentPostprocessing = 0;
295 | };
296 | /* End PBXSourcesBuildPhase section */
297 |
298 | /* Begin XCBuildConfiguration section */
299 | 7F866B301D76A0E20028592C /* Debug */ = {
300 | isa = XCBuildConfiguration;
301 | buildSettings = {
302 | ALWAYS_SEARCH_USER_PATHS = NO;
303 | CLANG_ANALYZER_NONNULL = YES;
304 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
305 | CLANG_CXX_LIBRARY = "libc++";
306 | CLANG_ENABLE_MODULES = YES;
307 | CLANG_ENABLE_OBJC_ARC = YES;
308 | CLANG_WARN_BOOL_CONVERSION = YES;
309 | CLANG_WARN_CONSTANT_CONVERSION = YES;
310 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
311 | CLANG_WARN_EMPTY_BODY = YES;
312 | CLANG_WARN_ENUM_CONVERSION = YES;
313 | CLANG_WARN_INFINITE_RECURSION = YES;
314 | CLANG_WARN_INT_CONVERSION = YES;
315 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
316 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
317 | CLANG_WARN_UNREACHABLE_CODE = YES;
318 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
319 | CODE_SIGN_IDENTITY = "-";
320 | COPY_PHASE_STRIP = NO;
321 | DEBUG_INFORMATION_FORMAT = dwarf;
322 | ENABLE_STRICT_OBJC_MSGSEND = YES;
323 | ENABLE_TESTABILITY = YES;
324 | GCC_C_LANGUAGE_STANDARD = gnu99;
325 | GCC_DYNAMIC_NO_PIC = NO;
326 | GCC_NO_COMMON_BLOCKS = YES;
327 | GCC_OPTIMIZATION_LEVEL = 0;
328 | GCC_PREPROCESSOR_DEFINITIONS = (
329 | "DEBUG=1",
330 | "$(inherited)",
331 | );
332 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
333 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
334 | GCC_WARN_UNDECLARED_SELECTOR = YES;
335 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
336 | GCC_WARN_UNUSED_FUNCTION = YES;
337 | GCC_WARN_UNUSED_VARIABLE = YES;
338 | MACOSX_DEPLOYMENT_TARGET = 10.11;
339 | MTL_ENABLE_DEBUG_INFO = YES;
340 | ONLY_ACTIVE_ARCH = YES;
341 | SDKROOT = macosx;
342 | };
343 | name = Debug;
344 | };
345 | 7F866B311D76A0E20028592C /* Release */ = {
346 | isa = XCBuildConfiguration;
347 | buildSettings = {
348 | ALWAYS_SEARCH_USER_PATHS = NO;
349 | CLANG_ANALYZER_NONNULL = YES;
350 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
351 | CLANG_CXX_LIBRARY = "libc++";
352 | CLANG_ENABLE_MODULES = YES;
353 | CLANG_ENABLE_OBJC_ARC = YES;
354 | CLANG_WARN_BOOL_CONVERSION = YES;
355 | CLANG_WARN_CONSTANT_CONVERSION = YES;
356 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
357 | CLANG_WARN_EMPTY_BODY = YES;
358 | CLANG_WARN_ENUM_CONVERSION = YES;
359 | CLANG_WARN_INFINITE_RECURSION = YES;
360 | CLANG_WARN_INT_CONVERSION = YES;
361 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
362 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
363 | CLANG_WARN_UNREACHABLE_CODE = YES;
364 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
365 | CODE_SIGN_IDENTITY = "-";
366 | COPY_PHASE_STRIP = NO;
367 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
368 | ENABLE_NS_ASSERTIONS = NO;
369 | ENABLE_STRICT_OBJC_MSGSEND = YES;
370 | GCC_C_LANGUAGE_STANDARD = gnu99;
371 | GCC_NO_COMMON_BLOCKS = YES;
372 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
373 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
374 | GCC_WARN_UNDECLARED_SELECTOR = YES;
375 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
376 | GCC_WARN_UNUSED_FUNCTION = YES;
377 | GCC_WARN_UNUSED_VARIABLE = YES;
378 | MACOSX_DEPLOYMENT_TARGET = 10.11;
379 | MTL_ENABLE_DEBUG_INFO = NO;
380 | SDKROOT = macosx;
381 | };
382 | name = Release;
383 | };
384 | 7F866B331D76A0E20028592C /* Debug */ = {
385 | isa = XCBuildConfiguration;
386 | buildSettings = {
387 | HEADER_SEARCH_PATHS = ./DSYMCreator/gflags/include/;
388 | LIBRARY_SEARCH_PATHS = (
389 | "$(inherited)",
390 | "$(PROJECT_DIR)/DSYMCreator/gflags/lib",
391 | );
392 | PRODUCT_NAME = "$(TARGET_NAME)";
393 | };
394 | name = Debug;
395 | };
396 | 7F866B341D76A0E20028592C /* Release */ = {
397 | isa = XCBuildConfiguration;
398 | buildSettings = {
399 | HEADER_SEARCH_PATHS = ./DSYMCreator/gflags/include/;
400 | LIBRARY_SEARCH_PATHS = (
401 | "$(inherited)",
402 | "$(PROJECT_DIR)/DSYMCreator/gflags/lib",
403 | );
404 | PRODUCT_NAME = "$(TARGET_NAME)";
405 | };
406 | name = Release;
407 | };
408 | /* End XCBuildConfiguration section */
409 |
410 | /* Begin XCConfigurationList section */
411 | 7F866B261D76A0E20028592C /* Build configuration list for PBXProject "DSYMCreator" */ = {
412 | isa = XCConfigurationList;
413 | buildConfigurations = (
414 | 7F866B301D76A0E20028592C /* Debug */,
415 | 7F866B311D76A0E20028592C /* Release */,
416 | );
417 | defaultConfigurationIsVisible = 0;
418 | defaultConfigurationName = Release;
419 | };
420 | 7F866B321D76A0E20028592C /* Build configuration list for PBXNativeTarget "DSYMCreator" */ = {
421 | isa = XCConfigurationList;
422 | buildConfigurations = (
423 | 7F866B331D76A0E20028592C /* Debug */,
424 | 7F866B341D76A0E20028592C /* Release */,
425 | );
426 | defaultConfigurationIsVisible = 0;
427 | defaultConfigurationName = Release;
428 | };
429 | /* End XCConfigurationList section */
430 | };
431 | rootObject = 7F866B231D76A0E20028592C /* Project object */;
432 | }
433 |
--------------------------------------------------------------------------------