Android JNI Crash定位步驟

1. 找到未strip的, 符號表完整的so庫文件

在Android Studio 3.2.1:

strip之前的文件所在目錄:
app/build/intermediaters/transforms/mergejniLibs/debug
或者根據(jù)Crash的APP是debug還是release版本選擇
app/build/intermediates/cmake/debug/objapp/build/intermediates/cmake/release/obj
由于CMake/CXX_FLAGS的配置等原因,以上目錄下的文件可能還是被strip了再扭。如何準(zhǔn)確判斷so有沒有被strip請參照文章下面提到的readelf工具鸥印。或者參考:file查看strip狀況
如果發(fā)現(xiàn)so還是被strip的蹄胰,嘗試在CMake添加如下配置:


/**
這幾行代碼表示debug版本的so文件保留so保留符號庫,這樣會導(dǎo)致so文件很大.
如果要讓release版本保留符號庫文件,就替換成CMAKE_C_FLAGS_RELEASE和CMAKE_CXX_FLAGS_RELEASE.
但務(wù)必在正式對外發(fā)布的時(shí)候去掉release 配置的-g選項(xiàng)拷淘,以免增加文件size
**/
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -g")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g")
//R16之前版本的NDK默認(rèn)是編譯時(shí)加-g的策吠,新版本不確定逛裤,所以需要不strip的 so文件,最好在CMake里配置一下-g
//并且不要有 -fvisibility=hidden 和 -s 選項(xiàng):锬ā带族!

如果依賴的是Native module或者aar, 那么
strip之前的文件所在目錄:
yourNativeLibModule/build/intermediates/transforms/mergeJniLibs/debug

strip之后的文件所在目錄:
app/build/intermediaters/transforms/stripDebugSymbol/debug

2. 確定發(fā)生Crash的設(shè)備對應(yīng)的CPU架構(gòu)

在JNI Crash的日志里
如果有l(wèi)ib/arm, 則是armeabi-v7a架構(gòu);
如果有l(wèi)ib/arm64, 則是arm64-v8a架構(gòu)

3. 根據(jù)CPU架構(gòu)找相應(yīng)的toolchain:

arm64-v8a對應(yīng)的是aarch64-linux-android-4.9
armeabi-v7a對應(yīng)的是arm-linux-androideabi-4.9

4.使用add2line 和ndk-stack等工具分析JNI Crash的log

addr2line

作用是根據(jù)內(nèi)存地址找到對應(yīng)的報(bào)錯(cuò)代碼的文件名和行號
所在目錄是toolchain的bin文件夾,
比如 aarch64-linux-android-4.9對應(yīng)的bin文件夾是
/Android/Sdk/ndk-bundle/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin

arm-linux-androideabi-4.9,對應(yīng)的bin文件夾是
/media/kyle/a393d005-ebe5-42a0-8c6a-c86fdfb185c1/Android/Sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin

用法:
arm-linux-androideabi-addr2line -f -e xxx.so 0x8eb09258
-f表示顯示函數(shù)名, -e表示execution,后面是包含符號庫的文件 以及報(bào)錯(cuò)的內(nèi)存地址(即Crash log里pc后的字段)

ndk-stack

作用是一鍵生成更可讀的Crash 日志
所在目錄是/media/kyle/a393d005-ebe5-42a0-8c6a-c86fdfb185c1/Android/Sdk/ndk-bundle/ndk-stack
用法:
ndk-stack -sym App/build/intermediates/transforms/mergeJniLibs/release/0/lib/對應(yīng)的abi目錄 -dump jniCrash.log
或者
adb logcat | ndk-stack -sym App/build/intermediates/transforms/mergeJniLibs/release/0/lib/對應(yīng)的abi目錄

-sym表示symbols

--------------------------------------------分隔符----------------------------------------

其他工具補(bǔ)充

toolchain下的:

