כשהכלי HWASan מזהה באג בזיכרון, התהליך מסתיים עם abort(),
ודוח מודפס ל-stderr ול-logcat. בדומה לכל הקריסות המקוריות ב-Android, השגיאות של 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 הם שגיאות של אי-התאמה בין תגים, כלומר גישה לזיכרון שבה תג המצביע לא תואם לתג הזיכרון המתאים. יכולות להיות לכך כמה סיבות:
- גישה מחוץ לתחום במחסנית או בערימה
- שגיאת שימוש אחרי שחרור בזיכרון ערימה (heap)
- שגיאת שימוש אחרי חזרה במחסנית
קטעים
הנה הסבר על כל אחד מהקטעים בדוח HWASan.
שגיאת גישה
הדוח מכיל מידע על הגישה הבעייתית לזיכרון, כולל:
- סוג הגישה (
READלעומתWRITE) - גודל הגישה (כמה בייטים נעשה ניסיון לגשת אליהם)
- מספר השרשור של הגישה
- תגי זיכרון וסמני מיקום (לניפוי באגים מתקדם)
גישה לדוח קריסות
דוח הקריסות של גישת הזיכרון הבעייתית. כדי להוסיף סמלים, אפשר לעיין במאמר בנושא הוספת סמלים.
הסיבה
הסיבה האפשרית לגישה הלא תקינה. אם יש כמה מועמדים, הם מוצגים בסדר יורד לפי הסבירות. מופיע לפני המידע המפורט על הגורם האפשרי. HWASan יכול לאבחן את הסיבות הבאות:
- שימוש אחרי תקופת הניסיון
- אי התאמה של תג המחסנית, שיכולה להיות שימוש במחסנית אחרי החזרה, שימוש במחסנית אחרי היקף או חריגה מגבולות
- גלישה מעבר לגבולות של מאגר נתונים זמני בזיכרון הערימה
- תפריט אפשרויות נוספות גלובלי
מידע על הזיכרון
תיאור של מה ש-HWASan יודע על הזיכרון שאליו מתבצעת גישה, והוא יכול להיות שונה בהתאם לסוג הבאג:
| סוג הבאג | הסיבה | פורמט הדוח |
|---|---|---|
| אי התאמה בין תגים | שימוש אחרי תקופת הניסיון | משתמשים בפורמט הדוח הזה:<address> is located N bytes inside of M-byte region [<start>, <end>) freed by thread T0 here: |
| גלישה מעבר לגבולות של מאגר נתונים זמני בזיכרון הערימה | הערה: יכול להיות שזה גם underflow.<address> is located N bytes to the right of M-byte region [<start>, <end>) allocated here: |
|
| חוסר התאמה בתג Stack | בדוחות על מחסנית הקריאות לא מבחינים בין גלישה או חריגה לבין באגים של שימוש אחרי החזרה. בנוסף, כדי למצוא את הקצאת הזיכרון במחסנית שגורמת לשגיאה, צריך לבצע שלב של סימבוליזציה אופליין. מידע על דוחות של ערימת טכנולוגיות | |
| משלוח חינם לא חוקי | שימוש אחרי תקופת הניסיון | באג של שחרור כפול של זיכרון. אם זה קורה כשמפסיקים את התהליך, יכול להיות שזו הפרה של כללי ה-ODR.
<address> is located N bytes inside of M-byte region [<start>, <end>) freed by thread T0 here: |
| לא ניתן לתאר את הכתובת | או שגיאה של שחרור זיכרון לא מוקצה (free of memory that hadn't been allocated before), או שגיאה של שחרור כפול אחרי שהזיכרון המוקצה הוצא ממאגר הזיכרון הפנוי של HWASan. | |
| 0x... הוא זיכרון צל של HWAsan | שגיאת free לא צפויה, כי האפליקציה ניסתה לפנות זיכרון שהוא פנימי ל-HWASan. |
Deallocation stack trace
Stack trace of where the memory was deallocated. הצגה רק עבור באגים מסוג use-after-free או invalid-free. אפשר לעיין במאמר בנושא הוספת סמלים.
דוח קריסות של הקצאות
דוח קריסות של המיקום שבו הוקצה הזיכרון. אפשר לעיין במאמר בנושא הוספת סמלים.
מידע מתקדם על תוצאות ניפוי הבאגים
דוח HWASan כולל גם מידע על תוצאות ניפוי הבאגים מתקדם, כולל (לפי הסדר):
- רשימת השרשורים בתהליך
- רשימת השרשורים בתהליך
- הערך של תגי הזיכרון ליד הזיכרון שבו התגלתה התקלה
- הדאמפ של הרגיסטרים בנקודת הגישה לזיכרון
פלט של תיוג זיכרון
אפשר להשתמש ב-tag memory dump כדי לחפש הקצאות זיכרון סמוכות עם אותו תג כמו תג המצביע. התגים האלה יכולים להצביע על גישה מחוץ לתחום עם היסט גדול. תג אחד מתאים ל-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 .. .. .. .. .. .. .. .. .. .. .. .. .. ..
שימו לב להרצה של 6 × 16 = 96 בייט של תגי ad בצד ימין שתואמים לתג המצביע.
אם גודל ההקצאה לא מתחלק ב-16, השארית של הגודל מאוחסנת כתג זיכרון והתג מאוחסן כתג גרנולרי קצר. בדוגמה הקודמת, מיד אחרי תג ההקצאה המודגש ad, יש הקצאה של 84 בייט לתג 5c (5 × 16 + 4 = 84).
תג זיכרון עם הערך אפס (לדוגמה, tags: ad/00 (ptr/mem)) מציין באג של שימוש במחסנית אחרי החזרה.
רישום קובץ Dump
ה-register dump בדוחות של HWASan תואם להוראה שביצעה את הגישה הלא תקינה לזיכרון. אחרי ה-dump הזה מופיע עוד dump של הרישום ממטפל האותות הרגיל של Android. אפשר להתעלם מהדאמפ השני, כי הוא נוצר כש-HWASan קרא ל-abort() והוא לא רלוונטי לבאג.
סימבוליזציה
כדי לקבל שמות של פונקציות ומספרי שורות במעקב מחסנית (stack trace) (ולקבל שמות של משתנים לשימוש בבאגים מסוג use-after-scope), צריך לבצע שלב סימבוליזציה אופליין.
הגדרה בפעם הראשונה: התקנת llvm-symbolizer
כדי להוסיף סמלים, צריך להתקין את llvm-symbolizer במערכת ולוודא שאפשר לגשת אליו מ-$PATH. ב-Debian, אפשר להתקין אותו באמצעות sudo apt install llvm.
השגת קובצי סמלים
לצורך יצירת סמלים, אנחנו דורשים קבצים בינאריים לא מוסרים שמכילים סמלים. המיקום שלהם תלוי בסוג הגרסה:
- בגרסאות build מקומיות, קובצי הסמלים נמצאים ב-
out/target/product/<product>/symbols/. - במקרה של גרסאות build של AOSP (לדוגמה, גרסאות שנצרבו מ-Android Flash Tool), גרסאות ה-build נמצאות ב-Android CI. בArtifacts של ה-build, יש קובץ
${PRODUCT}-symbols-${BUILDID}.zip. - במקרה של גרסאות build פנימיות מהארגון שלכם, כדאי לעיין במסמכי התיעוד של הארגון כדי לקבל עזרה בהשגת קובצי סמלים.
סימון
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
חלק מהבאגים מסוג use-after-free שמדווחים על ידי HWASan יכולים להצביע על הפרה של One Definition Rule (ODR). הפרה של כלל ODR מתרחשת כשאותו משתנה מוגדר כמה פעמים באותה תוכנית. המשמעות היא גם שהמשתנה נהרס כמה פעמים, מה שיכול להוביל לשגיאה use-after-free.
אחרי הסימבוליזציה, הפרות של ODR מציגות שגיאת שימוש אחרי שחרור זיכרון עם __cxa_finalize, גם במחסנית הגישה הלא חוקית וגם במחסנית freed here. המחסנית previously
allocated 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 שמופיע בכותרת של הקראש הוא בדרך כלל 00. אם יש לכם גישה לנתוני ה-tombstone המלאים, כדאי לעיין ב-dump של מפות הזיכרון כדי לגלות לאיזה מיפוי (אם בכלל) הכתובת שייכת.
באג מוטמע באותו שרשור
המשמעות היא שהיה באג במהלך יצירת דוח הקריסה של HWASan. בדרך כלל זה קורה בגלל באג בזמן הריצה של HWASan. מדווחים על באג ומספקים הוראות לשחזור הבעיה, אם אפשר.