HWASan की रिपोर्ट को समझना

जब HWASan टूल को मेमोरी से जुड़ी कोई गड़बड़ी का पता चलता है, तो प्रोसेस को abort() के साथ बंद कर दिया जाता है. साथ ही, stderr और logcat में एक रिपोर्ट प्रिंट की जाती है. Android पर होने वाली सभी नेटिव क्रैश की तरह, HWASan की गड़बड़ियां भी /data/tombstones में आती हैं.

उदाहरण के तौर पर दी गई रिपोर्ट

सामान्य नेटिव क्रैश की तुलना में, HWASan में टॉम्बस्टोन के सबसे ऊपर मौजूद Abort message फ़ील्ड में ज़्यादा जानकारी होती है. यहां हेप पर आधारित क्रैश का सैंपल दिया गया है. स्टैक से जुड़ी गड़बड़ियों के लिए, स्टैक से जुड़े सेक्शन के लिए नोट देखें.

*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Build fingerprint: 'google/flame_hwasan/flame:Tiramisu/MASTER/7956676:userdebug/dev-keys'
Revision: 'DVT1.0'
ABI: 'arm64'
Timestamp: 2019-04-24 01:13:22+0000
pid: 11154, tid: 11154, name: sensors@1.0-ser  >>> /vendor/bin/hw/android.hardware.sensors@1.0-service <<<
signal 6 (SIGABRT), code -1 (SI_QUEUE), fault addr --------
Abort message: '

[...]

[0x00433ae20040,0x00433ae20060) is a small unallocated heap chunk; size: 32 offset: 5








[ … regular crash dump follows …]

यह AddressSanitizer रिपोर्ट से मिलती-जुलती है. इनके उलट, HWASan के ज़्यादातर गड़बड़ियां, टैग मैच न होने की वजह से होती हैं. इसका मतलब है कि मेमोरी ऐक्सेस करने के दौरान, पॉइंटर टैग, उससे जुड़े मेमोरी टैग से मेल नहीं खाता. यह इनमें से कोई भी हो सकता है:

  • स्टैक या ढेर पर, तय सीमा से ज़्यादा ऐक्सेस
  • हीप पर, इस्तेमाल के बाद मुक्त करने से जुड़ी गड़बड़ी
  • स्टैक पर, रिटर्न के बाद इस्तेमाल करने से जुड़ी गड़बड़ी

सेक्शन

यहां HWASan रिपोर्ट के हर सेक्शन के बारे में जानकारी दी गई है.

ऐक्सेस करने से जुड़ी गड़बड़ी

इसमें मेमोरी के गलत ऐक्सेस के बारे में जानकारी होती है. जैसे:

  • ऐक्सेस टाइप (READ बनाम WRITE)
  • ऐक्सेस साइज़ (कितने बाइट ऐक्सेस करने की कोशिश की गई)
  • ऐक्सेस की थ्रेड नंबर
  • पॉइंटर और मेमोरी टैग (बेहतर तरीके से डीबग करने के लिए)

स्टैक ट्रेस ऐक्सेस करना

गलत मेमोरी ऐक्सेस का स्टैक ट्रेस. वैल्यू को दिखाने के लिए, सिंबलाइज़ेशन देखें.

वजह

ऐक्सेस की समस्या की संभावित वजह. अगर एक से ज़्यादा उम्मीदवार हैं, तो उन्हें सबसे ज़्यादा संभावना से लेकर सबसे कम संभावना के क्रम में सूची में शामिल किया जाता है. इसकी मदद से, समस्या की संभावित वजह के बारे में पूरी जानकारी मिलती है. HWASan इन वजहों का पता लगा सकता है:

  • मुफ़्त में आज़माने के बाद इस्तेमाल करना
  • स्टैक टैग का मेल न खाना. यह रिटर्न के बाद स्टैक का इस्तेमाल, स्कोप के बाद स्टैक का इस्तेमाल या स्टैक के दायरे से बाहर का इस्तेमाल हो सकता है
  • हीप बफ़र ओवरफ़्लो
  • ग्लोबल ओवरफ़्लो

मेमोरी की जानकारी

इससे पता चलता है कि ऐक्सेस की जा रही मेमोरी के बारे में HWASan को क्या पता है. यह जानकारी, गड़बड़ी के टाइप के हिसाब से अलग-अलग हो सकती है:

