כלי לחיטוי של HWAddress

‏Android NDK תומך ב-HWAddress Sanitizer, שנקרא גם HWASan, החל מגרסה NDK r21 ו-Android 10 (רמת API 29). HWASan זמין רק במכשירי Arm עם 64 ביט.

HWASan הוא כלי לזיהוי שגיאות זיכרון, בדומה ל-ASan. בהשוואה ל-ASan הקלאסי, ב-HWAsan יש:

  • עלות ריבית מקבילה ל-CPU (כ-2x)
  • יתרת קוד דומה (40-50%)
  • יתרת זיכרון RAM קטנה בהרבה (10% עד 35%)

HWASan מזהה את אותה קבוצת באגים כמו ASan:

  • זליגה או מחסור ב-buffer של סטאק ושל אשכול
  • שימוש בערימה (heap) אחרי 'free'
  • שימוש ב-Stack מחוץ להיקף
  • Double free או wild free

בנוסף, HWASan מזהה גם:

  • שימוש ב-stack לאחר החזרה

אפליקציה לדוגמה

אפליקציה לדוגמה שמראה איך להגדיר גרסת build עבור hwasan.

Build

כדי ליצור את הקוד המקורי (JNI) של האפליקציה באמצעות HWAddress Sanitizer, מבצעים את הפעולות הבאות:

ndk-build

בקובץ Application.mk:

APP_STL := c++_shared # Or system, or none, but not c++_static.
APP_CFLAGS := -fsanitize=hwaddress -fno-omit-frame-pointer
APP_LDFLAGS := -fsanitize=hwaddress

CMake

בקובץ build.gradle של המודול:

android {
    defaultConfig {
        externalNativeBuild {
            cmake {
                # Can also use system or none as ANDROID_STL, but not c++_static.
                arguments "-DANDROID_STL=c++_shared"
            }
        }
    }
}

לכל יעד ב-CMakeLists.txt:

target_compile_options(${TARGET} PUBLIC -fsanitize=hwaddress -fno-omit-frame-pointer)
target_link_options(${TARGET} PUBLIC -fsanitize=hwaddress)

ב-NDK 27 ואילך, אפשר גם להשתמש בקוד הבא ב-build.gradle ולא צריך לשנות את CMakeLists.txt:

android {
    defaultConfig {
        externalNativeBuild {
            cmake {
                arguments "-DANDROID_SANITIZE=hwaddress"
            }
        }
    }
}

הפעולה הזו לא תפעל אם משתמשים ב-ANDROID_USE_LEGACY_TOOLCHAIN_FILE=false.

Android מגרסה 14 ואילך: מוסיפים את wrap.sh

אם אתם משתמשים ב-Android מגרסה 14 ואילך, תוכלו להשתמש בסקריפט wrap.sh כדי להריץ את האפליקציה שניתנת לניפוי באגים בכל מכשיר עם Android. אם בחרתם לפעול לפי השלבים שמפורטים בהוראות ההגדרה, תוכלו לדלג על השלב הזה.

פועלים לפי ההוראות לאריזת סקריפט wrap.sh כדי להוסיף את הסקריפט הבא של wrap.sh עבור arm64-v8a.

#!/system/bin/sh
LD_HWASAN=1 exec "$@"

הרצה

אם אתם משתמשים בגרסה ישנה יותר של Android, או אם לא הוספתם סקריפט wrap.sh, עליכם לפעול לפי הוראות ההגדרה לפני שמפעילים את האפליקציה.

מפעילים את האפליקציה כרגיל. כשזוהתה שגיאת זיכרון, האפליקציה קורסה עם SIGABRT ומדפיסה הודעה מפורטת ב-logcat. עותק של ההודעה נמצא בקובץ ב-/data/tombstones ונראה כך:

ERROR: HWAddressSanitizer: tag-mismatch on address 0x0042a0826510 at pc 0x007b24d90a0c
WRITE of size 1 at 0x0042a0826510 tags: 32/3d (ptr/mem) in thread T0
    #0 0x7b24d90a08  (/data/app/com.example.hellohwasan-eRpO2UhYylZaW0P_E0z7vA==/lib/arm64/libnative-lib.so+0x2a08)
    #1 0x7b8f1e4ccc  (/apex/com.android.art/lib64/libart.so+0x198ccc)
    #2 0x7b8f1db364  (/apex/com.android.art/lib64/libart.so+0x18f364)
    #3 0x7b8f2ad8d4  (/apex/com.android.art/lib64/libart.so+0x2618d4)

