欧美一级特黄大片做受成人-亚洲成人一区二区电影-激情熟女一区二区三区-日韩专区欧美专区国产专区

深入理解AndroidNDK日志符號化-創(chuàng)新互聯(lián)

為了進(jìn)行代碼及產(chǎn)品保護(hù),幾乎所有的非開源App都會進(jìn)行代碼混淆,這樣當(dāng)收集到崩潰信息后,就需 要進(jìn)行符號化來還原代碼信息,以便開發(fā)者可以定位Bug?;谑褂肧DK和NDK的不同,Android的崩潰分為兩類:Java崩潰和C/C++崩潰。Java崩潰通過mapping.txt文件進(jìn)行符號化,比較簡單直觀,而C/C++崩潰的符號化則需要使用Google自帶的一些NDK工具,比如ndk-stack、addr2line、objdump等。本文不去討論如何使用這些工具,有興趣的朋友可以參考同事寫的另一篇文章《如何定位Android NDK開發(fā)中遇到的錯誤》,里面做了詳細(xì)的描述。

站在用戶的角度思考問題,與客戶深入溝通,找到丹江口網(wǎng)站設(shè)計與丹江口網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗,讓設(shè)計與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個性化、用戶體驗好的作品,建站類型包括:做網(wǎng)站、成都做網(wǎng)站、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣、空間域名、雅安服務(wù)器托管、企業(yè)郵箱。業(yè)務(wù)覆蓋丹江口地區(qū)。

基于NDK的Android的開發(fā)都會生成一個動態(tài)鏈接庫(so),它是基于C/C++編譯生成的。動態(tài)鏈接庫在Linux系統(tǒng)下廣泛使用,而Android系統(tǒng)底層是基于Linux的,所以NDK so庫的編譯生成遵循相同的規(guī)則,只不過Google NDK把相關(guān)的交叉編譯工具都封裝了。

      Ndk-build編譯時會生成的兩個同名的so庫,位于不同的目錄/projectpath/libs/armeabi/xxx.so和/project path/obj/local/armeabi/xxx.so,比較兩個so文件會發(fā)現(xiàn)體積相差很大。前者會跟隨App一起發(fā)布,所以盡可能的小,而后者包含了很多調(diào)試信息,主要為了gdb調(diào)試的時候使用,當(dāng)然NDK的日志符號化信息也包含其中。

深入理解Android NDK日志符號化

    本文主要分析這個包含調(diào)試信息的so動態(tài)庫,深入分析它的組成結(jié)構(gòu)。在開始之前,先來說說這樣做的目的或者好處。現(xiàn)在的App基本都會采集上報崩潰時的日志信息,無論是采用第三方云平臺(如Testin崩潰分析+),還是自己搭建云服務(wù),都要將含調(diào)試信息的so動態(tài)庫上傳,實現(xiàn)云端日志符號化以及云端可視化管理。移動App的快速迭代,使得我們必須存儲管理每一個版本的debugso庫,而其包含了很多與符號化無關(guān)的信息。如果我們只提取出符號化需要的信息,那么符號化文件的體積將會呈現(xiàn)數(shù)量級的減少。同時可以在自定義的符號化文件中添加App的版本號等信息,實現(xiàn)符號化提取、上傳到云端、云端解析及可視化等自動化部署。另外,從技術(shù)角度講,你將不在害怕看到“unresolvedsymbol” linking errors,更從容地 debugging C/C++ crash或者h(yuǎn)acking一些so文件。

 首先通過readelf來看看兩個不同目錄下的so庫有什么不同

 深入理解Android NDK日志符號化

    從中可以清楚看到,包含調(diào)試信息的so庫多了8個.debug_開頭的條目以及.symtab和.strtab條目。符號化的本質(zhì),是通過堆棧中的地址信息,還原代碼本來的語句以及相應(yīng)的行號,所以這里只需解析.debug_line和.symtab,最終獲取到如下的信息就可以實現(xiàn)符號化了。