गड़बड़ी का टाइप वजह रिपोर्ट का फ़ॉर्मैट
टैग मेल नहीं खाना मुफ़्त में आज़माने के बाद इस्तेमाल करना रिपोर्ट के लिए इस फ़ॉर्मैट का इस्तेमाल करें:
<address> is located N bytes inside of M-byte region [<start>, <end>)
freed by thread T0 here:
हीप बफ़र ओवरफ़्लो ध्यान दें कि यह अंडरफ़्लो भी हो सकता है.
<address> is located N bytes to the right of M-byte region [<start>, <end>)
allocated here:
स्टैक टैग मेल नहीं खाना स्टैक रिपोर्ट में, ओवरफ़्लो या अंडरफ़्लो और इस्तेमाल के बाद रिटर्न करने वाले बग के बीच अंतर नहीं किया जाता. इसके अलावा, गड़बड़ी का सोर्स कौनसा स्टैक ऐलोकेशन है, यह पता लगाने के लिए, ऑफ़लाइन सिंबलाइज़ेशन का चरण ज़रूरी है. स्टैक रिपोर्ट को समझना लेख पढ़ें.
अमान्य फ़्री मुफ़्त में आज़माने के बाद इस्तेमाल करना डबल फ़्री बग. अगर ऐसा प्रोसेस बंद होने पर होता है, तो इसका मतलब ओडीआर (ऑनलाइन विवाद समाधान) की नीति का उल्लंघन हो सकता है.
<address> is located N bytes inside of M-byte region [<start>, <end>)
freed by thread T0 here:
पते की जानकारी नहीं दी जा सकती वाइल्ड फ़्री (ऐसी मेमोरी जो पहले से एलोकेट नहीं की गई थी) या एलोकेट की गई मेमोरी को HWASan के फ़्री बफ़र से हटाने के बाद, डबल फ़्री.
0x..., एचडब्ल्यूएएसएन शैडो मेमोरी है ऐप्लिकेशन, HWASan में मौजूद मेमोरी को खाली करने की कोशिश कर रहा था.

डिएलॉकेशन स्टैक ट्रेस

मेमोरी को कहां से डिएलोकेट किया गया था, इसका स्टैक ट्रेस. सिर्फ़ उन गड़बड़ियों के लिए मौजूद है जो इस्तेमाल करने के बाद ठीक हो जाती हैं या जो अमान्य हैं. डेटा को सिंबल के तौर पर दिखाने के लिए, सिंबलाइज़ेशन देखें.

ऐलोकेशन स्टैक ट्रेस

मेमोरी को कहां सेट किया गया था, इसका स्टैक ट्रेस. डेटा को सिंबल के तौर पर दिखाने के लिए, सिंबलाइज़ेशन देखें.

डीबग करने के बारे में बेहतर जानकारी

HWASan रिपोर्ट में, डीबग करने से जुड़ी कुछ बेहतर जानकारी भी शामिल होती है. इसमें ये चीज़ें शामिल हैं:

  1. प्रोसेस में शामिल थ्रेड की सूची
  2. प्रोसेस में शामिल थ्रेड की सूची
  3. गड़बड़ी वाली मेमोरी के आस-पास मौजूद मेमोरी टैग की वैल्यू
  4. मेमोरी ऐक्सेस करने के समय रजिस्टर का डंप

मेमोरी टैग का डंप

टैग मेमोरी डंप का इस्तेमाल करके, पॉइंटर टैग के जैसे ही टैग के साथ आस-पास के मेमोरी ऐलोकेशन देखे जा सकते हैं. ये टैग, बड़े ऑफ़सेट के साथ, दायरे से बाहर के ऐक्सेस की ओर इशारा कर सकते हैं. एक टैग, 16 बाइट मेमोरी से जुड़ा होता है; पॉइंटर टैग, पते के सबसे ऊपर के 8 बिट होते हैं. टैग मेमोरी डंप से आपको कुछ अहम जानकारी मिल सकती है. उदाहरण के लिए, दाईं ओर मौजूद बफ़र ओवरफ़्लो:

tags: ad/5c (ptr/mem)
[...]
Memory tags around the buggy address (one tag corresponds to 16 bytes):
  0x006f33ae1ff0: 0e  0e  0e  57  20  20  20  20  20  2e  5e  5e  5e  5e  5e  b5
=>0x006f33ae2000: f6  f6  f6  f6  f6  4c  ad  ad  ad  ad  ad  ad [5c] 5c  5c  5c
  0x006f33ae2010: 5c  04  2e  2e  2e  2e  2e  2f  66  66  66  66  66  80  6a  6a
