乐趣区

关于前端:iOS-崩溃日志在线符号化实践

导读:本文将介绍什么是符号化?如何做本地符号化?为什么做在线符号化?

全文 14328 字,预计浏览工夫 28 分钟。

一、什么是符号化?

在日常开发中,利用难免会产生解体。通常,咱们间接从用户导出来的解体日志都是未符号化或者局部符号化的,都是一堆十六进制内存地址的汇合,可读性较差。未符号化或者局部符号化的解体日志对闪退问题的解决简直毫无帮忙,如下所示:

Last Exception Backtrace:
0  CoreFoundation  0x1ca4cd27c 0x1ca3b5000 + 1147516
1  libobjc.A.dylib  0x1c96a79f8 0x1c96a2000 + 23032
2  CoreFoundation  0x1ca3ded94 0x1ca3b5000 + 171412
3  TestBacktrace  0x102a47464 0x102a40000 + 29796
4  UIKitCore  0x1f6c86e30 0x1f63d3000 + 9125424

只有符号化后的解体日志能力显示各个线程的函数调用,而不仅仅是毫无意义的虚拟内存地址。符号化后的解体日志如下所示,此时,咱们就可能间接从堆栈信息中晓得利用 TestBacktrace 产生解体时的函数为[AppDelegate Application:didFinishLaunchingWithOptions:],解体时函数所在文件为 AppDelegate.m,行号为 23:

Last Exception Backtrace:
0   CoreFoundation                  0x1ca4cd27c __exceptionPreprocess + 228
1   libobjc.A.dylib                 0x1c96a79f8 objc_exception_throw + 55
2   CoreFoundation                  0x1ca3ded94 -[__NSSingleObjectArrayI objectAtIndex:] + 127
3   TestBacktrace                   0x102a47464 -[AppDelegate Application:didFinishLaunchingWithOptions:] + 29796 (AppDelegate.m:23)
4   UIKitCore                       0x1f6c86e30 -[UIApplication _handleDelegateCallbacksWithOptions:isSuspended:restoreState:] + 411

二、符号化原理

2.1 什么是 dSYM 文件?

iOS 平台中,dSYM 文件是指具备调试信息的指标文件,文件名通常为:xxx.app.dSYM,其中 xxx 通常示意应用程序的二进制包名,如下图所示:

通常咱们能够在 Xcode 打包进去的文件 xcarchive 外面看到 dSYM 文件以及目录架构:

dSYM 中存储着文件名、办法名、行号 等信息,是和可执行文件的 16 进制函数地址一一对应的,通过剖析解体的解体文件能够精确晓得具体的解体信息。

DWARF(Debuging With Arbitrary Record Format) 是 ELF 和 Mach-O 等文件格式中用来存储和解决调试信息的规范格局。DWARF 中的数据是高度压缩的,能够通过 dwarfdump、otool 等命令提取其中的可读信息。比方提取要害的调试信息 debug\_info、debug\_line,可应用命令

dwarfdump --debug-line /Users/xxxx/Desktop/resource/TestBacktrace.app.dSYM > debug_line.txt

导出 debug\_line 的信息到文件 debug\_line.txt 中,debug\_info 也能够应用相似命令导出。

ELF、Mach-O 别离是 Linux 和 Mac OS 平台用于存储二进制文件、可执行文件、指标代码和共享库的文件名称。

2.2 如何生成 dSYM 文件

在编译工程时,Debug 模式会默认选中不生成 dSYM 文件,该配置可在 Build Setting|Build Option 中更改,Release 模式下 dSYM 是默认生成的。另外,如果开启了 bitcode 优化的话,苹果会做二次编译优化,所以最终的 dSYM 就须要在 Apple Connect 手动下载了。每次编译生成的 dSYM 都会有所差异,通常 dSYM 中会有一个惟一标识,称作 UUID,用以辨别不同的 dSYM 文件。

2.3 如何通过解体日志中利用的 UUID 找到匹配的 dSYM?