c85    c8b     willCrash       jni/hello-jni.c:27-29
c8b    c8d     willCrash       jni/hello-jni.c:32
c8d    c8f     JNI_OnLoad      jni/hello-jni.c:34
c8f    c93     JNI_OnLoad      jni/hello-jni.c:35
c93    c9d     JNI_OnLoad      jni/hello-jni.c:37

    通常,目標(biāo)文件分為三類:relocatable文件、executable文件和shared object文件,它們格式稱為ELF(Executableand Linking Format),so動態(tài)庫屬于第三類shared object,它的整體組織結(jié)構(gòu)如下:

ELF Header
Program header table
optional
Section 1
...
Section n
...
Section header table
required

ELF Header

ELF Header文件頭的結(jié)構(gòu)如下,記錄了文件其他內(nèi)容在文件中的偏移以及大小信息。這里以32bit為例。

typedef struct {
    unsigned char   e_ident[EI_NIDENT];
    Elf32_Half      e_type;          //目標(biāo)文件類型,如relocatable、executable和shared object
    Elf32_Half      e_machine;   // 指定需要的特定架構(gòu),如Intel 80386,Motorola 68000
    Elf32_Word      e_version;   // 目標(biāo)文件版本,通e_ident中的EI_VERSION
    Elf32_Addr      e_entry;       //指定入口點(diǎn)地址,如C可執(zhí)行文件的入口是_start(),而不是main()
    Elf32_Off       e_phoff;   // program header table 的偏移量
    Elf32_Off       e_shoff;   // section header table的偏移量
    Elf32_Word      e_flags;  // 處理器相關(guān)的標(biāo)志
    Elf32_Half      e_ehsize;  // 代表ELF Header部分的大小
    Elf32_Half      e_phentsize; // program header table中每一項的大小
    Elf32_Half      e_phnum;   // program header table包含多少項
    Elf32_Half      e_shentsize;  // section header table中每一項的大小
    Elf32_Half      e_shnum;  // section header table包含多少項
    Elf32_Half      e_shstrndx;  //section header table中某一子項的index,該子項包含了所有section的字符串名稱
} Elf32_Ehdr;

其中e_ident為固定16個字節(jié)大小的數(shù)組,稱為ELF Identification,包含了處理器類型、文件編碼格式、機(jī)器類型等,具體結(jié)構(gòu)如下:

NameValuePurpose
EI_MAG00

前四個字節(jié)稱為magic number,分別為0x7f、’E’、’L’、’F’,表明文件類型為ELF。

EI_MAG1

1
EI_MAG22
EI_MAG33

EI_CLASS

4

表明文件是基于32-bit還是64-bit,不同的方式,對齊方式不同,讀取某些內(nèi)容的大小不同。

EI_DATA5

表明文件數(shù)據(jù)結(jié)構(gòu)的編碼方式,主要分為大端和小端兩種

EI_VERSION

6

指定了ELF文件頭的版本號

EI_OSABI

7

指定使用了哪種OS-或者ABI-的ELF擴(kuò)展

EI_ABIVERSION8

指定該ELF目標(biāo)文件的目標(biāo)ABI版本

EI_PAD

9

保留字段起始處,直到第16個字節(jié)

EI_NIDENT16

代表了e_ident數(shù)組的大小,固定為16

Sections

該部分包含了除ELF Header、program header table以及section header table之外的所有信息。通過section header table可以找到每一個section的基本信息,如名稱、類型、偏移量等。

先來看看Section Header的內(nèi)容,仍以32-bit為例:

typedef struct {
	Elf32_Word	sh_name; // 指定section的名稱,該值為String Table字符串表中的索引
	Elf32_Word	sh_type; // 指定section的分類
	Elf32_Word	sh_flags; // 該字段的bit代表不同的section屬性
	Elf32_Addr	sh_addr; // 如果section出現(xiàn)在內(nèi)存鏡像中,該字段表示section第一個字節(jié)的地址
	Elf32_Off	sh_offset; // 指定section在文件中的偏移量
	Elf32_Word	sh_size; // 指定section占用的字節(jié)大小
	Elf32_Word	sh_link; // 相關(guān)聯(lián)的section header table的index
	Elf32_Word	sh_info; // 附加信息,意義依賴于section的類型
	Elf32_Word	sh_addralign; // 指定地址對其約束
	Elf32_Word	sh_entsize; // 如果section包含一個table,該值指定table中每一個子項的大小
} Elf32_Shdr;

