وقتی ابزار HWASan یک اشکال حافظه را تشخیص میدهد، فرآیند با abort() خاتمه مییابد و گزارشی در stderr و logcat چاپ میشود. مانند همه کرشهای بومی در اندروید، خطاهای HWASan در /data/tombstones قرار دارند.
گزارش نمونه
در مقایسه با کرشهای معمولی بومی، HWASan اطلاعات اضافی را در فیلد پیام لغو نزدیک بالای سنگ قبر حمل میکند. در اینجا یک نمونه کرش مبتنی بر پشته آورده شده است. برای اشکالات پشته، به یادداشت مربوط به بخشهای خاص پشته مراجعه کنید.
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 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: '==9569==ERROR: HWAddressSanitizer: tag-mismatch on address 0x00433ae20045 at pc 0x00623ae2a9cc READ of size 1 at 0x00433ae20045 tags: 5b/83 (ptr/mem) in thread T0 #0 0x7240450c68 (/system/lib64/vndk-sp-R/libcutils.so+0x8c68) #1 0x723dffd490 (/vendor/lib64/sensors.ssc.so+0x34490) #2 0x723e0126e0 (/vendor/lib64/sensors.ssc.so+0x496e0) [...] [0x00433ae20040,0x00433ae20060) is a small unallocated heap chunk; size: 32 offset: 5 Cause: use-after-free 0x00433ae20045 is located 5 bytes inside of 10-byte region [0x00433ae20040,0x00433ae2004a) freed by thread T0 here: #0 0x72404d1b18 (/system/lib64/libclang_rt.hwasan-aarch64-android.so+0x10b18) #1 0x723af23040 (/vendor/lib64/libgralloccore.so+0x5040) #2 0x723af23fa4 (/vendor/lib64/libgralloccore.so+0x5fa4) [...] previously allocated here: #0 0x72404ce554 (/system/lib64/libclang_rt.hwasan-aarch64-android.so+0xd554) #1 0x7240115654 (/apex/com.android.runtime/lib64/bionic/libc.so+0x43654) #2 0x7240450ac8 (/system/lib64/vndk-sp-R/libcutils.so+0x8ac8) [...] hwasan_dev_note_heap_rb_distance: 1 1023 hwasan_dev_note_num_matching_addrs: 0 hwasan_dev_note_num_matching_addrs_4b: 0 Thread: T0 0x006a00002000 stack: [0x007fc1064000,0x007fc1864000) sz: 8388608 tls: [0x00737702ffc0,0x007377033000) Memory tags around the buggy address (one tag corresponds to 16 bytes): 0x006f33ae1f80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae1f90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae1fa0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae1fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae1fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae1fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae1fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae1ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 =>0x006f33ae2000: 08 00 08 00 [83] 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae2010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae2020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae2030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae2040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae2050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae2060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae2070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae2080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 Tags for short granules around the buggy address (one tag corresponds to 16 bytes): 0x006f33ae1ff0: .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. =>0x006f33ae2000: 72 .. d0 .. [..] .. .. .. .. .. .. .. .. .. .. .. 0x006f33ae2010: .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. See https://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html#short-granules for a description of short granule tags Registers where the failure occurred (pc 0x00623ae2a9cc): x0 0000007fc18623ec x1 5b0000433ae20045 x2 0000000000000013 x3 ffffffffffffffff x4 ffffffffffffffff x5 0000007fc1861da3 x6 6f7420676e696f47 x7 45522061206f6420 x8 0000000000000000 x9 0200006b00000000 x10 00000007fc18623f x11 5b0000433ae20040 x12 6f64206f7420676e x13 0a44414552206120 x14 0000000000000010 x15 ffffffffffffffff x16 000000737169ac94 x17 0000000000000007 x18 0000007377bd8000 x19 0000007fc1862498 x20 0200006b00000000 x21 0000007fc18624a8 x22 0000000000000001 x23 0000000000000000 x24 0000000000000000 x25 0000000000000000 x26 0000000000000000 x27 0000000000000000 x28 0000000000000000 x29 0000007fc1862410 x30 000000623ae2a9d0 sp 0000007fc18623d0 SUMMARY: HWAddressSanitizer: tag-mismatch (/system/lib64/vndk-sp-R/libcutils.so+0x8c68) [ … 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: | |
| عدم تطابق برچسب پشته | گزارشهای پشته تفاوتی بین سرریز یا سرریز زیرین و اشکالات استفاده پس از بازگشت قائل نمیشوند. علاوه بر این، برای یافتن تخصیص پشتهای که منبع خطا است، یک مرحله نمادگذاری آفلاین مورد نیاز است. به بخش «درک گزارشهای پشته» مراجعه کنید. | |
| رایگان نامعتبر | بعد از رایگان شدن استفاده کنید | یک اشکال آزادسازی مضاعف. اگر این اتفاق هنگام خاموش شدن فرآیند رخ دهد، میتواند نشاندهنده نقض ODR باشد. <address> is located N bytes inside of M-byte region [<start>, <end>) freed by thread T0 here: |
| نمیتوانم آدرس را توصیف کنم | یا یک آزادسازی وحشی (آزادسازی حافظهای که قبلاً تخصیص داده نشده بود) یا یک آزادسازی مضاعف پس از اینکه حافظه تخصیص داده شده از بافر آزاد HWASan خارج شد. | |
| 0x... حافظه سایه HWAsan است | کاملاً آزاد شد، زیرا برنامه در تلاش بود حافظه داخلی HWASan را آزاد کند. |
ردیابی پشته Delocation
رد پشتهای از محل آزادسازی حافظه. فقط برای اشکالات استفاده پس از آزادسازی یا آزادسازی نامعتبر ارائه میشود. برای نمادگذاری به نمادگذاری مراجعه کنید.
ردیابی پشته تخصیص
رد پشته از جایی که حافظه اختصاص داده شده است. برای نمادگذاری به Symbolization مراجعه کنید.
اطلاعات اشکالزدایی پیشرفته
گزارش HWASan همچنین شامل برخی اطلاعات اشکالزدایی پیشرفته است، از جمله (به ترتیب):
- فهرست رشتههای در حال انجام
- فهرست رشتههای در حال انجام
- مقدار برچسبهای حافظه نزدیک حافظهی معیوب
- روگرفت (dump) از رجیسترها در نقطه دسترسی به حافظه
تخلیه برچسب حافظه
شما میتوانید از دستور تخلیه حافظه تگ برای جستجوی تخصیصهای حافظه مجاور با همان تگ اشارهگر استفاده کنید. این تگها میتوانند به یک دسترسی خارج از محدوده با یک آفست بزرگ اشاره کنند. یک تگ معادل ۱۶ بایت حافظه است؛ تگ اشارهگر ۸ بیت بالای آدرس است. دستور تخلیه حافظه تگ میتواند نکاتی را ارائه دهد، برای مثال، مورد زیر یک سرریز بافر در سمت راست است:
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 در سمت چپ که با تگ اشارهگر مطابقت دارند، توجه کنید.
اگر اندازه یک تخصیص مضربی از ۱۶ نباشد، باقیمانده اندازه به عنوان برچسب حافظه ذخیره میشود و آن برچسب به عنوان یک برچسب گرانول کوتاه ذخیره میشود. در مثال قبلی، درست بعد از تخصیص پررنگ شده با برچسب ad ، یک تخصیص ۵ × ۱۶ + ۴ = ۸۴ بایت از برچسب 5c داریم.
یک برچسب حافظه صفر (برای مثال، tags: ad/ 00 (ptr/mem) ) نشان دهنده یک اشکال استفاده از پشته پس از بازگشت است.
ثبت نام کنید
دامپ رجیستر در گزارشهای HWASan مربوط به دستورالعملی است که دسترسی نامعتبر به حافظه را انجام داده است. پس از این دامپ، یک دامپ رجیستر دیگر از کنترلکننده سیگنال معمولی اندروید میآید. دامپ دوم را نادیده بگیرید ، زیرا هنگام فراخوانی تابع abort() توسط HWASan گرفته شده و ربطی به این اشکال ندارد.
نمادسازی
برای دریافت نام توابع و شماره خطوط در ردیابیهای پشته (و دریافت نام متغیرها برای اشکالات استفاده پس از محدوده)، یک مرحله نمادگذاری آفلاین مورد نیاز است.
راهاندازی اولیه: نصب llvm-symbolizer
برای نمادگذاری، سیستم شما باید llvm-symbolizer نصب کرده و از طریق $PATH به آن دسترسی داشته باشد. در دبیان، میتوانید آن را با استفاده از sudo apt install llvm نصب کنید.
دریافت فایلهای نماد
برای نمادگذاری، به فایلهای باینری بدون مرزبندی حاوی نمادها نیاز داریم. محل قرارگیری آنها به نوع ساخت بستگی دارد:
- برای نسخههای محلی ، فایلهای نماد در مسیر
out/target/product/<product>/symbols/قرار دارند. - برای نسخههای AOSP (مثلاً نسخههایی که از Android Flash Tool فلش شدهاند)، نسخهها روی Android CI هستند. در Artifacts مربوط به نسخه، یک فایل
${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 این فریمها را به محتوای قابل فهم برای انسان در گزارش اشکال تبدیل نمیکند و به یک مرحله نمادگذاری اضافی نیاز دارد.
تخلفات ODR
برخی از اشکالات استفاده پس از آزادسازی که توسط HWASan گزارش شدهاند، میتوانند نشاندهنده نقض قانون یک تعریفی (ODR) باشند. نقض ODR زمانی اتفاق میافتد که یک متغیر چندین بار در یک برنامه تعریف شود. این همچنین به این معنی است که متغیر چندین بار تخریب میشود، که میتواند منجر به خطای استفاده پس از آزادسازی شود.
پس از نمادگذاری، تخلفات ODR خطای استفاده پس از آزادسازی با __cxa_finalize را هم در پشته دسترسی نامعتبر و هم در پشته here آزاد شده نشان میدهند. پشته here که قبلاً تخصیص داده شده است شامل __dl__ZN6soinfo17call_constructorsEv است و باید به مکانی در برنامه شما اشاره کند که متغیر را در پشته بالاتر تعریف میکند.
اگر از کتابخانههای ایستا استفاده شود، ODR میتواند نقض شود. اگر یک کتابخانه ایستا که یک متغیر سراسری C++ را تعریف میکند به چندین کتابخانه مشترک یا فایل اجرایی متصل باشد، ممکن است تعاریف متعددی از یک نماد در یک فضای آدرس وجود داشته باشد که باعث خطای ODR میشود.
عیبیابی
در این بخش به برخی از خطاها و نحوه رفع آنها اشاره شده است.
HWAddressSanitizer نمیتواند آدرس را با جزئیات بیشتری توصیف کند.
گاهی اوقات HWASan ممکن است برای اطلاعات مربوط به تخصیصهای حافظه گذشته، فضای کافی نداشته باشد. در این صورت، گزارش فقط شامل یک ردیابی پشته برای دسترسی فوری به حافظه است و به دنبال آن یک یادداشت قرار دارد:
HWAddressSanitizer can not describe address in more detail.
در برخی موارد، میتوانید این مشکل را با اجرای چندین بارهی تست حل کنید. گزینهی دیگر افزایش اندازهی تاریخچهی HWASan است. میتوانید این کار را به صورت سراسری در build/soong/cc/sanitize.go (به دنبال hwasanGlobalOptions بگردید) یا در محیط پردازش خود انجام دهید (برای مشاهدهی تنظیمات فعلی adb shell echo $HWASAN_OPTIONS امتحان کنید).
این خطا همچنین میتواند در صورتی رخ دهد که حافظهی مورد دسترسی نگاشت نشده باشد، یا توسط تخصیصدهندهای غیر از HWASan تخصیص داده شده باشد. در این حالت، برچسب mem ذکر شده در هدر crash معمولاً 00 است. اگر به سنگ قبر کامل دسترسی دارید، ممکن است مراجعه به dump نقشههای حافظه برای فهمیدن اینکه آدرس متعلق به کدام نگاشت (در صورت وجود) است، مفید باشد.
اشکال تو در تو در همان تاپیک
این به این معنی است که هنگام تولید گزارش خرابی HWASan مشکلی وجود داشته است. این معمولاً به دلیل وجود اشکال در زمان اجرای HWASan است. در صورت امکان، یک اشکال ثبت کنید و دستورالعملهایی برای نحوهی ایجاد مجدد مشکل ارائه دهید.