还原解体堆栈时,须要 dSYM 的 UUID 与解体时的利用 UUID 统一。通常,每一个 dSYM 文件都有一个 UUID,和 App 文件中的 UUID 对应,代表着是一个利用。而每一条解体信息都会记录着利用的 UUID,用来和 dSYM 的 UUID 进行校对匹配。

1. 首先从解体日志的 Binary Images 后找到利用的 UUID,如下可失去 TestBacktrace 的 UUID 为:

6be881754f573769926b838490e39857。

Binary Images:
0x102a40000 - 0x102a6bfff TestBacktrace arm64  <6be881754f573769926b838490e39857> /var/containers/Bundle/Application/B44844E6-AFF4-491E-8168-F4ED93D644C2/TestBacktrace.App/TestBacktrace
0x102d14000 - 0x102d6bfff dyld arm64  <9c893b6aa3b13d9596326ef6952e7195> /usr/lib/dyld

2. 应用以下命令查看 dSYM 文件的 UUID,去掉 – 并且小写之后,与第一步中的 UUID 是完全一致的,证实两者是匹配的,否则是不匹配的。

xcrun dwarfdump --uuid < dSYM 文件 >

3. 如果本地 dSYM 过多的话,一个个查看太麻烦,还能够应用 mdfind 命名依据 UUID 在本机查找 dSYM。以下面的 UUID 为例,间接在终端输出以下命令就能够了。

mdfind "com_apple_xcode_dsym_uuids == 6BE88175-4F57-3769-926B-838490E39857"

2.4 符号化流程

将解体日志中的 APP 二进制地址转化为函数流程如下所示:

获取到解体日志 App 要害行信息

从上图中能够看到 APP 的关建行为是:

3 TestBacktrace 0x102a47464 0x102a40000 + 29796

其中 TestBacktrace 为咱们的二进制包名名称,其余行都是零碎堆栈。

获取到偏移量、运行时堆栈地址、运行时 APP 起始地址

由要害行信息获取到 TestBacktrace 绝对于起始地址的偏移量为 29796,运行时堆栈地址为 0x102a47464,运行时 APP 起始地址为 0x102a40000。

获取 dSYM 起始地址

dSYM 文件中保留中符号表 TEXT 段的起始地址,起始地址可通过以下命令取得:

otool -l /Users/xxxxx/Desktop/TestBacktrace.app.dSYM/Contents/Resources/DWARF/TestBacktrace | grep __TEXT -C 5

由上图中可失去 dSYM 中代码段起始地址为 0x10000000。

计算解体地址对应 dSYM 符号表中的地址

因为 iOS 加载 Mach-O 文件时为了平安应用了 ASLR(Address Space Layout Randomization) 机制,导致二进制 Mach-O 文件每次加载到内存的首地址都会不一样,然而偏移量,加载地址,起始地址的计算规定是一样的;从下面咱们能够失去 0x102a47464 (运行时地址) = 0x102a40000 (起始地址) + 29796(偏移量)这个公式。因而通过 dSYM 的起始地址和偏移量就能够计算出 0x102a47464 对应在 dSYM 中的地址为 0x100007464 = 0x0000000100000000 + 29296。

获取到具体的函数 / 行数 / 文件

获取到运行堆栈地址在 dSYM 文件的对应地址 0x100007464 之后,在 dSYM 文件的 debug-info 中就能够查找到蕴含该地址的 DIE(Debug Information Entry) 单元,Mac OS 下可应用命令。

dwarfdump TestBacktrace.app.dSYM --lookup 0x100007464