通過Section Header的sh_name可以找到指定的section,比如.debug_line、.symbol、.strtab。

String Table

String Table包含一系列以\0結(jié)束的字符序列,最后一個字節(jié)設(shè)置為\0,表明所有字符序列的結(jié)束,比如:

深入理解Android NDK日志符號化

String Table也屬于section,只不過它的偏移量直接在ELF Header中的e_shstrndx字段指定。String Table的讀取方法是,從指定的index開始,直到遇到休止符。比如要section header中sh_name獲取section的名稱,比如sh_name = 7, 則從string table字節(jié)流的第7個index開始(注意這里從0開始),一直讀到第一個休止符(index=18),讀取到的名稱為.debug_line

Symbol Table

該部分包含了程序符號化的定義相關(guān)信息,比如函數(shù)定義、變量定義等,每一項的定義如下:

# Symbol Table Entry

typedef struct {
	Elf32_Word	st_name; //symbol字符串表的索引
	Elf32_Addr	st_value; //symbol相關(guān)的值,依賴于symbol的類型
	Elf32_Word	st_size; //symbol內(nèi)容的大小
	unsigned char	st_info;   //symbol的類型及其屬性
	unsigned char	st_other;  //symbol的可見性,比如類的public等屬性
	Elf32_Half	st_shndx; //與此symbol相關(guān)的section header的索引
} Elf32_Sym;

Symbol的類型包含一下幾種

NameValue
STT_NOTYPE0
STT_OBJECT1

STT_FUNC

2

STT_SECTION

3

STT_FILE

4

STT_COMMO

5

STT_TLS

6

STT_LOOS

10
STT_HIOS12

STT_LOPRO

13

STT_HIPROC

15

其中STT_FUNC就是我們要找的函數(shù)symbol。然后通過st_name從symbol字符串表中獲取到相應(yīng)的函數(shù)名(如JNI_OnLoad)。當(dāng)symbol類型為STT_FUNC時,st_value代表該symbol的起始地址,而(st_value+st_size)代表該symbol的結(jié)束地址。

回顧之前的提到的.symtab和.strtab兩個部分,對應(yīng)的便是Symbol Section和Symbol String Section。

DWARF(Debugging With Attributed Record Formats)

DWARF是一種調(diào)試文件格式,很多編譯器和調(diào)試器都通過它進(jìn)行源碼調(diào)試(gdb等)。盡管它是一種獨(dú)立 的目標(biāo)文件格式,但往往嵌入在ELF文件中。前面通過readelf看到的8個.debug_* Section全部都屬于DWARF格式。本文將只討論與符號化相關(guān)的.debug_line部分,更多的DWARF信息請查看參考文獻(xiàn)的內(nèi)容。

.debug_line部分包含了行號信息,通過它可以將代碼語句和機(jī)器指令地址對應(yīng),從而進(jìn)行源碼調(diào)試。.debug_line有很多子項組成,每個子項都包含類似數(shù)據(jù)塊頭的描述,稱為Statement Program Prologue。Prologue提供了解碼程序指令和跳轉(zhuǎn)到其他語句的信息,它包含如下字段,這些字段是以二進(jìn)制格式順序存在的:

total_length

uword

整個子項占用的字節(jié)大小,注意并不包括該字段本身

versio

uhalf

該子項格式的版本號,其實也是整個DWARF格式的版本號,目前總共有四個版本。

prologue_length

uword

prologue的長度,不包括該字段及前面的兩個字段占用的字節(jié)數(shù),即相對于本字段,程序語句本身的第一個字節(jié)的偏移量

minimum_instruction_length

ubyte

最小的目標(biāo)機(jī)器指令

default_is_stmt

ubyte

