亚洲xxxx做受欧美,丰满熟妇bbwhd,无码人妻丰满熟妇区96,无码人妻丰满熟妇区96

Back

AddressSanitizer使用介紹

by WANGWANG


 

1、關(guān)于AddressSanitizer

1.1 引言

也許很多人都聽說過類似這樣的一個(gè)故事:某公司的服務(wù)器每隔3個(gè)月就會(huì)毫無預(yù)兆的崩潰一次,怎么也查不出原因,為了避免崩潰可能引發(fā)的問題,只得每2個(gè)月手動(dòng)重啟一次服務(wù)器。在這類有些靈異的事件背后,以內(nèi)存泄露為代表的一系列內(nèi)存錯(cuò)誤往往就是那個(gè)幕后黑手。


在計(jì)算機(jī)科學(xué)中,內(nèi)存泄漏指由于疏忽或錯(cuò)誤造成程序未能釋放已經(jīng)不再使用的內(nèi)存的情況。內(nèi)存泄漏并非指內(nèi)存在物理上的消失,而是應(yīng)用程序分配某段內(nèi)存后,由于設(shè)計(jì)錯(cuò)誤,失去了對(duì)該段內(nèi)存的控制,因而造成了內(nèi)存的浪費(fèi)。


內(nèi)存泄漏會(huì)導(dǎo)致可用內(nèi)存的數(shù)量減少從而降低計(jì)算機(jī)的性能。過多的可用內(nèi)存被分配掉會(huì)導(dǎo)致全部或部分設(shè)備停止正常工作,或者應(yīng)用程序崩潰。


其他的內(nèi)存錯(cuò)誤還包括緩沖區(qū)溢出、越界訪問等,此類錯(cuò)誤輕則導(dǎo)致程序計(jì)算錯(cuò)誤,重則引起程序崩潰,在內(nèi)存緊張的嵌入式系統(tǒng)中尤為致命,Google旗下的開源工具AddressSanitizer可以幫助我們檢測此類錯(cuò)誤。


AddressSanitizer(ASan)是一個(gè)快速的內(nèi)存錯(cuò)誤檢測工具。它非常快,只拖慢程序兩倍左右。它包括一個(gè)編譯器instrumentation模塊和一個(gè)提供malloc()/free()替代項(xiàng)的運(yùn)行時(shí)庫。從gcc 4.8開始,AddressSanitizer成為gcc的一部分。


詳細(xì)了解AddressSanitizer信息可以訪問其github項(xiàng)目地址:
https://github.com/google/sanitizers/wiki/AddressSanitizer

 

1.2 AddressSanitizer原理簡介

AddressSanitizer主要包括兩部分:插樁(Instrumentation)和動(dòng)態(tài)運(yùn)行庫(Run-time library)。插樁主要是針對(duì)在llvm編譯器級(jí)別對(duì)訪問內(nèi)存的操作(store,load,alloca等),將它們進(jìn)行處理。動(dòng)態(tài)運(yùn)行庫主要提供一些運(yùn)行時(shí)的復(fù)雜的功能(比如poison/unpoison shadow memory)以及將malloc,free等系統(tǒng)調(diào)用函數(shù)hook住。該算法的思路是:如果想防住Buffer Overflow漏洞,只需要在每塊內(nèi)存區(qū)域右端(或兩端,能防overflow和underflow)加一塊區(qū)域(RedZone),使RedZone的區(qū)域的影子內(nèi)存(Shadow Memory)設(shè)置為不可寫即可。具體的示意圖如下圖所示。

 

 

內(nèi)存映射

