上篇文章介绍了 MachO 文件的结构,你可能注意到其中的 LC_LOAD_DYLINKER 是 dyld, LC_MAIN 加载命令就是加载程序的主入口。这篇文章就详细讲讲 App 的加载过程。
MachO 可执行文件类型
Xcode build 出的 .app 包中可以看到一个 exec 可执行文件(所有 .o文件集合),同样是一个 MachO 文件,filetype 就是 MH_EXECUTE 类型。
MachOView中查看如下。
上一篇文章中提到了如何自建一个 Crash 平台,其中通过对系统库 (MachO) 的结构解析来寻找崩溃符号。这篇文章就具体讲讲 MachO 文件的结构分析。
iOS中,我们平时看见的 MachO 文件你肯定不陌生,包括静态库(.a)、dSym (yourAppName.dSym)、系统动态库 (/usr/lib/libobjc.A.dylib)、可执行文件等。具体类型下面会讲到。
MachO 二进制文件可以根据前四字节的magic_num来判断是不是 Fat (包含一个或多个架构,有 Fat_Header), 每个架构同样是的 MachO文件。可以这样比喻,相当于对一个或多个文件用文件夹压缩了下。zip 包相当于 Fat,文件是 Thin。每个文件的内部结构式一致的。
可以看到 Fat 多了 Fat_Header信息, 信息中包含架构数,每个架构的基本信息。
Fat 可以通过lipo -thin 命令分解出 thin。 thin 也可以合并成 Fat。
1 | //分解 |
【译】Symbolicating an iOS Crash Report
通常,当您收到来自iTunes连接的崩溃报告或提供移动崩溃收集和报告的第三方服务(如Apteligent)时,该服务将负责为您提供符号化后的崩溃。如果你没有上传符号,你可能会发现自己有一个非符号化的崩溃,没有别的东西可以继续。这样的崩溃文件对于调试可能影响大量用户的问题并不是非常有用。
在这种情况下,您必须通过将回溯堆栈地址解析为符号来对崩溃报告进行符号化,以获取有关崩溃的有用信息。
幸运的是,完全有可能手动符号化崩溃报告。本文将概述您需要的信息,向您展示如何解释崩溃报告,并查看OSX和XCode上可用的一些工具来符号化崩溃。
崩溃报告中只有两个部分与符号化异常跟踪相关。第一个是 Exception Backtrace 部分。这显示了崩溃时应用程序的调用堆栈。此特定崩溃日志片段显示了我们的 ApteligentExampleApp 应用程序内部崩溃的回溯。
1 | Last Exception Backtrace: |
如下代码 .h .m文件1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32//TestClang.h
@interface TestClang : NSObject
+ (void)testBlcok;
@end
//TestClang.m
#import "TestClang.h"
static int numGlobel = 29;
@implementation TestClang
+ (void)testBlcok {
//没有截获局部变量 __NSGlobalBlock__
void(^block1)(void) = ^{
NSLog(@"just a block");
};
NSLog(@" block1 = %@", block1);
block1();
static int numStatic = 12;
int num = 10;
__block int numBlock = 19;
__block int numBlock2 = 30;
__block int numBlockTest = 30;
void(^block2)(void) = ^{
NSLog(@"just a block === %d, numStatic = %d numGlobel = %d numBlock=%d numBlock2=%d numBlockTest = %d", num,numStatic,numGlobel,numBlock,numBlock2,numBlockTest);
};
num = 33;
numStatic = 121;
numGlobel = 129;
numBlock = 22222;
block2();
NSLog(@"block2 = %@", block2);
}
@end
执行:xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc TestClang.m
不要引用其他头文件,以免导出报Error
目录下生成了一个TestClang.cpp文件
1 | //_C_ 表示为类方法 _I_ 为实例方法 |
Xcode 可以给资源打 tag,被打 tag 的资源在打包时不会打到包内。需要时下载,测试时可以使用自己的服务器,但是发布到 AppStore 时需要托管到苹果的服务器。
苹果的 On-Demand Resource 文档
了解到了苹果 On-Demand Resource 机制,我们可以结合Resource Tags 下的资源不会打包到 ipa 包的特性。设计一套自己的下发机制。
行程时间: 9月7日 - 9月10日
提前一个月的时间定了吉祥航空的往返航班,2700左右/人。出发时下午5点,回程是下午7点。
行程酒店:美国村门巴公寓酒店,酒店外就是沙滩。
冲绳9月份是台风季,天气说不准,最好提前做下攻略。
启程,第一天出发的时间是北京时间5点,到冲绳大概2个小时,不过因为冲绳是早一个小时的,所以到冲绳是当地时间晚上8点了。预订的接机去美国村的酒店,400RMB。
抵达冲绳从机场出来就感觉非常干净,各种建筑街道啥的都非常干净,各种基础设施做的也很贴心。约的日本的司机来接机的,人很有礼貌,会一点英语, 大概花了50分钟左右到美国村。入住之后就去觅食,找到了上一波推荐去的一家叫 xx食堂的店,吃了猪豚骨饭,另外在冲绳大众点评也挺好用(^__^)。
美国村夜景