获取相应信息,如图所示:

  • DW\_TAG\_Subprogram 示意这个 DIE 单元示意的是函数办法。
  • DW\_AT\_low\_pc 示意这个办法起始地址为 0x1000073b4。
  • DW\_AT\_high\_pc 示意这个办法完结地址为 0x1000074c4。这就示意解体日志中 0x102a47464 转化后的偏移地址 0x100007464 正好位于这 DW\_AT\_low\_p 和 DW\_AT\_high\_pc 之间。
  • DW\_AT\_name 示意咱们的函数名为 [AppDelegateApplication:didFinishLaunchingWithOptions:]。
  • DW\_AT\_decl\_file 示意函数所在文件门路为 AppDelegate.m。
  • DW\_AT\_decl\_line 示意函数开始行数为 19。

组装并格式化

最终通过格局优化,解体日志中 0x102a47464 符号化进去对应的办法为:

3   TestBacktrace                   0x102a47464 -[AppDelegate Application:didFinishLaunchingWithOptions:] + 29796 (AppDelegate.m:23

三、本地符号化

3.1 符号化办法

Xcode 符号化

将解体日志、dSYM 文件和可执行文件放在同一目录下,而后将 解体日志拖拽至 Devicelog 中,右键 symbolicate Log 或者 Re-symbolicate Log 就能符号化。

应用 symbolicatecrash 命令行符号化

  • 定位 symbolicatecrash 脚本

通常 symbolicatecrash 的门路为 /Applications/Xcode.App/Contents/SharedFrameworks/DVTFoundation.framework/Versions/A/Resources/symbolicatecrash

  • 前置运行命令

运行 symbolicatecrash 前个别须要先运行:

export DEVELOPER_DIR="/Applications/XCode.App/Contents/Developer"
  • 运行 symbolicatecrash 命令

首先将解体日志、dSYM 以及 symbolicatecrash 复制进去放到同一个文件夹,而后 cd 到以后文件夹,运行如下命令符号化

./symbolicatecrash TestBacktrace-2021-07-30-135514.ips TestBacktrace.app.dSYM > symbol.log

3.2 系统日志符号化

值得注意的是,有些时候,解体日志里并不会有 App 的调用,而可能全都是零碎库的调用,如下:

Thread 32 Crashed:
0    libobjc.A.dylib                 0x19aaf6c10 0x19aad3000 + 146448
1    CFNetwork                       0x187545a28 0x18737d000 + 1870376
2    Foundation                      0x18808db4c 0x187f6c000 + 1186636
3    Foundation                      0x187f8a908 0x187f6c000 + 125192
4    Foundation                      0x18808fde8 0x187f6c000 + 1195496
5    Foundation                      0x187f8a5c4 0x187f6c000 + 124356
6    Foundation                      0x1880907e0 0x187f6c000 + 1198048
7    Foundation                      0x1880902ac 0x187f6c000 + 1196716
8    libdispatch.dylib               0x1869863e4 0x186976000 + 66532
9    libdispatch.dylib               0x1869d7298 0x186976000 + 397976
10   libdispatch.dylib               0x18697c028 0x186976000 + 24616
11   libdispatch.dylib               0x18697b828 0x186976000 + 22568
12   libdispatch.dylib               0x186988bb8 0x186976000 + 76728
13   libdispatch.dylib               0x186989378 0x186976000 + 78712
14   libsystem_pthread.dylib         0x1cf2c5580 0x1cf2ba000 + 46464

符号化后的日志为:

Thread 32 Crashed:0 libobjc.A.dylib _objc_release (in libobjc.A.dylib) 161 CFNetwork __CFNetworkHTTPConnectionCacheSetLimit (in CFNetwork) 1547282 Foundation ___NSBLOCKOPERATION_IS_CALLING_OUT_TO_A_BLOCK__ (in Foundation) 163 Foundation -[NSBlockOperation main] (in Foundation) 1004 Foundation ___NSOPERATION_IS_INVOKING_MAIN__ (in Foundation) 205 Foundation -[NSOperation start] (in Foundation) 7846 Foundation ___NSOPERATIONQUEUE_IS_STARTING_AN_OPERATION__ (in Foundation) 207 Foundation ___NSOQSchedule_f (in Foundation) 1808 libdispatch.dylib __dispatch_block_async_invoke2 (in libdispatch.dylib) 1049 libdispatch.dylib __dispatch_client_callout (in libdispatch.dylib) 1610 libdispatch.dylib __dispatch_continuation_pop$VARIANT$mp (in libdispatch.dylib) 41211 libdispatch.dylib __dispatch_async_redirect_invoke (in libdispatch.dylib) 78412 libdispatch.dylib __dispatch_root_queue_drain (in libdispatch.dylib) 37613 libdispatch.dylib __dispatch_worker_thread2 (in libdispatch.dylib) 12014 libsystem_pthread.dylib __pthread_wqthread (in libsystem_pthread.dylib) 212

能够看出是 CFNetwork 网络申请时产生野指针导致的问题,那么咱们就能够针对网络相干的申请做进一步排查。

至此能够得出结论:符号化零碎库是很有必要的,特地是对一些 App 堆栈信息齐全没有的解体日志。

如何符号化零碎库符号

符号化本人 App 的办法名,须要编译生成的 dSYM 文件。而要将零碎库的符号化为残缺的办法名,也须要 iOS 各零碎库的符号文件。

  • 匹配对应的符号文件版本

用户的解体日志来自各种零碎版本,须要对应版本的零碎符号文件能力符号化。零碎库符号文件不是通用的,而是对应解体所在设施的零碎版本和 CPU 型号的。

解体日志中有这样几个信息:

Code Type:       ARM-64
OS Version:      iOS 10.2 (14C82)
.........
Binary Images:
0x102a40000 - 0x102a6bfff TestBacktrace arm64  <6be881754f573769926b838490e39857> /var/containers/Bundle/Application/B44844E6-AFF4-491E-8168-F4ED93D644C2/TestBacktrace.App/TestBacktrace
0x102d14000 - 0x102d6bfff dyld arm64  <9c893b6aa3b13d9596326ef6952e7195> /usr/lib/dyld

Code Type 示意此设施的 CPU 架构为 armv7、armv7s、arm64 还是 arm64e。

OS Version 示意此设施的零碎版本号,括号中的字符串代表了此零碎的 build 号。

Binary Images 中的 <9c893b6aa3b13d9596326ef6952e7195> 外面的字符示意对应的零碎库 dyld 的 UUID,只有 build + UUID 匹配的零碎库符号文件能力符号化零碎符号

  • 把符号文件放到指定地位

把获取到的对应版本的符号文件放到 Mac OS 的 ~/Library/Developer/Xcode/iOS DeviceSupport 目录下,就能够应用 Xcode 自带的符号化工具 symbolicatecrash 进行符号化了。这个工具会主动依据解体日志中零碎库的 UUID 搜寻本机系统库的符号文件。

3.3 获取零碎符号文件的 2 个办法

从真机上获取

大部分零碎库符号文件只能从真机上获取,苹果也没有提供间接的下载地址。然而当你用 Xcode 第一次连贯某台设施进行真机调试时,会看到 Xcode 显示 Processing symbol files,这时候就是在拷贝真机上的符号文件到 Mac OS 零碎的 /Users/xxx/Library/Developer/Xcode/iOS DeviceSupport 目录下。

目录下的 14.7.1 (18G82) 这样的文件夹就是对应的符号文件,通常都有 1-5GB 的大小。

从固件中提取符号文件

从固件 (iPSW) 中能够通过一些形式提取到零碎库符号文件。固件解密分为 下载并提取零碎符号 和 零碎库符号 提取两步。

1. 下载并提取零碎符号

  • iOS9 以及 iOS9 之前

a. 下载对应版本的 iPSW 固件,间接解压,解压后外面有几个 dmg 格局的镜像文件,最大的 dmg 文件就是零碎镜像。

b. 从 Firmware\_Keys (见文末参考链接)找到对应固件的解密 key (页面上 Root Filesystem 字段的 key)

c. 用 dmg 工具进行解密。cd 到解压后的 iPSW 文件夹,执行 ./dmg extract xxx-xxxx-xxx.dmg dec.dmg -k <key>。extract 前面跟两个参数,别离是零碎镜像 dmg 的名字和解密后的文件名,-k 前面填写第 2 步获取到的 key。如果 key 不对,解密会失败。解密胜利后会生成一个 dec.dmg 文件,双击关上即可加载零碎镜像。

  • iOS10 以及 iOS10 之后

下载对应版本的 iPSW 固件,间接解压,解压后外面有几个 dmg 格局的镜像文件,最大的 dmg 文件就是零碎镜像。

2. 零碎库符号提取

从 iPhone OS 3.1 开始,所有的零碎库都打包成一个文件:

dyld\_shared\_cache\_xxx,其中 xxx 示意具体的架构,此文件位于:/System/Library/Caches/com.Apple.dyld 目录。

dyld\_shared\_cache\_xxx 文件的解压能够应用 dyld 中的 dsc\_extractor.cpp 代码,但做肯定的改变。

a. 首先在 Apple 开源网站下载源码 dyld 库的源码,留神,这里须要下载 dyld-7 的源码。

b. 下载之后,将文件 dsc\_extractor.cpp,main 函数前后的代码改为如下代码:

#if 1
// test program
#include <stdio.h>
#include <stddef.h>
#include <dlfcn.h>
typedef int (*extractor_proc)(const char* shared_cache_file_path,const char* extraction_root_path,void (^progress)(unsigned current,unsigned total));
int main(int argc, const char* argv[]){if ( argc != 4) {fprintf(stderr,"usage: dsc_extractor <dsc_extractor.bundle path> <path-to-cache-file> <path-to-device-dir>\n");
return 1;
    }
void* handle = dlopen(argv[1],RTLD_LAZY);
if (handle == NULL) {fprintf(stderr,"dsc_extractor.bundle could not be loaded\n");
return 1;
    }
    extractor_proc proc = (extractor_proc)dlsym(handle,"dyld_shared_cache_extract_dylibs_progress");
if (proc == NULL) {fprintf(stderr,"dsc_extractor.bundle did not have dyld_shared_cache_extract_dylibs_progress symbol\n");
return 1;
    }
int result = (*proc)(argv[2],argv[3],^(unsigned c, unsigned total) {printf("%d/%d\n", c, total); } );
fprintf(stderr, "dyld_shared_cache_extract_dylibs_progress() => %d\n",r esult);
return 0;
}
#endif

c. 在终端上 cd 到 dyld 源码目录 launch-cache 下,在终端命令行编译并生成 dsc\_extractor 工具。

clang++ -o dsc_extractor dsc_extractor.cpp dsc_iterator.cpp

d. 从 Xcode 的包中 /Applications/Xcode.App/Contents/Developer/Platforms/iPhoneOS.platform/usr/lib 中提取出 dsc\_extractor.bundle 文件。dsc\_extractor.bundle 和要提取的 iOS 零碎强关联,比方 iOS14 的零碎符号须要导出 Xcode12 里的 dsc\_extractor.bundle,而 iOS15 的须要 Xcode 13 Beta 里的。如果不匹配的话,有可能不能提取出零碎符号。

e. 调用如下命令提取出零碎符号;如下,最终提取的零碎库在目录 17C81 下,咱们解析零碎符号须要的文件根本为 dylib 和 framework。

dsc_extractor  dsc_extractor.bundle   /System/Library/Caches/com.Apple.dyld/dyld_shared_cache_arm64   17C81

四、在线符号化

4.1 为什么要实现在线符号化

  • 打包时候符号文件是由继续集成打包机产生,本地获取有老本。
  • 不便研发人员疾速符号化解体日志 。很多时候,解体都是在非研发人员(产品,QA 等) 应用利用的时候产生的;同步到研发人员之后,因为本地环境的差别,在没有打包环境的状况下,研发人员也须要能迅速符号化解体堆栈
  • 线上用户上传的解体日志规模大。大多数解体都是发版之后用户应用过程中产生的,如果大量线上日志未经符号化就同步到研发人员,就会减少研发人员的累赘,升高问题解决的效率。
  • 用户零碎多,收集难度大。用户的零碎从 iOS9 到 iOS14 都有,千奇百怪,靠研发人员本地想要解析所有的零碎符号纯属臆想。

4.2 在线 App / 动静库符号化

通常状况下,咱们只须要符号化极少局部解体日志,这种状况下咱们在本地就能够符号化了。但当咱们的利用上线发版后,解体日志日均收集量级可能超百万以上,此时就不适宜在 Mac OS 上应用脚本 / 工具符号化了(在 Mac OS 上应用 symbolicatecrash 命令符号化单个日志时,耗时根本 1 秒以上)。此时,就须要更通用,疾速的符号化形式了。

为了可能在 Linux 服务器上极速符号化 iOS 解体日志,咱们深刻调研了 iOS 本地符号化的原理,在和平台方屡次就技术计划进行了调研商量之后,最终采取了如下计划:

生成 mapping 文件

将 dSYM 文件通过脚本提取生成一个 mapping 文件,格局如下:

Format:        Mach-O/64-BitArch:        arm64Symbols:        5Tool Version::        1.0.1File Version:   1.0.0UUID:        e569d81abb2c372e89a2410edc3d368fBuilt Time:          2021-07-29 13:31:08Symbol table:6c64    6c78    -[ViewController viewDidLoad]   (in TestBacktrace)  (ViewController.m:17)6c78    6c84    -[ViewController viewDidLoad]   (in TestBacktrace)  (ViewController.m:0)

提取操作会波及到 DWARF 中 debug\_line 段数据的符号化,相干提取算法能够参考 DWARF 官网的材料。debug\_line 段蕴含有具体的代码偏移量地址和文件名称,依照 DWARF 的算法就能够解析进去,而后与 Symbol Table 的函数符号一一匹配,就能生成代码地址偏移量与函数、文件、行数的映射关系。须要留神的是,苹果的 Mach-O 当初大部分格局都是应用 DWARF2 和 DWARF4 版本,提取的时候须要重点关注这两种格局的兼容和算法不同。最终,能够看到 Symbol table 每一行对应一个符号的偏移量。

能够发现 7464 刚好处于 7454 – 7478 之间,匹配进去的符号刚好是 -[AppDelegate Application:didFinishLaunchingWithOptions:] (in TestBacktrace) (AppDelegate.m:23),与 Mac OS 上应用 symbolicatecrash 脚本符号化的后果统一。

依据 mapping 文件符号化

借助于脚本工具提取的符号 mapping 文件,服务端就可能脱离平台限度,依据解体日志中的 UUID 去匹配映射文件,在 Linux 上极速符号化解体日志,提供高效实时的符号化服务。

4.3 在线符号化 iOS 零碎库符号

在 Mac OS 平台上,咱们能够间接应用零碎库的符号间接应用脚本去符号化符号,然而一旦要符号化所有用户上传的解体日志,这一套机制就不免被速度和平台限度。并且 iOS 零碎从 2.0 开始,始终到当初 iOS 14,收回的版本几百个,要手动提取出零碎库符号简直是不可能的事件。为了解决这个问题,在借鉴了 dSYM 跨平台符号化计划之后,咱们做了一套零碎符号自动化符号化的计划,最终实现了在 Linux 平台上高效实时的符号化零碎堆栈。

1. 定时从 theiphonewiki 网站上导出各个系统以及最新公布零碎的 iPSW 文件下载地址。

2. 解压 iPSW 并加载零碎镜像 dmg 文件,找到 dyld\_shared\_cache\_xxx 文件。

3. 应用工具 dsc\_extractor 将零碎库符号文件导出,导出文件根本为后缀为 dylib 和 framework 的 Mach-O 类型文件。

4. 将所有的 dylib 和 framework 应用工具提取生成如下格局的 mapping 文件。这一步与 dSYM 提取操作会有肯定差异,通常来说,零碎库只有符号表段,不须要对 debug\_line 段做提取,绝对比较简单。

20b8    20fa    +[ZoomServicesUI enableZoomServices]    (in AccessibilitySettingsLoader)20fa    2120    +[ZoomServicesUI disableZoomServices]   (in AccessibilitySettingsLoader)2120    21b6    -[ZoomServicesUI init]  (in AccessibilitySettingsLoader)21b6    2222    -[ZoomServicesUI dealloc]   (in AccessibilitySettingsLoader)

5. 解体日志上传到符号化服务器之后,服务器依据解体日志中零碎库的 UUID 和 mapping 文件中的 UUID 惟一确定 mapping 文件并符号化零碎堆栈。

五、成果

1. 在线符号化零碎上线之后,用户的日志通过解体组件主动上传到性能之后,符号化解析零碎间接将解体日志符号化并聚类,最终符号化的解体日志详情如下。应用程序的地址最终体现为 函数 + 文件 + 行数,零碎堆栈会具体显示出解体的函数,整个过程实时且高效。

Last Exception Backtrace:
0   CoreFoundation                  0x1ca4cd27c __exceptionPreprocess + 228
1   libobjc.A.dylib                 0x1c96a79f8 objc_exception_throw + 55
2   CoreFoundation                  0x1ca3ded94 -[__NSSingleObjectArrayI objectAtIndex:] + 127
3   TestBacktrace                   0x102a47464 -[AppDelegate Application:didFinishLaunchingWithOptions:] + 29796 (AppDelegate.m:23)
4   UIKitCore                       0x1f6c86e30 -[UIApplication _handleDelegateCallbacksWithOptions:isSuspended:restoreState:] + 411
5   UIKitCore                       0x1f6c88594 -[UIApplication _callInitializationDelegatesForMainScene:transitionContext:] + 3351
6   UIKitCore                       0x1f6c8dd20 -[UIApplication 
```````
`Thread 0 name:  Dispatch queue: com.Apple.main-thread
Thread 0 Crashed:
0   libsystem_kernel.dylib          0x00000001ca06a0dc __pthread_kill + 8
1   libsystem_pthread.dylib         0x00000001ca0e3094 pthread_kill$VARIANT$mp + 380
2   libsystem_c.dylib               0x00000001c9fc3ea8 abort + 140
3   libc++abi.dylib                 0x00000001c9690788 __cxa_bad_cast + 0`

2\. 局部来自研发和测试的解体日志,平台提供了在线符号化的入口,只须要手动上传解体日志到平台,立即就能把符号化后的解体日志下载给相应人员。## 六、收益
1\. 线上问题定位速度取得极大晋升,从线上产生新增卡顿 / 解体问题到具体研发响应工夫大大缩减,从产生解体到定位问题,根本都在 10 分钟以内。2\. 目前,性能平台日均在线符号化解体 / 卡顿日志超百万次,厂内接入产品线超 30+,符号化性能做到了上传即解析,整个过程无需研发人员干涉。真正做到了自动化、在线、实时的符号化解体、卡顿日志,并实时依据符号化的问题代码定位到具体开发人员,高效的响应并解决线上问题。** 参考资料:**



\[1\] iOS Crash 剖析必备:符号化零碎库办法 https://zuikyo.github.io/2016/12/18/iOS%20Crash%E6%97%A5%E5%BF%97%E5%88%86%E6%9E%90%E5%BF%85%E5%A4%87%EF%BC%9A%E7%AC%A6%E5%8F%B7%E5%8C%96%E7%B3%BB%E7%BB%9F%E5%BA%93%E6%96%B9%E6%B3%95/\[2\] 聊聊从 iOS 固件提取零碎库符号 http://crash.163.com/#news/!newsId=31  
\[3\] Xcode 中和 symbols 无关的几个设置 https://www.jianshu.com/p/11710e7ab661\[4\] iOS\_SDK https://en.wikipedia.org/wiki/IOS\_SDK\[5\] IOS\_version\_history https://en.wikipedia.org/wiki/IOS\_version\_history#iOS\_14  
\[6\] dyld 源码下载地址 https://opensource.apple.com/tarballs/dyld/\[7\] The DWARF Debugging Standard http://www.dwarfstd.org/\[8\] iOS9 之前的 Firmware\_Keys https://www.theiphonewiki.com/wiki/Firmware\_Keys  
\[9\] dmg 工具下载地址 https://github.com/Zuikyo/iOS-System-Symbols/blob/master/tools/dmg\[10\] 零碎符号下载地址索引 wiki https://www.theiphonewiki.com/wiki/Firmware

****** 招聘信息 ******:** 挪动端高级 / 资深工程师 **

咱们是百度 APP 挪动技术平台团队,负责百度 APP 性能优化、网络优化、架构降级、工程效力晋升和新技术摸索等。咱们在线上线下研发工具,智能性能优化,网络库开发,网络监控,编译构建零碎,动态化计划等方面深耕,技术深度上是挪动端的灯塔。咱们反对业务疾速迭代的同时,保障超大规模团队的研发效力,服务于 MAU 超过 6 亿的用户。咱们致力于打造行业内性能最佳的 APPs,在高中低端机上有卓越的性能稳定性和晦涩度。咱们致力于建设适宜百度的挪动技术平台,赋能百度的挪动端产品,智能音箱和车载设施。** 技术栈 **:Java/OC/C/C++/Kotlin/Swift/Ruby/PHP 等

** 撑持业务 **:百度 APP 的搜寻,Feed,小程序,直播,视频等;百度贴吧,难看视频等其余挪动端产品;小度音箱等 IOT 设施;智能交通,车联网等车载设施。** 学历要求 **:统招本科毕业

如果你在某个方向有专长,有技术深度;如果你酷爱专研,挑战疑难问题;如果你爱冲破翻新,应用端智能等新技术解决各种问题,这里就是你施展能力的舞台!** 投递邮箱:**  

**_geektalk@baidu.com(投递备注岗位)_**

  

举荐浏览:[|百度商业托管页零碎高可用建设办法和实际](http://mp.weixin.qq.com/s?__biz=Mzg5MjU0NTI5OQ==&mid=2247503928&idx=1&sn=a595da431aad386e4210f886cbcddaca&chksm=c03ee044f7496952e70788ab0ba71d6acaaff6de4162d4fa3d3e872cfcbb4b34335b95f597cf&scene=21#wechat_redirect)


[|AI 在视频畛域使用—弹幕穿人](http://mp.weixin.qq.com/s?__biz=Mzg5MjU0NTI5OQ==&mid=2247503597&idx=1&sn=a9b60d17f310dc3b5ccf29d067d66111&chksm=c03efe91f74977872cc380f48edd6c97e7915bc2fd99c49ca9edfdbaf2f4d9484e40d05b5b86&scene=21#wechat_redirect)


[|iOS 签名校验那些事儿](http://mp.weixin.qq.com/s?__biz=Mzg5MjU0NTI5OQ==&mid=2247503500&idx=1&sn=f84fd6f9e62feeb7b91dfd6f1f0d145d&chksm=c03efef0f74977e66f26f287912dc37c1f3cb0124c57483205345ad7645ea59bc3518e1c82e2&scene=21#wechat_redirect)

**---------- END ----------**



百度 Geek 说




百度官网技术公众号上线啦!技术干货 · 行业资讯 · 线上沙龙 · 行业大会




招聘信息 · 内推信息 · 技术书籍 · 百度周边




欢送各位同学关注
退出移动版