AddressSanitizer保護(hù)的主要原理是對(duì)程序中的虛擬內(nèi)存提供粗粒度的影子內(nèi)存(每8個(gè)字節(jié)的內(nèi)存對(duì)應(yīng)一個(gè)字節(jié)的影子內(nèi)存),為了減少overhead,采用了直接內(nèi)存映射策略,所采用的具體策略如下:Shadow=(Mem >> 3) + offset。每8個(gè)字節(jié)的內(nèi)存對(duì)應(yīng)一個(gè)字節(jié)的影子內(nèi)存,影子內(nèi)存中每個(gè)字節(jié)存取一個(gè)數(shù)字k,如果k=0,則表示該影子內(nèi)存對(duì)應(yīng)的8個(gè)字節(jié)的內(nèi)存都能訪問,如果0<k<7,表示前k個(gè)字節(jié)可以訪問,如果k為負(fù)數(shù),不同的數(shù)字表示不同的錯(cuò)誤(e.g. Stack buffer overflow, Heap buffer overflow)。

 

插樁

為了防止buffer overflow,需要將原來分配的內(nèi)存兩邊分配額外的內(nèi)存Redzone,并將這兩邊的內(nèi)存加鎖,設(shè)為不能訪問狀態(tài),這樣可以有效的防止buffer overflow(但不能杜絕buffer overflow)。以下是在棧中插樁的一個(gè)例子。

 

未插樁的代碼:

 

插樁后的代碼:

 

插樁后的代碼:

在動(dòng)態(tài)運(yùn)行庫中將malloc/free函數(shù)進(jìn)行了替換。在malloc函數(shù)中額外的分配了Redzone區(qū)域的內(nèi)存,將與Redzone區(qū)域?qū)?yīng)的影子內(nèi)存加鎖,主要的內(nèi)存區(qū)域?qū)?yīng)的影子內(nèi)存不加鎖。
free函數(shù)將所有分配的內(nèi)存區(qū)域加鎖,并放到了隔離區(qū)域的隊(duì)列中(保證在一定的時(shí)間內(nèi)不會(huì)再被malloc函數(shù)分配),可檢測Use after free類的問題。
詳細(xì)了解ASan算法原理可以訪問以下地址:
https://github.com/google/sanitizers/wiki/AddressSanitizerAlgorithm

 

2、使用方法

環(huán)境:Ubuntu 16.04   gcc 4.8以上
用-fsanitize=address選項(xiàng)編譯和鏈接你的程序;
用-fno-omit-frame-pointer編譯,以在錯(cuò)誤消息中添加更好的堆棧跟蹤。
增加-O1以獲得更好的性能。
下面以簡單的測試代碼leaktest.c為例

 

 

在終端中輸入以下命令編譯leaktest.c

 

 

運(yùn)行l(wèi)eaktest,會(huì)打印下面的錯(cuò)誤信息:

 

 

第一部分(ERROR),指出錯(cuò)誤類型detected memory leaks;
第二部分給出詳細(xì)的錯(cuò)誤信息:Direct leak of 80 byte(s) in 1 object(s),以及發(fā)生錯(cuò)誤的對(duì)象名/源文件位置/行數(shù);
第三部分是以上信息的一個(gè)總結(jié)(SUMMARY)。
 

3、設(shè)置檢測白名單

可以根據(jù)以下的需求設(shè)置ASan檢測白名單
忽略一個(gè)確定正確的函數(shù)以提高應(yīng)用運(yùn)行速度;
忽略一個(gè)特定功能的函數(shù)(例如:繞過框架邊界穿過線程的堆棧);
忽略已知的問題。

使用no_sanitize_address屬性(Clang3.3及GCC4.8以上版本支持)定義如下的宏命令:

 

4、AddressSanitizer能檢測的錯(cuò)誤類型(以官方Wiki為準(zhǔn))

請您填寫郵箱地址,以獲得下載權(quán)限。
主站蜘蛛池模板: 凌云县| 湘乡市| 黄梅县| 镇原县| 晋城| 民乐县| 共和县| 开封县| 柞水县| 万州区| 富蕴县| 扎兰屯市| 阿坝| 磐安县| 登封市| 重庆市| 贞丰县| 邵阳县| 廉江市| 宝丰县| 岫岩| 银川市| 旺苍县| 长乐市| 阿瓦提县| 武平县| 陆川县| 班玛县| 华容县| 会昌县| 九江市| 汤阴县| 永顺县| 泰顺县| 县级市| 甘肃省| 罗平县| 嘉鱼县| 且末县| 建瓯市| 固原市|