AddressSanitizer (ASan), सिस्टम को तेज़ी से कंपाइल करने में मदद करने वाला टूल है नेटिव कोड में मेमोरी की गड़बड़ियों की संख्या.
ASan को पता चलता है:
- स्टैक और हीप बफ़र ओवरफ़्लो/अंडरफ़्लो
- मुफ़्त के बाद हीप का इस्तेमाल
- स्टैक का बाहरी दायरा इस्तेमाल करें
- डबल फ़्री/वाइल्ड फ़्री
ASan, 32-बिट और 64-बिट ARM, साथ ही, x86 और x86-64, दोनों पर काम करता है. ASan का सीपीयू ओवरहेड करीब दो गुना है, 50% से 2x के बीच कोड साइज़ का ओवरहेड 50% से 2x के बीच है. साथ ही, एक बड़ी मेमोरी ओवरहेड है यह आपके ऐलोकेशन पैटर्न पर निर्भर करता है. हालांकि, यह 2x के क्रम पर होता है.
AArch64 पर, Android 10 और AOSP की मुख्य ब्रांच जिस पर हार्डवेयर से सहायता पाने वाले AddressSanitizer (HWASan) की सुविधा काम करती हो, मिलता-जुलता टूल, जिसकी रैम कम होती है और कई तरह की गड़बड़ियों का पता चला है. HWASan, गड़बड़ियों के साथ-साथ, वापस आने के बाद स्टैक इस्तेमाल का पता लगाता है को ASan ने पता लगाया.
HWASan का सीपीयू और कोड साइज़ ओवरहेड एक जैसा है, लेकिन रैम का ओवरहेड काफ़ी कम है (15%). HWASan पूरी तरह से तय नहीं होता है. टैग की सिर्फ़ 256 वैल्यू हो सकती हैं. इसलिए, इसकी वैल्यू 0.4% है किसी गड़बड़ी के छूटने की संभावना को कम कर दिया जाता है. HWASan में, ASan के सीमित साइज़ के रेड ज़ोन उपलब्ध नहीं हैं अतिरिक्त सुविधाओं और सीमित क्षमता वाले क्वॉरंटीन का पता लगाना, ताकि उन्हें बिना किसी शुल्क के इस्तेमाल किए जाने का पता चल सके, इसलिए, इससे HWASan को कोई फ़र्क़ नहीं पड़ता कि ओवरफ़्लो कितना बड़ा है या मेमोरी कितनी पहले है असाइन किया गया था. यह HWASan को ASan से बेहतर बनाता है. यहां दी गई जानकारी पाने के लिए, इसकी डिज़ाइन HWASan या Android पर HWASan के इस्तेमाल के बारे में जानकारी.
ASan, स्टैक/ग्लोबल ओवरफ़्लो का पता लगाता है इसमें हीप ओवरफ़्लो के अलावा, कम से कम मेमोरी ओवरहेड के साथ तेज़ी से काम करता है.
इस दस्तावेज़ में, Android के सभी पार्ट/सभी डिवाइसों को बनाने और चलाने का तरीका बताया गया है असैन. अगर आपको ASan की मदद से, SDK टूल/NDK ऐप्लिकेशन बनाना है, तो अड्रेस सैनिटाइज़र आज़माएं.
ASan की मदद से, एक्ज़ीक्यूट किए जा सकने वाले व्यक्तिगत दस्तावेज़ों को साफ़ करें
LOCAL_SANITIZE:=address
या sanitize: { address: true }
को इसमें जोड़ें
बिल्ड नियम की शर्तों के बारे में बताता है. आप मौजूदा उदाहरणों के लिए कोड की खोज कर सकते है या
सैनिटाइज़र का इस्तेमाल नहीं कर सकते.
किसी बग का पता चलने पर, ASan
आउटपुट और logcat
तक भेजता है और फिर प्रोसेस को क्रैश कर देता है.
शेयर की गई लाइब्रेरी को ASan से साफ़ करें
ASan के काम करने के तरीके की वजह से, ASan के साथ बनाई गई लाइब्रेरी का इस्तेमाल सिर्फ़ एक्ज़ीक्यूटेबल जिसे ASan के साथ बनाया गया है.
एक से ज़्यादा एक्ज़ीक्यूटेबल में इस्तेमाल की जाने वाली शेयर लाइब्रेरी को साफ़ करने के लिए, न कि सभी
जिन्हें ASan के साथ बनाया गया है, तो आपको लाइब्रेरी की दो कॉपी की ज़रूरत होगी. कॉन्टेंट बनाने
ऐसा करने का सुझाया गया तरीका यह है कि आप Android.mk
में यह जानकारी जोड़ें
यहां दिए गए मॉड्यूल के लिए:
LOCAL_SANITIZE:=address LOCAL_MODULE_RELATIVE_PATH := asan
यह लाइब्रेरी को इसके बजाय /system/lib/asan
में रखता है
/system/lib
. इसके बाद, एक्ज़ीक्यूटेबल को इसके साथ चलाएं:
LD_LIBRARY_PATH=/system/lib/asan
सिस्टम डीमन के लिए, नीचे दिए गए विकल्पों को
/init.rc
या /init.$device$.rc
.
setenv LD_LIBRARY_PATH /system/lib/asanअभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है
पुष्टि करें कि प्रोसेस में /system/lib/asan
की लाइब्रेरी का इस्तेमाल किया जा रहा है
जब मौजूद होता है. /proc/$PID/maps
को पढ़कर सुनाएं. अगर ऐसा नहीं है, तो आपको
SELinux को अक्षम करने के लिए:
adb root
adb shell setenforce 0
# restart the process with adb shell kill $PID # if it is a system service, or may be adb shell stop; adb shell start.
बेहतर स्टैक ट्रेस
ASan, स्टैक को रिकॉर्ड करने के लिए, फ़्रेम-पॉइंटर की मदद से तेज़ी से काम करने वाले अनविंडर का इस्तेमाल करता है ट्रेस करता है. ज़्यादातर Android डिवाइस को फ़्रेम पॉइंटर के बिना बनाया गया है. इस वजह से, आपको अक्सर सिर्फ़ एक या दो सही फ़्रेम के साथ. इसे ठीक करने के लिए, या तो इसके साथ लाइब्रेरी को फिर से बनाएं ASan (सुझाया गया!), या इसके साथ:
LOCAL_CFLAGS:=-fno-omit-frame-pointer LOCAL_ARM_MODE:=arm
इसके अलावा, प्रोसेस में ASAN_OPTIONS=fast_unwind_on_malloc=0
को सेट करें
पर्यावरण को ध्यान में रखकर काम करना. बाद वाली प्रोसेस, सीपीयू की ज़रूरत के हिसाब से हो सकती है
लोड हो सके.
प्रतीक
शुरुआत में, ASan रिपोर्ट में बाइनरी और शेयर किए गए डेटा में ऑफ़सेट के रेफ़रंस शामिल होते हैं लाइब्रेरी. सोर्स फ़ाइल और लाइन की जानकारी पाने के दो तरीके हैं:
- पक्का करें कि
/system/bin
मेंllvm-symbolizer
बाइनरी मौजूद हो.llvm-symbolizer
को इसके स्रोतों से बनाया गया हैthird_party/llvm/tools/llvm-symbolizer
. external/compiler-rt/lib/asan/scripts/symbolize.py
के ज़रिए रिपोर्ट को फ़िल्टर करें स्क्रिप्ट.
दूसरे तरीके में ज़्यादा डेटा (यानी, file:line
जगह) मिल सकता है, क्योंकि
होस्ट पर सिंबल वाली लाइब्रेरी की उपलब्धता.
ऐप्लिकेशन में ASan
ASan, Java कोड को नहीं देख सकता. हालांकि, यह JNI में गड़बड़ियों का पता लगा सकता है
लाइब्रेरी. इसके लिए, आपको ASan के साथ एक्ज़ीक्यूटेबल बनाना होगा, जिसमें
यह मामला /system/bin/app_process(32|64)
का है. यह
ASan को डिवाइस पर मौजूद सभी ऐप्लिकेशन में एक साथ चालू करती है.
भारी लोड होता है, लेकिन 2 जीबी वाले डिवाइस में यह काम किया जा सकता है.
LOCAL_SANITIZE:=address
को इसमें जोड़ें
frameworks/base/cmds/app_process
में app_process
बिल्ड नियम. नज़रअंदाज़ करें
फ़िलहाल, इसी फ़ाइल में app_process__asan
टारगेट (अगर यह है)
उस समय भी वहाँ मौजूद रहेंगी).
इसके service zygote
सेक्शन में बदलाव करें
जोड़ने के लिए सही system/core/rootdir/init.zygote(32|64).rc
फ़ाइल
इंडेंट की गई लाइनों के ब्लॉक में आने वाली लाइनें, जिनमें class main
भी शामिल है
समान राशि से इंडेंट किया गया:
setenv LD_LIBRARY_PATH /system/lib/asan:/system/lib setenv ASAN_OPTIONS allow_user_segv_handler=true
बिल्ड, adb सिंक, फ़ास्टबूट फ़्लैश बूट, और फिर से चालू करें.
रैप प्रॉपर्टी का इस्तेमाल करना
पिछले सेक्शन में बताए गए तरीके से, ASan को सिस्टम में मौजूद ऐप्लिकेशन (वास्तव में, Zygote के हर वंशज में प्रक्रिया). ASan के साथ, सिर्फ़ एक या एक से ज़्यादा ऐप्लिकेशन को चलाया जा सकता है. ऐप्लिकेशन शुरू होने में ज़्यादा समय लगने की वजह से, कुछ मेमोरी ओवरहेड से ट्रेड करना शुरू कर दिया जाएगा.
अपने ऐप्लिकेशन को wrap.
प्रॉपर्टी से शुरू करके ऐसा किया जा सकता है.
नीचे दिया गया उदाहरण ASan के तहत Gmail ऐप्लिकेशन चलाता है:
adb root
adb shell setenforce 0 # disable SELinux
adb shell setprop wrap.com.google.android.gm "asanwrapper"
इस संदर्भ में, asanwrapper
/system/bin/app_process
को फिर से लिखता है
/system/bin/asan/app_process
को, जिसे इसके साथ बनाया गया है
असैन. यह शुरुआत में /system/lib/asan
भी जोड़ता है
डाइनैमिक लाइब्रेरी खोज पाथ. इस तरह से असैन-इंस्ट्रूमेंटेड
सामान्य लाइब्रेरी की तुलना में, /system/lib/asan
की लाइब्रेरी को प्राथमिकता दी जाती है
asanwrapper
की मदद से दौड़ने पर, /system/lib
में.
अगर कोई गड़बड़ी मिलती है, तो ऐप्लिकेशन क्रैश हो जाता है और रिपोर्ट लॉग.
SANITIZE_TARGET
Android 7.0 और उसके बाद के वर्शन में, Android 7.0 और इसके बाद के वर्शन के लिए, सभी सुविधाएं मिलती हैं. एक बार में असैन. (अगर आपको Android 9 से पहले के वर्शन वाली रिलीज़ बनानी है, तो HWASan बेहतर है.)
उसी बिल्ड ट्री में इन कमांड को चलाएं.
make -j42
SANITIZE_TARGET=address make -j42
इस मोड में, userdata.img
में अतिरिक्त लाइब्रेरी होती हैं और इन्हें
डिवाइस पर भी फ़्लैश हुआ. इस कमांड लाइन का इस्तेमाल करें:
fastboot flash userdata && fastboot flashall
यह शेयर की गई लाइब्रेरी के दो सेट बनाता है: सामान्य तौर पर
/system/lib
(पहली बार शुरू करने के लिए) और ASan
/data/asan/lib
(दूसरे नंबर पर शुरू करने के लिए). एक्ज़ीक्यूटेबल
दूसरा बिल्ड पहले बिल्ड से ओवरराइट हो जाता है. असैन-इंस्ट्रूमेंटेड
एक्ज़ीक्यूटेबल को अलग लाइब्रेरी का खोज पाथ मिलता है जिसमें
इस आइटम का इस्तेमाल करने पर, /system/lib
से पहले /data/asan/lib
मिलेंगे
PT_INTERP
में /system/bin/linker_asan
.
बिल्ड सिस्टम क्लोबर्स इंटरमीडिएट ऑब्जेक्ट डायरेक्ट्रीज़ को तब इकट्ठा करता है, जब
$SANITIZE_TARGET
की वैल्यू बदल गई है. यह सभी को फिर से बनाने के लिए मजबूर करता है
टारगेट. साथ ही, इंस्टॉल की गई बाइनरी को /system/lib
के अंदर सुरक्षित रखते हुए.
कुछ टारगेट ASan के साथ नहीं बनाए जा सकते:
- स्टैटिक रूप से लिंक किए गए एक्ज़ीक्यूटेबल
LOCAL_CLANG:=false
टारगेटSANITIZE_TARGET=address
के लिएLOCAL_SANITIZE:=false
, ASan's नहीं हैं
इस तरह की एक्ज़ीक्यूटेबल को SANITIZE_TARGET
बिल्ड में छोड़ दिया जाता है और
पहली बार शुरू करने का वर्शन /system/bin
में रहने दिया गया है.
इस तरह की लाइब्रेरी ASan के बिना बनाई गई हैं. उसमें ASan के साथ कुछ किया जा सकता है कोड की मदद से बनाया है, जिस पर वे निर्भर करते हैं.