Android NDK hỗ trợ HWAddress Sanitizer, còn được gọi là HWASan, kể từ NDK r21 và Android 10 (API cấp 29). HWASan chỉ có trên các thiết bị Arm 64-bit.
HWASan là một công cụ phát hiện lỗi bộ nhớ tương tự như ASan. So với phiên bản ASan cũ, HWASan có:
- Mức hao tổn CPU tương tự (~2x)
- Mức hao tổn kích thước mã tương tự (40 – 50%)
- Mức hao tổn RAM thấp hơn nhiều (10% – 35%)
HWASan phát hiện cùng một nhóm lỗi như ASan:
- Chặn tràn (overflow) hoặc chặn trống (underflow) cho ngăn xếp (stack) và bộ nhớ khối xếp (heap)
- Sử dụng bộ nhớ khối xếp sau khi giải phóng
- Sử dụng ngăn xếp bên ngoài phạm vi
- Giải phóng hai lần hoặc giải phóng bộ nhớ chưa được cấp phát trước đó
Ngoài ra, HWASan cũng phát hiện:
- Sử dụng ngăn xếp sau khi trả về
Ứng dụng mẫu
Ứng dụng mẫu cho biết cách định cấu hình biến thể bản dựng cho hwasan.
Tạo
Để tạo mã gốc (JNI) của ứng dụng bằng HWAddress Sanitizer, hãy làm như sau:
ndk-build
Trong tệp 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
Trong tệp build.gradle
của mô-đun:
android {
defaultConfig {
externalNativeBuild {
cmake {
# Can also use system or none as ANDROID_STL, but not c++_static.
arguments "-DANDROID_STL=c++_shared"
}
}
}
}
Đối với mỗi mục tiêu trong CMakeLists.txt:
target_compile_options(${TARGET} PUBLIC -fsanitize=hwaddress -fno-omit-frame-pointer)
target_link_options(${TARGET} PUBLIC -fsanitize=hwaddress)
Với NDK 27 trở lên, bạn cũng có thể sử dụng nội dung sau trong build.gradle
và không cần thay đổi CMakeLists.txt:
android {
defaultConfig {
externalNativeBuild {
cmake {
arguments "-DANDROID_SANITIZE=hwaddress"
}
}
}
}
Thao tác này sẽ không hoạt động khi sử dụng ANDROID_USE_LEGACY_TOOLCHAIN_FILE=false
.
Android 14 trở lên: thêm wrap.sh
Nếu đang chạy Android 14 trở lên, bạn có thể dùng tập lệnh wrap.sh để chạy ứng dụng có thể gỡ lỗi của mình trên mọi thiết bị chạy Android. Bạn có thể bỏ qua bước này nếu chọn làm theo các bước trong Hướng dẫn thiết lập.
Làm theo hướng dẫn đóng gói tập lệnh wrap.sh để thêm tập lệnh wrap.sh sau đây cho arm64-v8a
.
#!/system/bin/sh
LD_HWASAN=1 exec "$@"
Chạy
Nếu bạn đang chạy trên phiên bản Android cũ hơn 14 hoặc chưa thêm tập lệnh wrap.sh, hãy làm theo Hướng dẫn thiết lập trước khi chạy ứng dụng.
Chạy ứng dụng như bình thường. Khi phát hiện lỗi bộ nhớ, một ứng dụng sẽ gặp sự cố với SIGABRT và đưa ra (print) một thông báo chi tiết tới logcat. Bạn có thể tìm thấy bản sao của thông báo này ở một tệp trong /data/tombstones
và bản sao sẽ có dạng như sau:
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)
Theo sau thông báo có thể là thông tin gỡ lỗi bổ sung, bao gồm danh sách các luồng trực tiếp trong ứng dụng, thẻ phân bổ bộ nhớ lân cận và giá trị đăng ký CPU.
Hãy xem bài viết Tìm hiểu báo cáo HWASan để biết thêm thông tin về các thông báo lỗi HWASan.
Tạo tệp thực thi dòng lệnh
Bạn có thể tạo và chạy các tệp thực thi được đo lường bằng HWASan trên Android 14 trở lên. Bạn có thể sử dụng cấu hình tương tự như mô tả trong phần Tạo cho ndk-build hoặc CMake cho các tệp thực thi. Đẩy các tệp thực thi vào một thiết bị chạy Android 14 trở lên và chạy như bình thường bằng shell.
Nếu bạn đang sử dụng libc++, hãy đảm bảo bạn đang sử dụng STL dùng chung và đẩy STL đó vào thiết bị, đồng thời đặt LD_LIBRARY_PATH
thành thư mục chứa STL đó khi chạy tệp nhị phân.
Nếu bạn không sử dụng Gradle, hãy xem tài liệu NDK để tìm hiểu cách tạo bản dựng từ dòng lệnh bằng CMake và ndk-build.
Android 13 trở xuống: Thiết lập
Nếu thiết bị của bạn chạy Android 14 trở lên, bạn có thể bỏ qua bước này và làm theo hướng dẫn sử dụng wrap.sh trong phần Tạo. Bạn cũng có thể chọn làm theo phần này và bỏ qua hướng dẫn sử dụng wrap.sh.
Trước phiên bản Android 14, các ứng dụng HWASan cần có bản dựng HWASan của Android để chạy. Bạn có thể truyền nhanh hình ảnh HWASan tạo sẵn sang các thiết bị Pixel được hỗ trợ. Các bản dựng có trên ci.android.com. Tại đây, bạn có thể nhấp vào hình vuông của đúng bản dựng mà bạn muốn lấy đường liên kết Bản dựng Flash. Để thực hiện thao tác này, bạn cần biết tên mã dành cho điện thoại của bạn.
Truy cập thẳng vào flash.android.com có thể dễ dàng hơn vì tại đó, quy trình bắt đầu từ việc phát hiện thiết bị của bạn và chỉ hiển thị các bản dựng mà bạn có thể sử dụng. Các hình ảnh sau minh hoạ quy trình thiết lập trong công cụ này.
Bật chế độ nhà phát triển trên thiết bị của bạn và kết nối với máy tính bằng cáp USB. Nhấp vào Add new device (Thêm thiết bị mới), chọn thiết bị của bạn trong hộp thoại rồi nhấp vào Connect (Kết nối).
Sau khi thiết bị được kết nối, hãy nhấp vào thiết bị đó để định cấu hình bản dựng.
Trong hộp Select a build ID (Chọn mã bản dựng), hãy chọn nhánh aosp-master-with-phones-throttled
để tự động chọn đúng hình ảnh cho thiết bị bạn đã kết nối.
Nhấp vào Install (Cài đặt) để truyền nhanh thiết bị.
Bạn có thể xem thêm thông tin chi tiết về cách thiết lập cần thiết trong tài liệu về Android Flash Tool. Ngoài ra, bạn có thể xem tài liệu về AOSP (Dự án nguồn mở Android) để biết hướng dẫn tạo hình ảnh HWASan từ nguồn.