NDK異常信息一般有三個要素:
ndk--------->墓碑
第一步:?
cd /data/tombstones/??
第二步:?
/data/tombstones # ls -lht
第三步:?
more cdc_8295-221024-197-tombstone_048?
so庫是如何生成的 ????
cmake生成.so方案
以上方案都是通通不行的,最終找到是Cmake 3.10.2版本過高土全,與build版本不一致造成的
NDK異常信息一般有三個要素:
信號
調(diào)用棧信息(棧地址茅郎,內(nèi)存地址)
寄存器信息
錯誤信號:11是信號量sigNum委煤,SIGSEGV是信號的名字,SEGV_MAPERR是SIGSEGV下的一種類型。
寄存器快照:進(jìn)程收到錯誤信號時保存下來的寄存器快照衔肢,其中PC寄存器存儲的就是下個要運(yùn)行的指令(出錯的位置)。
調(diào)用棧:#00是棧頂豁翎,#02是棧底角骤,#02調(diào)用#01調(diào)用#00方法,#00的方法時libspirit.so中的Spirit類下的testCrash方法,出錯的地方是testCrash方法內(nèi)匯編偏移17(不是行號哦0钭稹)
通常的來源有三個:
1背桐、硬件發(fā)生異常,即硬件(通常是CPU)檢測到一個錯誤條件并通知Linux內(nèi)核蝉揍,內(nèi)核處理該異常链峭,給相應(yīng)的進(jìn)程發(fā)送信號。硬件異常的例子包括執(zhí)行一條異常的機(jī)器語言指令又沾,諸如弊仪,被0除,或者引用了無法訪問的內(nèi)存區(qū)域杖刷。大部分信號如果沒有被進(jìn)程處理励饵,默認(rèn)的操作就是殺死進(jìn)程。在本文中挺勿,SIGSEGV(段錯誤)曲横,SIGBUS(內(nèi)存訪問錯誤),SIGFPE(算數(shù)異常)屬于這種信號不瓶。
2禾嫉、進(jìn)程調(diào)用的庫發(fā)現(xiàn)錯誤,給自己發(fā)送中止信號蚊丐,默認(rèn)情況下熙参,該信號會終止進(jìn)程。在本文中麦备,SIGABRT(中止進(jìn)程)屬于這種信號孽椰。
3、用戶(手賤)或第三方App(惡意)通過kill-信號 pid的方式給錯誤進(jìn)程發(fā)送凛篙,這時signal中的si_code會小于0黍匾。
SO庫奔潰總結(jié)方案:
1.添加日志信息
2.找到c的源代碼生成帶符號的so庫。
3.安裝bugly呛梆,分析具體那一行出了問題
4.jni異常和c++異常的基本分析和解決辦法
5.從奔潰信息中可以反饋一個問題:c比較安全锐涯,比較難破解
=====================================================
need-to-insert-img
在介紹工具之前,先簡單講一下有調(diào)試與無調(diào)試信息的兩個版本 so 填物。 一個含有 native 代碼的 app 項目的典型結(jié)構(gòu)是這樣的:
一般的分析崩潰日志的工具都是利用含有調(diào)試信息的 so纹腌, 結(jié)合崩潰信息,分析崩潰點(diǎn)在源代碼中的行號滞磺。
通常一次編譯會先生成一個有含有調(diào)試信息的 so升薯, 路徑通常是在 obj/local/ 各 abi 目錄下,其中還有一些中間文件(比如.o文件)击困;再通過對這些含有調(diào)試信息的 so 進(jìn)行一次 strip 涎劈, 產(chǎn)生對應(yīng)的無調(diào)試信息 so, 放到 libs 目錄下各 abi 目錄中, 發(fā)布產(chǎn)品時责语,我們都是用這些 strip 后的 so炮障。
————————————————
1.android如何編譯出帶符號表的.so庫
如果是mk:可以直接生成2種so庫
如果是cmake:debug版本就是帶符號的。release就是不帶符號的坤候。
用默認(rèn)的so庫路徑
#生成的so文件目錄
#set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/../../../../src/main/jniLibs/armebai-v7a)
把自己生成的注釋掉
bugly:分析有符號的so庫
https://bugly.qq.com/docs/user-guide/symbol-configuration-android/?v=1590754344571#_11
符號表:
need-to-insert-img
VS 編寫實(shí)現(xiàn)方法生成 dll 動態(tài)庫
使用VisualStudio高效開發(fā)調(diào)試AndroidNDK
cmake編譯so庫胁赢。然后同時生成apk。
會發(fā)現(xiàn):會先編譯然后生成的apk會把so打包進(jìn)去白筹。放心好了
===========================================================================
2.so庫奔潰具體行數(shù):定位so奔潰的行數(shù)
Android NDK墓碑/崩潰分析
閃退發(fā)生時在logcat中將日志過濾條件選為“No Filters”就可以看到完整的閃退日志智末,或者叫tombstone(墓碑)文件。
tombstone(墓碑)是當(dāng)系統(tǒng) crash 的時候徒河,會保存一個 tombstone 文件到/data/tombstones目錄下(Logcat中也會有相應(yīng)的信息)
https://blog.csdn.net/crash163/article/details/51605926
3.NDK安裝包中提供了三個調(diào)試工具:addr2line系馆、objdump和ndk-stack,
google官方提供的ndk-stack工具分析:
https://developer.android.google.cn/ndk/guides/ndk-stack?hl=zh-cn
4.bugly的定位原理:ndk-stack使用:
https://blog.csdn.net/xyang81/article/details/42319789
Android ndk-stack 定位so庫crash位置
如果你覺得上面的方法太麻煩的話顽照,ndk-stack可以幫你減輕操作步聚由蘑,直接定位到代碼出錯的位置。
使用adb獲取logcat的日志代兵,并通過管道輸出給ndk-stack分析尼酿,并指定包含符號表的so文件位置。如果程序包含多種CPU架構(gòu)植影,需要根據(jù)手機(jī)的CPU類型裳擎,來選擇不同的CPU架構(gòu)目錄。以armv7架構(gòu)為例思币,執(zhí)行如下命令:
1.運(yùn)行終端鹿响。?跳轉(zhuǎn)到你android sdk 目錄 因為你的adb 在里面。
如 cd /Users/name/Android/adt-bundle-mac-x86_64-20131030/sdk/platform-tools?
2谷饿、找了路徑正確繼續(xù)下一步惶我,./adb logcat | 你android ndk-stack所在的路徑 -sym /你安卓工程.so文件所在的目錄
如./adb logcat | /Users/name/Android/android-ndk-r8e/ndk-stack -sym /Users/name/test/proj.android/obj/local/armeabi
3、正確配置后會在終端出現(xiàn)
- waiting for device -
adb logcat | $NDK_HOME/ndk-stack -sym $PROJECT/libs/armeabi
其中博投,$PROJECT/libs/armeabi是so的路徑指孤。
adb logcat | $NDK_HOME/ndk-stack -sym /Users/mac/AiOpen/AiOpen/app/jni-libs/armeabi
adb logcat > /Users/mac/ndk/tongue.txt
$NDK_HOME/ndk-stack -sym /Users/mac/AiOpen/AiOpen/app/jni-libs/armeabi -dump /Users/mac/ndk/tongue.txt
可以看到具體的行數(shù)
need-to-insert-img
need-to-insert-img
總結(jié):
如果是so庫找不到,那么看不到詳情
null指針可以
5.so庫奔潰贬堵,日志種類分析:
http://www.reibang.com/p/d8ef41edb1bd(不錯)
結(jié)合signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0信息,配合崩潰信號列表:
信號描述
SIGSEGV內(nèi)存引用無效结洼。
SIGBUS訪問內(nèi)存對象的未定義部分黎做。
SIGFPE算術(shù)運(yùn)算錯誤,除以零松忍。
SIGILL非法指令蒸殿,如執(zhí)行垃圾或特權(quán)指令
SIGSYS糟糕的系統(tǒng)調(diào)用
SIGXCPU超過CPU時間限制。
SIGXFSZ文件大小限制。
1宏所、SIGSEGV 段錯誤
SEGV_MAPERR 要訪問的地址沒有映射到內(nèi)存空間酥艳。 比如上面對空指針的寫操作, 當(dāng)指針被意外復(fù)寫為一個較小的數(shù)值時爬骤。
SEGV_ACCERR 訪問的地址沒有權(quán)限充石。比如試圖對代碼段進(jìn)行寫操作。
2霞玄、SIGFPE 浮點(diǎn)錯誤骤铃,一般發(fā)生在算術(shù)運(yùn)行出錯時。
FPE_INTDIV 除以0
FPE_INTOVE 整數(shù)溢出
3坷剧、SIGBUS 總線錯誤
BUS_ADRALN 地址對齊出錯惰爬。arm cpu比x86 cpu 要求更嚴(yán)格的對齊機(jī)制,所以在 arm cpu 機(jī)器中比較常見惫企。
4撕瞧、SIGILL 發(fā)生這種錯誤一般是由于某處內(nèi)存被意外改寫了。
ILL_ILLOPC 非法的指令操作碼
ILL_ILLOPN 非法的指令操作數(shù)
5狞尔、當(dāng)調(diào)用堆棧中出現(xiàn) stack_chk_fail 函數(shù)時丛版,一般是由于比如 strcpy 之類的函數(shù)調(diào)用將棧上的內(nèi)容覆蓋,而引起棧檢查失敗沪么。
Testin崩潰分析如何幫開發(fā)者發(fā)現(xiàn)NDK錯誤
以上提到的方法硼婿,只適合在開發(fā)測試期間,如果你的應(yīng)用或游戲已經(jīng)上線禽车,而用戶經(jīng)常反饋說崩潰寇漫、閃退,指望用戶幫你收集信息定位問題幾乎是不可能的殉摔。這個時候州胳,我們就需要用其他的手段來捕獲崩潰信息。
目前業(yè)界已經(jīng)有一些公司推出了崩潰信息收集的服務(wù)逸月,通過嵌入SDK栓撞,在程序發(fā)生崩潰時收集堆棧信息,發(fā)送到云服務(wù)平臺碗硬,從而幫助開發(fā)者定位錯誤信息瓤湘。在這方面,國內(nèi)的Testin和國外的crittercism都可以提供類似服務(wù)恩尾。
Testin從1.4版本開始支持NDK的崩潰分析弛说,其最新版本已升級到1.7。當(dāng)程序發(fā)生NDK錯誤時翰意,其內(nèi)嵌的SDK會收集程序在用戶手機(jī)上發(fā)生崩潰時的堆棧信息(主要就是上面我們通過logcat日志獲取到的函數(shù)指針)木人、設(shè)備信息信柿、線程信息等,SDK將這些信息上報至Testin云服務(wù)平臺醒第,在平臺進(jìn)行唯一性的處理渔嚷、并可以自定義時段進(jìn)行詳盡的統(tǒng)計分析,從多維度展示程序崩潰的信息和嚴(yán)重程度稠曼;最新版本還支持用戶自定義場景形病,方便開發(fā)者定位問題所在。
從用戶手機(jī)上報的堆棧信息蒲列,Testin為NDK崩潰提供了符號化的功能窒朋,只要將我們編譯過程中產(chǎn)生的包含符號表的so文件上傳,就可以自動將函數(shù)指針地址定位到函數(shù)名稱和代碼行數(shù)蝗岖。符號化之后侥猩,看起來就和我們前面在本地測試的結(jié)果是一樣的了,一目了然抵赢。而且使用這個功能還有一個好處:這些包含符號表的so文件欺劳,在每次開發(fā)者編譯之后都會改變,很有可能我們發(fā)布之后就已經(jīng)變了铅鲤,因為開發(fā)者會修改程序划提。在這樣的情況下,即使我們拿到了崩潰時的堆棧信息邢享,那也無法再進(jìn)行符號化了鹏往。我們可以將這些文件上傳到Testin進(jìn)行符號化的工作,Testin會為我們保存和管理不同版本的so文件骇塘,確保信息不會丟失伊履。
NDK | 說說 so 庫從加載到卸載的全過程
https://juejin.cn/post/6892793299427491854
.so文件的區(qū)別
armeabi、armeabi-v7a和x86都表示CPU的類型款违。一般的手機(jī)或平板都是用arm的cpu唐瀑。
不同的cpu的特性不一樣,armeabi就是針對普通的或舊的
arm v5 cpu插爹,armeabi-v7a是針對有浮點(diǎn)運(yùn)算或高級擴(kuò)展功能的arm v7 cpu哄辣。
mips、armeabi赠尾、armeabi-v7a和x86到底是什么
armeabi:默認(rèn)選項力穗,將創(chuàng)建以基于
ARM* v5TE 的設(shè)備為目標(biāo)的庫。 具有這種目標(biāo)的浮點(diǎn)運(yùn)算使用軟件浮點(diǎn)運(yùn)算气嫁。 使用此 ABI (二進(jìn)制接口)
創(chuàng)建的二進(jìn)制代碼將可以在所有 ARM* 設(shè)備上運(yùn)行当窗。所以armeabi通用性很強(qiáng)。但是速度慢
armeabi-v7a:創(chuàng)建支持基于 ARM* v7 的設(shè)備的庫杉编,并將使用硬件 FPU 指令超全。armeabi-v7a是針對有浮點(diǎn)運(yùn)算或高級擴(kuò)展功能的arm v7 cpu。
x86:支持基于硬件的浮點(diǎn)運(yùn)算的?
總結(jié):
不同的CPU不用的芯片邓馒,armeabi是最基本的嘶朱,有不同的運(yùn)算指令,如浮點(diǎn)運(yùn)算光酣,所以需要生成不同的.so文件
如果項目只包含了?armeabi疏遏,那么在所有android設(shè)備都可以運(yùn)行; 如果項目只包含了 armeabi-v7a救军,除armeabi架構(gòu)的設(shè)備外都可以運(yùn)行财异;?
如果項目只包含了 x86,那么armeabi架構(gòu)和armeabi-v7a的Android設(shè)備是無法運(yùn)行的唱遭;
如果同時包含了 armeabi戳寸, armeabi-v7a和x86,
所有設(shè)備都可以運(yùn)行拷泽,程序在運(yùn)行的時候去加載不同平臺對應(yīng)的so疫鹊,這是較為完美的一種解決方案,同時也會導(dǎo)致包變大司致。
2. 接下來說明這么做的依據(jù):?
看上面圖分析拆吆,armeabi-v7主要不支持ARMv5(1998年誕生)和ARMv6(2001年誕生).目前這兩款處理器的手機(jī)設(shè)備基本不在我公司的適配范圍(市場占比太少)。?
而許多基于 x86 的設(shè)備也可運(yùn)行 armeabi-v7a 和 armeabi NDK 二進(jìn)制文件脂矫。對于這些設(shè)備枣耀,主要 ABI 將是 x86,輔助 ABI 是 armeabi-v7a庭再。?
最后總結(jié)一點(diǎn):如果適配版本高于4.1版本捞奕,可以直接像我上面這樣寫,當(dāng)然佩微,如果armeabi-v7a不是設(shè)備主要ABI缝彬,那么會在性能上造成一定的影響。?
---------------------?
早期的Android系統(tǒng)幾乎只支持ARMv5的CPU架構(gòu)哺眯。你知道現(xiàn)在它支持多少種嗎谷浅?7種!
Android系統(tǒng)目前支持以下七種不同的CPU架構(gòu):ARMv5奶卓,ARMv7 (從2010年起)一疯,x86 (從2011年起),MIPS (從2012年起)夺姑,ARMv8墩邀,MIPS64和x86_64 (從2014年起),每一種都關(guān)聯(lián)著一個相應(yīng)的ABI盏浙。
應(yīng)用程序二進(jìn)制接口(Application Binary Interface)定義了二進(jìn)制文件(尤其是.so文件)如何運(yùn)行在相應(yīng)的系統(tǒng)平臺上眉睹,從使用的指令集荔茬,內(nèi)存對齊到可用的系統(tǒng)函數(shù)庫。在Android系統(tǒng)上竹海,每一個CPU架構(gòu)對應(yīng)一個ABI:armeabi慕蔚,armeabi-v7a,x86斋配,mips孔飒,arm64-v8a,mips64艰争,x86_64坏瞄。
4. ABI 兼容性
目前搜索的資料總結(jié)如下:
armeabi-v7a :armeabi-v7a向下兼容armeabi
arm64-v8a : 能兼容 armeabi-v7a 和 armeabi
x86_64 : 兼容 x86
mips64 : 兼容 mips
目前主流 APP 所用的 ABI 各是哪些
數(shù)據(jù)是?2017/4/8看的市場最新版,采集的幾個代表性樣本如下:
僅有 armeabi :?微博甩卓,今日頭條鸠匀,淘寶,QQ猛频,微信狮崩。
armeabi 與 armeabi-v7a:?UC 瀏覽器。
armeabi鹿寻,armeabi-v7a睦柴,armeabi-x86:優(yōu)酷,嗶哩嗶哩動畫毡熏。
7種類型全有:知乎坦敌。
現(xiàn)在主要是armV7的架構(gòu)和x86
我也看了目前流行的游戲 王者榮耀(因為我只安裝了它。痢法。狱窘。哈哈),發(fā)現(xiàn)它僅有 armeabi-v7a财搁。
ABI和CPU的關(guān)系
很多設(shè)備都支持多于一種的ABI蘸炸。例如ARM64和x86設(shè)備也可以同時運(yùn)行armeabi-v7a和armeabi的二進(jìn)制包。但最好是針對特定平臺提供相應(yīng)平臺的二進(jìn)制包尖奔,這種情況下運(yùn)行時就少了一個模擬層(例如x86設(shè)備上模擬arm的虛擬層)
CPU/ABIarmeabiarmeabi-v7aarm64-v8ax86x86_64mipsmips64
ARMv5支持
ARMv7支持支持
ARMv8支持支持支持
x86支持支持 支持
x86_64支持 支持支持
mips 支持
mips_64 支持支持
need-to-insert-img
通過指令查看cpu的信息搭儒,包含cpu的架構(gòu)
如何查看so庫安裝在手機(jī)里面存放在了什么位置立美?和它到底加載哪個
你應(yīng)該盡可能的提供專為每個ABI優(yōu)化過的.so文件丹泉,但要么全部支持,要么都不支持:你不應(yīng)該混合著使用贡珊。你應(yīng)該為每個ABI目錄提供對應(yīng)的.so文件茴扁。
當(dāng)一個應(yīng)用安裝在設(shè)備上铃岔,只有該設(shè)備支持的CPU架構(gòu)對應(yīng)的.so文件會被安裝。在x86設(shè)備上峭火,libs/x86目錄中如果存在.so文件的話毁习,會被安裝智嚷,如果不存在,則會選擇armeabi-v7a中的.so文件纺且,如果也不存在纤勒,則選擇armeabi目錄中的.so文件(因為x86設(shè)備也支持armeabi-v7a和armeabi)。
正確的做法
當(dāng)前市面絕大多數(shù)是arm的CPU隆檀,而且都是V7架構(gòu)的了,所以可以保留armeabi或者armeabi-v7a即可粹湃。
如果僅保留armeabi-v7a恐仑,而有些第三方包未提供v7a的包,則可以將對應(yīng)armeabi包拷貝到armeabi-v7a为鳄。
如果同時保留armeabi和armeabi-v7a裳仆,則需要保證兩個目錄下的so庫文件數(shù)相同。
so庫:https://juejin.im/post/5eae6f86e51d454ddb0b3dc6
3.NDK問題 孤钦,so庫類型不對奔潰
ndk {
abiFilters"armeabi"
}
4.奔潰歧斟,因為找不到方法或者so庫奔潰,方法找不到原因:要包名一樣才行的
?java.lang.UnsatisfiedLinkError: No implementation found for double
6.NDK版本不對偏形,導(dǎo)致奔潰問題
完美解決 No toolchains found in the NDK toolchains folder for ABI with prefix: mips64el-linux-android
https://blog.csdn.net/qq_24118527/article/details/82867864
7..地址配置有問題:拼接
Unable to resolve host "open-api1.51yund.comauth": No address associated with hostname
==========================