is_stmt寄存器的初始值

line_base

sbyte

不同的操作碼,代表不同的含義,只影響special opcodes

line_range

ubyte

不同的操作碼,代表不同的含義,只影響special opcodes

opcode_base

ubyte

第一個操作碼的數(shù)值

standard_opcode_lengths

array of ubyte

標(biāo)準(zhǔn)操作碼的LEB128操作數(shù)的數(shù)值

include_directories

sequence

目錄名字符序列

file_names

sequence

源代碼所在文件名字符序列

這里用到的機(jī)器指令可以分為三類:

special opcodes

單字節(jié)操作碼,不含參數(shù),大多數(shù)指令屬于此類

standard opcodes

單字節(jié)操作碼,可以包含0個或者多個LEB128參數(shù)

extended opcodes

多字節(jié)操作碼

這里不做機(jī)器指令的解析說明,感興趣的,可以查看參考文獻(xiàn)的內(nèi)容。

通過.debug_line,我們最終可以獲得如下信息:文件路徑、文件名、行號以及起始地址。

最后我們匯總一下整個符號化提取的過程:

1、從ELF Header中獲知32bit或者64bit,以及大端還是小端,基于此讀取后面的內(nèi)容

2、從ELF Header中獲得Section Header Table在文件中的位置

3、讀取Section Header Table,從中獲得.debug_line、.symtab以及.strtab三個section在文中的位置

4、讀取.symtab和.strtab兩個section,最后獲得所有function symbol的名稱、起始地址以及結(jié)束地址

5、讀取.debug_line,按照DWARF格式解析獲取文件名稱、路徑、行號以及起始地址

6、對比步驟4和5中獲取的結(jié)果,進(jìn)行對比合并,形成最終的結(jié)果

參考文獻(xiàn):

http://www.csdn.net/article/2014-12-30/2823366-Locate-Android-NDK

http://eli.thegreenplace.net/2011/02/07/how-debuggers-work-part-3-debugging-information/

http://www.sco.com/developers/gabi/latest/ch5.intro.html

http://www.dwarfstd.org/

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價比高”等特點(diǎn)與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。

當(dāng)前文章:深入理解AndroidNDK日志符號化-創(chuàng)新互聯(lián)
文章轉(zhuǎn)載:http://aaarwkj.com/article18/gjpdp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站建設(shè)、網(wǎng)站收錄網(wǎng)站排名、定制開發(fā)、虛擬主機(jī)自適應(yīng)網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

網(wǎng)站建設(shè)網(wǎng)站維護(hù)公司
久久99精品人妻一区二区三区| 久久精品91久久久| 免费人成网站在线观看| 在线一区二区三区高清视频 | 九九六热这里只有精品| 中文字幕乱码亚洲影视| 精品久久久久久亚洲野狼| 欧美另类精品一区二区| 亚洲ve中文字幕久久一区二区| 熟妇人妻内射一区二区三区| 日本欧美高清一区二区| 黄色av网站在线免费| 亚洲国产区男人的天堂| 国产精品久久久久精品综合| 18禁视频免费无遮挡| 国产欧美日韩综合91| 男女生做刺激性视频网站| 日韩精品毛片一区到三区| 亚洲五月婷婷久久综合| 欧美精品中出一区二区三区| 午夜精品一区二区三区在线视频| 一本之道久久成人综合| 国产丝袜美腿在线观看| 天天操天天日天天射夜夜爽| 蜜臀久久精品国产综合| 色吊最新在线视频免费观看| 欧美高清视频看片在线观看| 欧美日韩精品亚洲成人精品| 国产精品大屁股白浆一区二区| 欧美影院波波在线影院| 日本成熟妇高潮视频在线观看不卡| 日本高清视频免费一区| 五月婷久久精品国产亚洲av| 加勒比在线观看欧美一区| 97国产在线视频观看| 91出品国产福利在线| 欧美精品高清在线视频| 色悠悠色综合视频在线| 日韩高清一级黄色大片网站| 久久午夜av一区二区| 91欧美一区二区在线视频|