arm-linux-androideabi-readelf
  1. 有時(shí)候用addr2line發(fā)現(xiàn)能顯示函數(shù)名但行號是亂碼蟀给?蝙砌?,有可能是因?yàn)檫@個(gè)so被strip了跋理。被strip的so的
    readelf結(jié)果里“section headers”的個(gè)數(shù)會比未strip后的少择克,所以可以根據(jù)readelf來判斷so是否是真的被strip了
    命令格式:
    arm-linux-androideabi-readelf -S xx.so

  2. 可以用于查看so文件中的所有函數(shù)。所以如果遇到JNI方法找不到的錯(cuò)誤前普,就可以使用該工具查看so庫中的所有函數(shù)肚邢,然后搜索對應(yīng)的JNI方法,看到底有沒有被編譯到動態(tài)庫中拭卿。
    命令格式:
    arm-linux-androideabi-readelf -a xx.so > fun.txt
    注意:仍需要使用未strip之前的so文件骡湖, 上面的命令會把結(jié)果寫入fun.txt

arm-linux-androideabi-objdump

可以獲取so文件的符號表信息,可以看到編譯進(jìn)來的所有方法以及調(diào)用堆棧的地址.
命令格式:
arm-linux-androideabi-objdump -dx xx.so > stacktrace.txt

/aarch64-linux-android-objdump -dx xx.so > stacktrace.txt

arm-linux-androideabi-nm

可以查看靜態(tài)庫中的符號记劈,比如查看所有方法的聲明勺鸦。
如果在編譯so動態(tài)庫的過程中碰到undefined reference類型的錯(cuò)誤, 或者
duplicated reference目木, 可以使用這條指令將對應(yīng)靜態(tài)庫的所有方法都導(dǎo)出來换途, 然后看一下是否有某方法.
命令格式:
arm-linux-androideabi-nm xx.a > symbol.txt

常用信號量的含義
#define SIGABRT 6 // abort() 調(diào)用abort函數(shù)生成的信號懊渡,表示程序運(yùn)行異常被中止
#define SIGSEGV 11 // segmentation violation 指針?biāo)鶎?yīng)的地址是無效或非法地址,比如訪問越界/stack overflow/文件操作不被允許( fault addr 0x0 或者其他小地址 fault addr 0x0000008 一般是空指針錯(cuò)誤军拟,訪問為null的結(jié)構(gòu)體的成員變量時(shí)剃执,報(bào)錯(cuò)地址會是小地址)
#define SIGILL 4 // Illegal instruction 執(zhí)行了非法指令,比如第三方庫的兼容性問題懈息,權(quán)限問題
#define SIGSYS 31 // bad argument to system call 非法的系統(tǒng)調(diào)用
#define SIGBUS 7 // 非法地址肾档,包括內(nèi)存地址對齊出錯(cuò),比如訪問一個(gè)4字節(jié)的整數(shù), 但其地址不是4的倍數(shù)
#define SIGFPE 8 // 進(jìn)程執(zhí)行了一個(gè)錯(cuò)誤的算術(shù)操作辫继,比如除0怒见、溢出
#define SIGKILL 9 // 強(qiáng)制結(jié)束程序,本信號不能被捕獲
#define SIGPIPE 13 // write on a pipe with no one to read it 管道破裂姑宽,通常在進(jìn)程間通信產(chǎn)生
用AddressSanitizer檢測內(nèi)存問題

谷歌官方出品的AddressSanitizer遣耍,使用也比較簡單。目前還不支持內(nèi)存泄漏的檢測炮车,但支持檢測以下內(nèi)存問題:

tip
  1. 有時(shí)候堆棧里有offset信息舵变,比如
#09  pc 0000000000087050  /data/app/com.ufotosoft.justshot-o0tTYIIuxWN-zbg7o3aW_g==/oat/arm64/base.odex (offset 0x85000) (com.tencent.apollo.ApolloVoiceEngine.Pause [DEDUPED]+144)t