0x0042a0826510 is located 0 bytes to the right of 16-byte region [0x0042a0826500,0x0042a0826510)
allocated here:
    #0 0x7b92a322bc  (/apex/com.android.runtime/lib64/bionic/libclang_rt.hwasan-aarch64-android.so+0x212bc)
    #1 0x7b24d909e0  (/data/app/com.example.hellohwasan-eRpO2UhYylZaW0P_E0z7vA==/lib/arm64/libnative-lib.so+0x29e0)
    #2 0x7b8f1e4ccc  (/apex/com.android.art/lib64/libart.so+0x198ccc)

יכול להיות שלאחר ההודעה יופיע מידע נוסף על ניפוי הבאגים, כולל רשימת השרשור הפעילים באפליקציה, תגים של הקצאות זיכרון בקרבת מקום וערכים של מרשם המעבד (CPU).

מידע נוסף על הודעות השגיאה של HWASan זמין במאמר הסבר על דוחות HWASan.

פיתוח קובצי הפעלה לשורת הפקודה

אפשר ליצור ולהריץ קובצי הפעלה עם HWASan ב-Android מגרסה 14 ואילך. אפשר להשתמש באותה הגדרה שמתוארת בקטע Build עבור ndk-build או CMake לקובצי ההפעלה. מעבירים את קובצי ההפעלה למכשיר עם Android מגרסה 14 ואילך ומפעילים אותם כרגיל באמצעות המעטפת.

אם אתם משתמשים ב-libc++, חשוב לוודא שאתם משתמשים ב-STL המשותף, לדחוף אותו למכשיר ולהגדיר את LD_LIBRARY_PATH לספרייה שמכילה אותו כשמריצים את הקובץ הבינארי.

אם אתם לא משתמשים ב-Gradle, תוכלו לעיין במסמכי התיעוד של NDK כדי ללמוד איך לבצע פיתוח משורת הפקודה באמצעות CMake ו-ndk-build.

Android 13 וגרסאות קודמות: הגדרה

אם במכשיר שלכם פועלת מערכת Android מגרסה 14 ואילך, תוכלו לדלג על השלב הזה ולפעול לפי ההוראות לשימוש ב-wrap.sh בקטע Build. אפשר גם לפעול לפי הקטע הזה ולדלג על ההוראות לשימוש ב-wrap.sh.

לפני Android 14, אפליקציות HWASan צריכות גרסה של Android עם ה-build של HWASan כדי לפעול. אפשר להבהיל תמונות HWASan מוכנות מראש למכשירי Pixel נתמכים. הגרסאות הזמינות בכתובת ci.android.com, שם אפשר ללחוץ על הריבוע של הגרסה המדויקת שרוצים כדי לקבל קישור ל-Flash Build. לשם כך, צריך לדעת את הכינוי של הטלפון.

איך מבצעים אימייל של build של מכשיר

יכול להיות שיהיה קל יותר לעבור ישירות אל flash.android.com, כי שם התהליך מתחיל בזיהוי המכשיר, ומוצגות רק גרסאות build שאפשר להשתמש בהן. בתמונות הבאות מוצג תהליך ההגדרה בכלי הזה.

מפעילים את מצב הפיתוח במכשיר ומחברים אותו למחשב באמצעות כבל USB. לוחצים על הוספת מכשיר חדש, בוחרים את המכשיר בתיבת הדו-שיח ולוחצים על חיבור.

איתור מכשיר לעדכון בוחרים את המכשיר שאליו רוצים להתחבר.

אחרי שמחברים את המכשיר, לוחצים עליו כדי להגדיר את הגרסה היציבה. בתיבה Select a build ID, בוחרים את ההסתעפות aosp-master-with-phones-throttled כדי לבחור באופן אוטומטי את התמונה המתאימה למכשיר המחובר.

בוחרים את המכשיר שרוצים לעדכן. אישור אפשרויות ה-Flash והפעלת ה-Flash במכשיר

לוחצים על Install (התקנה) כדי להריץ את ה-Flash במכשיר.

פרטים נוספים על ההגדרה הנדרשת מופיעים במסמכי התיעוד של Android Flash Tool. לחלופין, אפשר לעיין במסמכי העזרה של AOSP כדי לקבל הוראות ליצירת קובץ אימג' של HWASan מהמקור.