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 ดังนี้
- Stack และ Heap Buffer Overflow หรือ Underflow
- การใช้ฮีปหลังจากปล่อย
- การใช้สแต็กนอกขอบเขต
- ฟรี 2 เท่าหรือฟรีแบบไม่จำกัด
นอกจากนี้ 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 ขึ้นไป แล้วเรียกใช้ตามปกติโดยใช้เชลล์
หากคุณใช้ libc++ โปรดตรวจสอบว่าคุณใช้ STL ที่แชร์และพุชไปยัง
อุปกรณ์ แล้วตั้งค่า LD_LIBRARY_PATH
เป็นไดเรกทอรีที่มี STL นั้นเมื่อ
เรียกใช้ไบนารี
หากไม่ได้ใช้ Gradle โปรดดูเอกสารประกอบ NDK เพื่อดูวิธีสร้างจากบรรทัดคำสั่งด้วย CMake และ ndk-build
Android 13 หรือเวอร์ชันก่อนหน้า: การตั้งค่า
หากอุปกรณ์ใช้ Android 14 ขึ้นไป ให้ข้ามขั้นตอนนี้และทำตามวิธีการใช้ wrap.sh ในส่วนสร้าง นอกจากนี้ คุณยังเลือกทำตามส่วนนี้และข้ามวิธีการใช้ wrap.sh ได้ด้วย
ก่อน Android 14 แอปพลิเคชัน HWASan ต้องใช้บิลด์ HWASan ของ Android เพื่อเรียกใช้ คุณสามารถแฟลชอิมเมจ HWASan ที่สร้างไว้ล่วงหน้าไปยังอุปกรณ์ Pixel ที่รองรับ บิลด์พร้อมใช้งานที่ ci.android.com ซึ่งคุณสามารถคลิกสี่เหลี่ยมสำหรับบิลด์ที่ต้องการเพื่อรับลิงก์ Flash Build โดยคุณต้องทราบชื่อรหัสของโทรศัพท์
คุณอาจไปที่ flash.android.com โดยตรงได้ง่ายกว่า เนื่องจากที่นั่น โฟลว์จะเริ่มต้นด้วยการตรวจหาอุปกรณ์ของคุณ และจะแสดงเฉพาะบิลด์ที่คุณใช้ได้ รูปภาพต่อไปนี้แสดงขั้นตอนการตั้งค่าในเครื่องมือนี้
เปิดใช้โหมดนักพัฒนาแอปในอุปกรณ์และเชื่อมต่อกับคอมพิวเตอร์โดยใช้ สาย USB คลิกเพิ่มอุปกรณ์ใหม่ เลือกอุปกรณ์จากกล่องโต้ตอบ แล้วคลิกเชื่อมต่อ
หลังจากเชื่อมต่ออุปกรณ์แล้ว ให้คลิกอุปกรณ์เพื่อกำหนดค่าบิลด์
ในช่องเลือกรหัสบิลด์ ให้เลือกaosp-master-with-phones-throttled
สาขาเพื่อเลือกอิมเมจที่ถูกต้องสำหรับอุปกรณ์ที่คุณเชื่อมต่อโดยอัตโนมัติ
คลิกติดตั้งเพื่อแฟลชอุปกรณ์
ดูรายละเอียดเพิ่มเติมเกี่ยวกับการตั้งค่าที่จำเป็นได้ในเอกสารประกอบของ Android Flash Tool หรือจะดูวิธีการสร้างอิมเมจ HWASan จากแหล่งที่มาได้ในเอกสารประกอบของ AOSP