iOS閃退監(jiān)控方案

實現(xiàn)方案

基本思路:日志捕獲采用 KSCrash钮科,捕獲的日志上傳服務(wù)器,然后在服務(wù)器對日志進行符號化婆赠。

KSCrash 的上傳日志需要注意啟動閃退的情況跺嗽,一般是應(yīng)用啟動如果存在日志,需要先 hold 主線程页藻,等上傳完再釋放桨嫁。

基本模型如下:

//防止在登錄前就必閃情況
__block BOOL finished = NO;
[self uploadIfExistWithCompleteHandler:^{
    finished = YES;
}];
//防止上傳失敗
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    finished = YES;
});
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop addPort:[NSMachPort port] forMode:NSRunLoopCommonModes];
while (!finished) {
    [runLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
}

符號化方案

以下主要討論的是服務(wù)端通過腳本自動符號化日志需求

方案一:通過修改配置,不需要自主符號化日志份帐,也能看到日志堆棧類和函數(shù)名

通過在 Xcode 中設(shè)置 Build Settings -> Strip Style -> Debugging Symbols

Strip Style 有三個選項如下

  • All Symbols:剝離所有符號表和重定向信息
  • Non-Global Symbols:剝離非全局的符號(包括調(diào)試符號)璃吧,保留外部符號
  • Debugging Symbols:剝離調(diào)試符號,保留局部符號和全局符號

開啟設(shè)備符號化需要在最終版本中包含基本符號废境,所以要在 build settings 中設(shè)置 Strip StyleDebugging Symbols畜挨。也會造成最終的二進制文件大小增加 5% 左右筒繁,這也是之前 PLCrashReporter 中提到的,不過當(dāng)時查到的數(shù)據(jù)是 30-50%巴元,確實測試后沒有如此大的差距毡咏,也算是解了疑惑,由于打包包含了基本符號表導(dǎo)致的二進制大小增加逮刨。

注意:系統(tǒng)庫無法符號化呕缭,需要 symbolicatecrash 來符號化

方案二:通過 symbolicatecrash 自主符號化日志

atos 是蘋果提供的符號化工具,在 Mac OS 系統(tǒng)下默認安裝修己,他的缺點是只能一個地址一個地址逐個翻譯恢总。

symbolicatecrash 是 Xcode 自帶的一個程序,他是對 atos 的封裝睬愤,可以翻譯整個 crash 文件片仿。

接下來通過使用 symbolicatecrash 進行符號化日志

第一步:獲取 symbolicatecrash 文件,通過使用以下命令搜索尤辱,找到之后拷到閃退日志目錄下

find /Applications/Xcode.App -name symbolicatecrash -type f

第二步:設(shè)置路徑

export DEVELOPER_DIR="/Applications/Xcode.app/Contents/Developer"

第三步:符號化日志砂豌,cd 到閃退日志目錄下轴猎,然后運行下面命令

./symbolicatecrash log.txt -d xxx.App.dSYM > result.txt  

獲取符號文件

獲取項目符號文件

iOS 的打包一般有兩種方式驮吱,Xcode 打包或者腳本打包。

不過哪種方式都會生成 xxx.xcarchive 文件浸剩,打開就可以看到 dSYMs 符號文件可帽。

  1. Xcode 打包:在 Xcode 中工具欄上 Window -> Organizeer -> 選擇相應(yīng)的App -> Archives -> 選擇對應(yīng)的包進入就可以看到 xxx.xcarchive 文件
  2. 腳本打包:一般ipa包生成同時旁邊也會生成 xxx.xcarchive 文件

這里有個問題,閃退日志必須和符號化文件匹配才能解析窗怒,我們可以通過 UUID 來匹配

dSYM 的 UUID 獲取方式

命令:dwarfdump --uuid appName.app.dSYM

例如:dwarfdump --uuid /Users/xxx/Desktop/Demo.app.dSYM
結(jié)果:UUID: 35E34DE0-4C45-36CF-8F11-1F33BA40F3ED (arm64)

日志自動帶上了 UUID

image.png

此時符號化的日志如下

image-1.png

獲取系統(tǒng)符號文件

系統(tǒng)符號文件會根據(jù)不同 CPU 架構(gòu)(armv7,armv7s,arm64,arm64e)映跟,以及不同系統(tǒng)對應(yīng)的文件都不一樣。通過 symbolicatecrash 工具進行符號化時扬虚,工具會自動會在 /Users/xxx/Library/Developer/Xcode/iOS DeviceSupport 目錄下進行匹配解析努隙。

方式一:從真機上獲取

當(dāng)你用 Xcode 第一次連接某臺設(shè)備進行真機調(diào)試時,會看到 Xcode 顯示 Processing symbol files 辜昵,這時候就是在拷貝真機上的符號文件到 Mac OS 系統(tǒng)的 /Users/xxx/Library/Developer/Xcode/iOS DeviceSupport 目錄下荸镊。

image-2.png

14.6 (18F72) arm64e 就是對應(yīng)的系統(tǒng)符號文件

如果僅通過真機來獲取系統(tǒng)的符號化文件,比較局限堪置,把不同系統(tǒng)版本以及不同 CPU 架構(gòu)類型的手機準(zhǔn)備齊全比較難躬存。

方式二:從固件中提取符號文件

下面以獲取 iPhone12 系統(tǒng)為 iOS 14.6 為例。

第一步:下載對應(yīng)的固件舀锨,從中獲取 dyld_shared_cache_xxx 可執(zhí)行文件岭洲,其中 xxx 是 CPU 架構(gòu)類型。

www.theiphonewiki.com 下載坎匿。優(yōu)點整理的齊全盾剩,缺點下載速度有點慢雷激。

image-3.png

下載完解壓得到,獲取最大的 dmg 文件

image-4.png

運行 018-17771-088.dmg 獲取 dyld_shared_cache_arm64e告私,路徑 System -> Library -> Caches -> com.apple.dyld

image-5.png

第二步:通過 dyld 生成 dsc_extractor 可執(zhí)行文件屎暇。

在蘋果的開源網(wǎng)站下載 dyld 源碼,例子中下載了 dyld-750.6.tar.gz 解壓

image-6.png

修改 dsc_extractor.cpp 文件驻粟,把 #if 0 改成 #if 1根悼,屏蔽其他代碼

#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 != 3 ) {
        fprintf(stderr, "usage: dsc_extractor <path-to-cache-file> <path-to-device-dir>\n");
        return 1;
    }

    //void* handle = dlopen("/Volumes/my/src/dyld/build/Debug/dsc_extractor.bundle", RTLD_LAZY);
    void* handle = dlopen("/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/usr/lib/dsc_extractor.bundle", 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[1], argv[2], ^(unsigned c, unsigned total) { printf("%d/%d\n", c, total); } );
    fprintf(stderr, "dyld_shared_cache_extract_dylibs_progress() => %d\n", result);
    return 0;
}
#endif

