前提:
测试提了一个关于某个操作下会比较卡顿的问题,并上传了applog。
log初探
app内部工具的InnerToolBlockDetect 里记录了卡顿的情况并打印了对应的线程堆栈信息。
但由于测试用的是release包,因此堆栈里都是相应函数的位移地址,无法看出真正的卡顿代码。
libsystem_kernel.dylib 0x1f59140f4 mach_msg_trap + 8
libsystem_kernel.dylib 0x1f59135a0 mach_msg + 72
libdispatch.dylib 0x1f5778884 + 500
libdispatch.dylib 0x1f5778d14 + 52
libxpc.dylib 0x1f59d891c xpc_connection_send_message_with_reply_sync + 204
CoreMedia 0x1f93a9514 FigXPCRemoteClientSendSyncMessageCreatingReply + 36
CoreMedia 0x1f92ca884 + 192
CoreFoundation 0x1f5d15d30 + 192
MediaToolbox 0x1fa95459c + 1448
MediaToolbox 0x1fa953f6c FigAssetRemoteCreateWithURL + 120
AVFoundation 0x1fbdf5bb0 + 192
AVFoundation 0x1fbd0a874 + 884
AVFoundation 0x1fbd033e4 + 100
Fly-rls 0x106382da0 _ZNSt3__114__thread_proxyINS_5tupleIJNS_10unique_ptrINS_15__thread_structENS_14default_deleteIS3_EEEEZN3dji6common6WorkerC1EvEUlvE_EEEEEPvSC_ + 1355164
Fly-rls 0x106383224 _ZNSt3__114__thread_proxyINS_5tupleIJNS_10unique_ptrINS_15__thread_structENS_14default_deleteIS3_EEEEZN3dji6common6WorkerC1EvEUlvE_EEEEEPvSC_ + 1356320
Fly-rls 0x1044c5fec _mh_execute_header + 303084
Fly-rls 0x1044c5e1c _mh_execute_header + 302620
Fly-rls 0x10466c0ec _mh_execute_header + 2031852
Fly-rls 0x10466b920 _mh_execute_header + 2029856
Fly-rls 0x1044bd92c _mh_execute_header + 268588
libdispatch.dylib 0x1f57c0a38 + 24
libdispatch.dylib 0x1f57c17d4 + 16
libdispatch.dylib 0x1f576f008 + 1068
CoreFoundation 0x1f5d1432c + 12
CoreFoundation 0x1f5d0f264 + 1924
CoreFoundation 0x1f5d0e7c0 CFRunLoopRunSpecific + 436
GraphicsServices 0x1f7f0f79c GSEventRunModal + 104
UIKitCore 0x222813c38 UIApplicationMain + 212
Fly-rls 0x10448482c _mh_execute_header + 34860
libdyld.dylib 0x1f57d28e0 + 4
堆栈还原
手头上有对应app包的 dysm 文件,查了一下,发现可以用 xcrun 命令来还原堆栈。比如:
xcrun atos -o Foo.app/Foo -arch arm64 -l 0xd7000 0x0033f9bb
其中 0xd7000 是app执行文件的 运行开始内存地址,0x0033f9bb 是 对应的堆栈函数地址(比如上面的0x1044bd92c)
函数地址都已知,但不像crash的 ips文件,这里并没有列出 Fly-rls 执行文件的运行起始地址。
在 crash 的ips文件里,列出了 对应执行文件的运行时内存地址区间。
Binary Images:
0x104144000 - 0x10922bfff Fly-dbg arm64 <191a2e0e899a36d2affc5183f78af174> /var/containers/Bundle/Application/25A26AFE-CE43-4E1C-B3E0-543BA6C28ADB/Fly-dbg.app/Fly-dbg
但我发现,main函数的入口地址 就是app运行开始地址 加上一部分位移(该位移在不同的build 包里,是不一样的)。
如:
34 Fly-dbg 0x000000010415466c 0x104144000 + 67180
于是我便去bugly上,搜索 对应release包的crash记录,看能不能找到产生卡顿的版本的app包的 main函数位移地址。
随便搜了一条crash记录,并查看这个记录的原始 堆栈地址信息,成功找到了 位移大小(就是34860)。
Fly-rls 0x000000010252082c 0x0000000102518000 + 34860
看,跟卡顿堆栈log 的 位移是一样的。
那么用 ** 0x10448482c** 减去 34860 就是卡顿发生那次运行的app的起始内存地址了。
算出来是 0x10447c000
然后再跑xcrun 命令就可以顺利解析出卡顿堆栈了。
xcrun atos -o /Users/spy.liu/Downloads/_GO_Lite_Develop_697.dSYM/\ Fly-rls.app.dSYM/Contents/Resources/DWARF/\ Fly-rls -arch arm64 -l 0x10447c000 0x1044c5e1c
把多个堆栈地址放到一个文件里,换行隔开,可以一次解析多个堆栈。
xcrun atos -o /Users/spy.liu/Downloads/_GO_Lite_Develop_697.dSYM/\ Fly-rls.app.dSYM/Contents/Resources/DWARF/\ Fly-rls -arch arm64 -l 0x10447c000 -f addresss.txt