گزارش های HWASan را درک کنید

وقتی ابزار 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: '

[...]

[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:
عدم تطابق برچسب پشته گزارش‌های پشته تفاوتی بین سرریز یا سرریز زیرین و اشکالات استفاده پس از بازگشت قائل نمی‌شوند. علاوه بر این، برای یافتن تخصیص پشته‌ای که منبع خطا است، یک مرحله نمادگذاری آفلاین مورد نیاز است. به بخش «درک گزارش‌های پشته» مراجعه کنید.
رایگان نامعتبر بعد از رایگان شدن استفاده کنید یک اشکال آزادسازی مضاعف. اگر این اتفاق هنگام خاموش شدن فرآیند رخ دهد، می‌تواند نشان‌دهنده نقض 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 همچنین شامل برخی اطلاعات اشکال‌زدایی پیشرفته است، از جمله (به ترتیب):

  1. فهرست رشته‌های در حال انجام
  2. فهرست رشته‌های در حال انجام
  3. مقدار برچسب‌های حافظه نزدیک حافظه‌ی معیوب
  4. روگرفت (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 است. در صورت امکان، یک اشکال ثبت کنید و دستورالعمل‌هایی برای نحوه‌ی ایجاد مجدد مشکل ارائه دهید.