修改 dsc_iterator.cpp 文件,屏蔽頭文件 #include "SupportedArchs.h"

在終端上 cd 到 dyld 源碼目錄 launch-cache 下格嗅,在終端命令行編譯并生成 dsc_extractor 可執(zhí)行文件

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

第三步:通過 dyld_shared_cache_xxxdsc_extractor 獲取系統(tǒng)符號文件

新建一個文件夾把 dsc_extractordyld_shared_cache_arm64e 兩個可執(zhí)行文件放入其中

通過以下命令就可以生成系統(tǒng)符號文件

dsc_extractor <path-to-cache-file> <path-to-device-dir>

比如:

./dsc_extractor ./dyld_shared_cache_arm64e ./Symbols

新建一個文件夾 14.6 (18F72) arm64e番挺,把 Symbols 拖入其中,然后拖入 /Users/xxx/Library/Developer/Xcode/iOS DeviceSupport 目錄下屯掖。

此時符號化的日志如下

image-7.png

參考資料

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末玄柏,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子贴铜,更是在濱河造成了極大的恐慌粪摘,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件绍坝,死亡現(xiàn)場離奇詭異徘意,居然都是意外死亡,警方通過查閱死者的電腦和手機轩褐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進店門椎咧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人把介,你說我怎么就攤上這事勤讽。” “怎么了拗踢?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵脚牍,是天一觀的道長。 經(jīng)常有香客問我巢墅,道長诸狭,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任君纫,我火速辦了婚禮驯遇,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蓄髓。我一直安慰自己妹懒,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布双吆。 她就那樣靜靜地躺著眨唬,像睡著了一般会前。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上匾竿,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天瓦宜,我揣著相機與錄音,去河邊找鬼岭妖。 笑死临庇,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的昵慌。 我是一名探鬼主播假夺,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼斋攀!你這毒婦竟也來了已卷?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤淳蔼,失蹤者是張志新(化名)和其女友劉穎侧蘸,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鹉梨,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡讳癌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了存皂。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片晌坤。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖旦袋,靈堂內(nèi)的尸體忽然破棺而出骤菠,到底是詐尸還是另有隱情,我是刑警寧澤猜憎,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布娩怎,位于F島的核電站搔课,受9級特大地震影響胰柑,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜爬泥,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一柬讨、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧袍啡,春花似錦踩官、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽颖系。三九已至,卻和暖如春辩越,著一層夾襖步出監(jiān)牢的瞬間嘁扼,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工黔攒, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留趁啸,地道東北人。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓督惰,卻偏偏與公主長得像不傅,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子赏胚,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內(nèi)容