Tags for short granules around the buggy address (one tag corresponds to 16 bytes):
  0x006f33ae1ff0: ab  52  eb  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..
=>0x006f33ae2000: ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  .. [..] ..  ..  ..
  0x006f33ae2010: ..  5c  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..

बाईं ओर मौजूद, पॉइंटर टैग से मैच करने वाले ad टैग के 6 × 16 = 96 बाइट के रन पर ध्यान दें.

अगर किसी ऐलोकेशन का साइज़ 16 का मल्टीपल नहीं है, तो बाकी बचे साइज़ को मेमोरी टैग के तौर पर स्टोर किया जाता है. साथ ही, टैग को छोटे ग्रैनल टैग के तौर पर स्टोर किया जाता है. पिछले उदाहरण में, बोल्ड किए गए ऐलोकेशन के ठीक बाद, हमारे पास टैग 5c के लिए 5 × 16 + 4 = 84 बाइट का ऐलोकेशन है.ad

शून्य मेमोरी टैग (उदाहरण के लिए, tags: ad/00 (ptr/mem)), स्टैक-इस्तेमाल-बाद-रिटर्न बग को दिखाता है.

रजिस्टर डंप

HWASan रिपोर्ट में रजिस्टर का डंप, उस निर्देश से जुड़ा होता है जिसने अमान्य मेमोरी ऐक्सेस किया है. इस डंप के बाद, Android के सामान्य सिग्नल हैंडलर से एक और रजिस्टर डंप मिलता है. दूसरे डंप को अनदेखा करें, क्योंकि इसे तब लिया गया था, जब HWASan ने abort() को कॉल किया था और यह बग के लिए काम का नहीं है.

सिंबलाइज़ेशन

स्टैक ट्रेस में फ़ंक्शन के नाम और लाइन नंबर पाने के लिए, ऑफ़लाइन सिंबलाइज़ेशन की ज़रूरत होती है. साथ ही, 'स्कोप के बाद इस्तेमाल करने से जुड़ी गड़बड़ियों' के लिए वैरिएबल के नाम पाने के लिए भी ऐसा करना ज़रूरी है.

पहली बार सेटअप करने के लिए: llvm-symbolizer इंस्टॉल करना

सिंबल बनाने के लिए, आपके सिस्टम में llvm-symbolizer इंस्टॉल होना चाहिए और $PATH से ऐक्सेस किया जा सकता हो. Debian पर, sudo apt install llvm का इस्तेमाल करके इसे इंस्टॉल किया जा सकता है.

सिंबल फ़ाइलें पाना

सिंबल बनाने के लिए, हमें ऐसे बाइनरी की ज़रूरत होती है जिनमें सिंबल शामिल हों. उनकी जगह, बिल्ड के टाइप पर निर्भर करती है:

  • लोकल बिल्ड के लिए, सिंबल फ़ाइलें out/target/product/<product>/symbols/ में होती हैं.
  • AOSP बिल्ड (उदाहरण के लिए, Android Flash Tool से फ़्लैश किए गए) के लिए, बिल्ड Android CI पर मौजूद होते हैं. बिल्ड के लिए आर्टफ़ैक्ट में, एक ${PRODUCT}-symbols-${BUILDID}.zip फ़ाइल है.
  • अपने संगठन के इंटरनल बिल्ड के लिए, सिंबल फ़ाइलें पाने में मदद पाने के लिए, अपने संगठन का दस्तावेज़ देखें.

निशान लगाना