這里的offset指的是so文件的偏移量

  1. 在許多情況下,故障地址將不會是 0瘦穆,而是其他一些小數(shù)字纪隙。兩位或三位地址尤其常見,而六位地址幾乎肯定不是 Null 指針解引用(它需要 1 MiB 的偏移量)
    一個(gè)充分的低位故障地址通常意味著您可以跳過堆棧中的任意 libc.so 幀扛或,并直接歸咎于調(diào)用的代碼绵咱。不過,情況并非總是如此熙兔,這些例外將是您用作展示的絕佳機(jī)會麸拄。
    您可以使用 crasher fprintf-NULL 或 crasher readdir-NULL 重現(xiàn)此類崩潰問題的實(shí)例
本文參考文章

Android NDK開發(fā)Crash錯(cuò)誤定位
Can anyone explain the gcc cross-compiler naming convention?
NDK toolchain對應(yīng)ABI
Android基礎(chǔ)開發(fā)實(shí)踐:如何分析Native Crash(文字介紹的“當(dāng)前符號表so與實(shí)際出現(xiàn)Crash的so不匹配,但當(dāng)前出問題的native函數(shù)沒有進(jìn)行過修改時(shí)仍可以解析”的方法很好用黔姜,記得加地址偏移時(shí)是16進(jìn)制)
Android Stability - Native Crash問題概述
診斷原生代碼崩潰問題

《音視頻開發(fā)進(jìn)階指南》 by 展曉凱 魏曉紅

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市蒂萎,隨后出現(xiàn)的幾起案子秆吵,更是在濱河造成了極大的恐慌,老刑警劉巖五慈,帶你破解...
    沈念sama閱讀 222,183評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件纳寂,死亡現(xiàn)場離奇詭異,居然都是意外死亡泻拦,警方通過查閱死者的電腦和手機(jī)毙芜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來争拐,“玉大人腋粥,你說我怎么就攤上這事。” “怎么了隘冲?”我有些...
    開封第一講書人閱讀 168,766評論 0 361
  • 文/不壞的土叔 我叫張陵闹瞧,是天一觀的道長。 經(jīng)常有香客問我展辞,道長奥邮,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,854評論 1 299
  • 正文 為了忘掉前任罗珍,我火速辦了婚禮洽腺,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘覆旱。我一直安慰自己蘸朋,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評論 6 398
  • 文/花漫 我一把揭開白布通殃。 她就那樣靜靜地躺著度液,像睡著了一般。 火紅的嫁衣襯著肌膚如雪画舌。 梳的紋絲不亂的頭發(fā)上堕担,一...
    開封第一講書人閱讀 52,457評論 1 311
  • 那天,我揣著相機(jī)與錄音曲聂,去河邊找鬼霹购。 笑死,一個(gè)胖子當(dāng)著我的面吹牛朋腋,可吹牛的內(nèi)容都是我干的齐疙。 我是一名探鬼主播,決...
    沈念sama閱讀 40,999評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼旭咽,長吁一口氣:“原來是場噩夢啊……” “哼贞奋!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起穷绵,我...
    開封第一講書人閱讀 39,914評論 0 277
  • 序言:老撾萬榮一對情侶失蹤轿塔,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后仲墨,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體勾缭,經(jīng)...
    沈念sama閱讀 46,465評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評論 3 342
  • 正文 我和宋清朗相戀三年目养,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了俩由。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,675評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡癌蚁,死狀恐怖幻梯,靈堂內(nèi)的尸體忽然破棺而出兜畸,到底是詐尸還是另有隱情,我是刑警寧澤礼旅,帶...
    沈念sama閱讀 36,354評論 5 351
  • 正文 年R本政府宣布膳叨,位于F島的核電站,受9級特大地震影響痘系,放射性物質(zhì)發(fā)生泄漏菲嘴。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評論 3 335
  • 文/蒙蒙 一汰翠、第九天 我趴在偏房一處隱蔽的房頂上張望龄坪。 院中可真熱鬧,春花似錦复唤、人聲如沸健田。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽妓局。三九已至,卻和暖如春呈宇,著一層夾襖步出監(jiān)牢的瞬間好爬,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評論 1 274
  • 我被黑心中介騙來泰國打工甥啄, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留存炮,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,091評論 3 378
  • 正文 我出身青樓蜈漓,卻偏偏與公主長得像穆桂,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子融虽,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評論 2 360