ตัวล้าง HWAddress

Android NDK รองรับ HWAddress Sanitizer หรือที่เรียกว่า HWASan ตั้งแต่ NDK r21 และ Android 10 (ระดับ API 29) เป็นต้นไป HWASan ใช้ได้เฉพาะในอุปกรณ์ Arm แบบ 64 บิต

HWASan เป็นเครื่องมือตรวจหาข้อผิดพลาดด้านหน่วยความจำที่คล้ายกับ ASan เมื่อเทียบกับ ASan แบบคลาสสิกแล้ว HWASan มีลักษณะดังนี้

  • ค่าใช้จ่าย CPU ที่คล้ายกัน (~2 เท่า)
  • ค่าใช้จ่ายขนาดโค้ดที่คล้ายกัน (40–50%)
  • ค่าใช้จ่าย RAM ที่น้อยกว่ามาก (10–35%)

HWASan ตรวจพบข้อบกพร่องชุดเดียวกับ ASan ดังนี้

  • บัฟเฟอร์ล้นหรือบัฟเฟอร์ขาดในสแต็กและฮีป
  • การใช้ฮีปหลังจากช่วงใช้ฟรี
  • การใช้สแต็กนอกขอบเขต
  • การใช้ฟังก์ชัน free() กับหน่วยความจำที่ถูกใช้ฟังก์ชัน free() ไปแล้ว หรือการใช้ฟังก์ชัน free() กับหน่วยความจำที่ไม่ได้ถูกจัดสรร

นอกจากนี้ HWASan ยังตรวจพบสิ่งต่อไปนี้ด้วย

  • การใช้สแต็กหลังจากส่งคืน

แอปตัวอย่าง

แอปตัวอย่างแสดงวิธีกำหนดค่าตัวแปรบิลด์สำหรับ hwasan

บิลด์

หากต้องการสร้างโค้ดเนทีฟ (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 (Gradle Groovy)

ในไฟล์ 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

CMake (Gradle Kotlin)

ในไฟล์ 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 เวอร์ชันเก่ากว่า 14 หรือไม่ได้เพิ่มสคริปต์ 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 ขึ้นไป คุณสามารถใช้การกำหนดค่าเดียวกับที่อธิบายไว้ในส่วนสร้างสำหรับ ndk-build หรือ CMake สำหรับไฟล์ปฏิบัติการ พุชไฟล์ปฏิบัติการไปยังอุปกรณ์ที่ใช้ Android 14 หรือใหม่กว่า แล้วดำเนินการตามปกติโดยใช้ Shell

หากใช้ libc++ โปรดตรวจสอบว่าคุณใช้ STL ที่แชร์ แล้วส่งไปยังอุปกรณ์และตั้งค่า LD_LIBRARY_PATH เป็นไดเรกทอรีที่มี STL เมื่อเรียกใช้ไบนารี

หากไม่ได้ใช้ Gradle โปรดดูเอกสารประกอบของ NDK เพื่อดูวิธีสร้างจาก บรรทัดคำสั่งด้วย CMake และ ndk-build

Android 13 ลงไป: การตั้งค่า

หากอุปกรณ์ใช้ Android 14 ขึ้นไป คุณสามารถข้ามขั้นตอนนี้และทำตาม วิธีการใช้ wrap.sh ในส่วน สร้าง ได้ หรือจะเลือกทำตามส่วนนี้และข้ามวิธีการใช้ wrap.sh ก็ได้

ก่อน Android 14 แอปพลิเคชัน HWASan ต้องใช้ Android เวอร์ชัน HWASan เพื่อเรียกใช้ คุณสามารถแฟลชอิมเมจ HWASan ที่สร้างไว้ล่วงหน้าลงในอุปกรณ์ Pixel ที่รองรับ บิลด์พร้อมใช้งานใน ci.android.com ซึ่งคุณสามารถคลิกสี่เหลี่ยมสำหรับ บิลด์ที่ต้องการเพื่อรับลิงก์แฟลชบิลด์ การดำเนินการนี้กำหนดให้คุณต้องทราบ ชื่อรหัสของโทรศัพท์

แฟลชบิลด์ของอุปกรณ์

การไปที่ flash.android.com โดยตรงอาจง่ายกว่า เนื่องจาก ขั้นตอนที่นั่นจะ เริ่มต้น ด้วยการตรวจหาอุปกรณ์ของคุณและแสดงเฉพาะบิลด์ที่คุณใช้ได้ รูปภาพต่อไปนี้แสดงขั้นตอนการตั้งค่าในเครื่องมือนี้

เปิดใช้โหมดนักพัฒนาแอปในอุปกรณ์และเชื่อมต่อกับคอมพิวเตอร์โดยใช้สาย USB คลิกเพิ่มอุปกรณ์ใหม่ เลือกอุปกรณ์จากกล่องโต้ตอบ และ คลิกเชื่อมต่อ

ตรวจหาอุปกรณ์ที่จะแฟลช เลือกอุปกรณ์ที่จะเชื่อมต่อ

หลังจากเชื่อมต่ออุปกรณ์แล้ว ให้คลิกอุปกรณ์เพื่อกำหนดค่าบิลด์ ในช่องเลือกรหัสบิลด์ ให้เลือกสาขา aosp-master-with-phones-throttled เพื่อเลือกอิมเมจที่ถูกต้องสำหรับอุปกรณ์ที่คุณเชื่อมต่อโดยอัตโนมัติ

เลือกอุปกรณ์ที่จะแฟลช ยืนยันตัวเลือกการแฟลชและแฟลชอุปกรณ์

คลิกติดตั้ง เพื่อแฟลชอุปกรณ์

ดูรายละเอียดเพิ่มเติมเกี่ยวกับการตั้งค่าที่จำเป็นได้ใน เอกสารประกอบของ Android Flash Tool หรืออีกวิธีคือดู เอกสารประกอบของ AOSP เพื่อดูวิธีการสร้างอิมเมจ HWASan จากแหล่งที่มา