hwasan_symbolize --symbols <DECOMPRESSED_DIR>/out/target/product/*/symbols < crash

स्टैक रिपोर्ट को समझना

स्टैक वैरिएबल से जुड़ी गड़बड़ियों के लिए, HWASan रिपोर्ट में यह जानकारी शामिल होती है:

Cause: stack tag-mismatch
Address 0x007d4d251e80 is located in stack of thread T64
Thread: T64 0x0074000b2000 stack: [0x007d4d14c000,0x007d4d255cb0) sz: 1088688 tls: [0x007d4d255fc0,0x007d4d259000)
Previously allocated frames:
  record_addr:0x7df7300c98 record:0x51ef007df3f70fb0  (/apex/com.android.art/lib64/libart.so+0x570fb0)
  record_addr:0x7df7300c90 record:0x5200007df3cdab74  (/apex/com.android.art/lib64/libart.so+0x2dab74)
  [...]

स्टैक बग को समझने में आपकी मदद करने के लिए, HWASan पिछले स्टैक फ़्रेम को ट्रैक करता है. HWASan, गड़बड़ी की रिपोर्ट में इन डेटा को लोगों के समझने लायक कॉन्टेंट में बदलता नहीं है. इसके लिए, सिंबल बनाने के लिए एक और चरण की ज़रूरत होती है.

ओडीआर (ऑनलाइन विवाद समाधान) के उल्लंघन

HWASan की ओर से रिपोर्ट किए गए, इस्तेमाल के बाद मुक्त होने वाले कुछ बग, One Definition Rule (ODR) के उल्लंघन का संकेत दे सकते हैं. ओडीआर का उल्लंघन तब होता है, जब एक ही प्रोग्राम में एक ही वैरिएबल को कई बार तय किया जाता है. इसका मतलब यह भी है कि वैरिएबल को कई बार हटाया जाता है. इससे, इस्तेमाल के बाद हटाने से जुड़ी गड़बड़ी हो सकती है.

सिंबलाइज़ेशन के बाद, ODR के उल्लंघनों से __cxa_finalize के साथ, इस्तेमाल के बाद मुक्त करने से जुड़ी गड़बड़ी दिखती है. यह गड़बड़ी, अमान्य ऐक्सेस स्टैक और यहां मुक्त किया गया स्टैक, दोनों पर दिखती है. पहले यहां सेट किए गए स्टैक में __dl__ZN6soinfo17call_constructorsEv है. साथ ही, यह आपके प्रोग्राम में उस जगह पर ले जाना चाहिए जो स्टैक में वैरिएबल को ऊपर सेट करता है.

स्टैटिक लाइब्रेरी का इस्तेमाल करने पर, ओडीआर का उल्लंघन हो सकता है. अगर C++ ग्लोबल की जानकारी देने वाली स्टैटिक लाइब्रेरी को कई शेयर की गई लाइब्रेरी या रन किए जा सकने वाले प्रोग्राम में लिंक किया जाता है, तो एक ही पता स्पेस में एक ही सिंबल की कई परिभाषाएं मौजूद हो सकती हैं. इस वजह से, ओडीआर गड़बड़ी होती है.

समस्या का हल

इस सेक्शन में, कुछ गड़बड़ियों और उन्हें ठीक करने के तरीके के बारे में बताया गया है.

HWAddressSanitizer, पते के बारे में ज़्यादा जानकारी नहीं दे सकता

कभी-कभी, HWASan में मेमोरी के पिछले ऐलोकेशन की जानकारी के लिए जगह खत्म हो सकती है. ऐसे में, रिपोर्ट में तुरंत मेमोरी ऐक्सेस करने के लिए सिर्फ़ एक स्टैक ट्रेस होता है. इसके बाद, एक नोट दिखता है:

HWAddressSanitizer can not describe address in more detail.

कुछ मामलों में, टेस्ट को कई बार चलाकर इस समस्या को हल किया जा सकता है. दूसरा विकल्प यह है कि आप HWASan के इतिहास का साइज़ बढ़ाएं. ऐसा करने के लिए, build/soong/cc/sanitize.go (hwasanGlobalOptions खोजें) में जाकर, दुनिया भर में या अपने प्रोसेस एनवायरमेंट में जाकर (मौजूदा सेटिंग देखने के लिए adb shell echo $HWASAN_OPTIONS आज़माएं) ऐसा किया जा सकता है.

यह गड़बड़ी तब भी हो सकती है, जब ऐक्सेस की गई मेमोरी को मैप न किया गया हो या उसे एलोकेट करने वाला एलिमेंट, HWASan के बारे में न जानता हो. इस मामले में, क्रैश हेडर में मौजूद mem टैग आम तौर पर 00 होता है. अगर आपके पास पूरे टॉम्बस्टोन का ऐक्सेस है, तो मेमोरी मैप के डंप से यह पता लगाने में मदद मिल सकती है कि पता किस मैपिंग (अगर कोई है) से जुड़ा है.

एक ही थ्रेड में नेस्ट की गई गड़बड़ी

इसका मतलब है कि HWASan क्रैश-रिपोर्ट जनरेट करते समय कोई गड़बड़ी हुई. आम तौर पर, ऐसा HWASan रनटाइम में मौजूद गड़बड़ी की वजह से होता है. बग की शिकायत करें. साथ ही, अगर हो सके, तो समस्या को दोहराने का तरीका बताएं.