المعقّم للعنوان

يتوافق Android NDK مع تطبيق Address Sanitizer (المعروف أيضًا باسم ASan) الذي يبدأ مع المستوى 27 من واجهة برمجة التطبيقات (Android O MR 1)

ASan هي أداة سريعة تستند إلى برنامج التجميع لرصد أخطاء الذاكرة في الرموز البرمجية الأصلية. يكتشف ASan ما يلي:

  • تجاوز/تدفق المخزن المؤقت للتكديس وأجزاء من الذاكرة
  • استخدام لقطات لأجزاء من الذاكرة بعد الفترة المجانية
  • استخدام التكديس خارج النطاق
  • موقف سيارات مزدوج/بدون تكلفة

يبلغ الزيادة في وحدة المعالجة المركزية في ASan حوالي الضعف، ويتراوح حجم الرمز البرمجي بين 50% و2x، وحجم الذاكرة كبيرًا (يعتمد على أنماط التخصيص، ولكن بالترتيب 2x).

نموذج التطبيق

نموذج تطبيق كيفية ضبط صيغة إصدار لنظام asan.

إنشاء

لإنشاء الرمز الأصلي (JNI) لتطبيقك باستخدام مصحِّح العنوان، عليك تنفيذ التالي:

لعبة ndk-build

في Application.mk:

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

لكل وحدة في Android.mk:

LOCAL_ARM_MODE := arm

إنشاء فيديوهات Shorts

في Build.gradle:

android {
    defaultConfig {
        externalNativeBuild {
            cmake {
                // Can also use system or none as ANDROID_STL.
                arguments "-DANDROID_ARM_MODE=arm", "-DANDROID_STL=c++_shared"
            }
        }
    }
}

لكل هدف في CMakeLists.txt:

target_compile_options(${TARGET} PUBLIC -fsanitize=address -fno-omit-frame-pointer)
set_target_properties(${TARGET} PROPERTIES LINK_FLAGS -fsanitize=address)

تشغيل

بدءًا من Android O MR1 (المستوى 27 من واجهة برمجة التطبيقات)، يمكن أن يوفر التطبيق التفاف النص البرمجي Shell الذي يمكن أن يلتف حول عملية التطبيق أو يحل محلها. هذا يسمح تطبيق يمكن تصحيح الأخطاء به لتخصيص بدء تشغيل التطبيق، وهو ما يمكّن باستخدام ASan على أجهزة الإنتاج.

  1. إضافة android:debuggable إلى بيان التطبيق
  2. ضبط useLegacyPackaging إلى true في ملف build.gradle لتطبيقك. الاطّلاع على دليل التفاف النصّ البرمجي لواجهة الأوامر لمزيد من المعلومات.
  3. يمكنك إضافة مكتبة وقت تشغيل ASan إلى jniLibs في وحدة تطبيقك.
  4. يمكنك إضافة wrap.sh ملف يتضمّن المحتوى التالي إلى كل دليل في دليل src/main/resources/lib.

    #!/system/bin/sh
    HERE="$(cd "$(dirname "$0")" && pwd)"
    export ASAN_OPTIONS=log_to_syslog=false,allow_user_segv_handler=1
    ASAN_LIB=$(ls $HERE/libclang_rt.asan-*-android.so)
    if [ -f "$HERE/libc++_shared.so" ]; then
        # Workaround for https://github.com/android-ndk/ndk/issues/988.
        export LD_PRELOAD="$ASAN_LIB $HERE/libc++_shared.so"
    else
        export LD_PRELOAD="$ASAN_LIB"
    fi
    "$@"
    

على افتراض أنّ اسم وحدة تطبيقات مشروعك هو "app"، سيكون الدليل النهائي هو ما يلي:

<project root>
└── app
    └── src
        └── main
            ├── jniLibs
            │   ├── arm64-v8a
            │   │   └── libclang_rt.asan-aarch64-android.so
            │   ├── armeabi-v7a
            │   │   └── libclang_rt.asan-arm-android.so
            │   ├── x86
            │   │   └── libclang_rt.asan-i686-android.so
            │   └── x86_64
            │       └── libclang_rt.asan-x86_64-android.so
            └── resources
                └── lib
                    ├── arm64-v8a
                    │   └── wrap.sh
                    ├── armeabi-v7a
                    │   └── wrap.sh
                    ├── x86
                    │   └── wrap.sh
                    └── x86_64
                        └── wrap.sh

تتبعات بنية تخزين العناصر

على معقّم العنوان إلغاء الحزمة في كل malloc/realloc/free. الاتصال. هناك خياران هنا:

  1. "سرعة" أداة إلغاء التمرير بالإطار المستند إلى المؤشر. وهذا ما يتم استخدامه من خلال اتباع التعليمات في قسم المبنى.

  2. "بطيئة" إلغاء ربط CFI. في هذا الوضع، يستخدم ASan _Unwind_Backtrace. أُنشأها جون هنتر، الذي كان متخصصًا تتطلب فقط -funwind-tables، والتي تكون مفعّلة عادةً بشكل تلقائي.

وتكون أداة التراجع السريع هي الخيار التلقائي لـ mailoc/realloc/free. تُعد عملية التفكيك البطيئة هو الإعداد الافتراضي لعمليات تتبع تسلسل استدعاء الدوال البرمجية الفادحة. يمكن تفعيل ميزة إلغاء التمرير البطيء للجميع عمليات تتبُّع تسلسل استدعاء الدوال البرمجية من خلال إضافة fast_unwind_on_malloc=0 إلى المتغيّر ASAN_OPTIONS في wrap.sh.