هنگام اشکال زدایی و نمایه سازی برنامه ها با کد بومی، اغلب استفاده از ابزارهای اشکال زدایی که باید در هنگام راه اندازی فرآیند فعال شوند مفید است. این مستلزم آن است که برنامه خود را به جای شبیه سازی از زیگوت در یک فرآیند تازه اجرا کنید. مثالها عبارتند از:
- تماس های سیستم ردیابی با strace .
- یافتن اشکالات حافظه با اشکال زدایی malloc یا Address Sanitizer (ASan) .
- پروفایل با Simpleperf .
از اسکریپت wrap shell استفاده کنید
استفاده از wrap.sh
آسان است:
- یک APK قابل اشکال زدایی سفارشی کامپایل کنید که موارد زیر را بسته بندی می کند:
- یک اسکریپت پوسته به نام
wrap.sh
برای جزئیات بیشتر به ایجاد اسکریپت wrap shell و Package wrap.sh مراجعه کنید. - هر ابزار اضافی مورد نیاز اسکریپت پوسته شما (مانند باینری
strace
خود).
- یک اسکریپت پوسته به نام
- APK قابل اشکال زدایی را روی دستگاه نصب کنید.
- برنامه را راه اندازی کنید.
اسکریپت wrap shell را ایجاد کنید
هنگامی که یک APK قابل اشکال زدایی را راه اندازی می کنید که حاوی wrap.sh
است، سیستم اسکریپت را اجرا می کند و دستور شروع برنامه را به عنوان آرگومان ارسال می کند. اسکریپت مسئول راه اندازی برنامه است، اما می تواند هر محیط یا آرگومان را تغییر دهد. اسکریپت باید از دستور MirBSD Korn shell (mksh) پیروی کند.
قطعه زیر نحوه نوشتن یک فایل wrap.sh
ساده را نشان می دهد که به تازگی برنامه را راه اندازی می کند:
#!/system/bin/sh exec "$@"
اشکال زدایی Malloc
برای استفاده از malloc debug از طریق wrap.sh
، باید خط زیر را وارد کنید:
#!/system/bin/sh LIBC_DEBUG_MALLOC_OPTIONS=backtrace logwrapper "$@"
ASan
نمونه ای از نحوه انجام این کار برای ASan در مستندات ASan وجود دارد.
بسته بندی wrap.sh
برای استفاده از wrap.sh
، APK شما باید قابل اشکالزدایی باشد. مطمئن شوید که تنظیم android:debuggable="true"
در عنصر <application>
در مانیفست اندروید شما پیکربندی شده باشد، یا اگر از Android Studio استفاده می کنید، یک ساختار اشکال زدایی را در فایل build.gradle
پیکربندی کرده اید.
همچنین لازم است useLegacyPackaging
در فایل build.gradle
برنامه خود روی true
تنظیم کنید. در بیشتر موارد، این گزینه به طور پیش فرض روی false
تنظیم شده است، بنابراین ممکن است بخواهید برای جلوگیری از هرگونه غافلگیری، این گزینه را به صراحت روی true
تنظیم کنید.
شما باید اسکریپت wrap.sh
با کتابخانه های بومی برنامه بسته بندی کنید. اگر برنامه شما حاوی کتابخانه های بومی نیست، دایرکتوری lib را به صورت دستی به فهرست پروژه خود اضافه کنید. برای هر معماری که برنامه شما از آن پشتیبانی میکند، باید یک کپی از اسکریپت wrap shell در آن فهرست کتابخانه اصلی ارائه دهید.
مثال زیر طرح بندی فایل را برای پشتیبانی از معماری های ARMv8 و x86-64 نشان می دهد:
# App Directory |- AndroidManifest.xml |- … |- lib |- arm64-v8a |- ... |- wrap.sh |- x86_64 |- ... |- wrap.sh
Android Studio فقط فایل های .so
را از دایرکتوری های lib/
بسته بندی می کند، بنابراین اگر کاربر اندروید استودیو هستید، باید فایل های wrap.sh
خود را در دایرکتوری های src/main/resources/lib/*
قرار دهید تا آنها به درستی بسته بندی می شوند.
توجه داشته باشید که resources/lib/x86
در رابط کاربری به صورت lib.x86
نمایش داده می شود، اما در واقع باید یک زیر شاخه باشد:
هنگام استفاده از wrap.sh اشکال زدایی کنید
اگر میخواهید هنگام استفاده از wrap.sh
یک اشکالزدا را ضمیمه کنید، اسکریپت پوسته شما باید اشکالزدایی را به صورت دستی فعال کند. نحوه انجام این کار بین نسخهها متفاوت است، بنابراین این مثال نشان میدهد که چگونه میتوان گزینههای مناسب را برای همه نسخههایی که از wrap.sh
پشتیبانی میکنند اضافه کرد:
#!/system/bin/sh
cmd=$1
shift
os_version=$(getprop ro.build.version.sdk)
if [ "$os_version" -eq "27" ]; then
cmd="$cmd -Xrunjdwp:transport=dt_android_adb,suspend=n,server=y -Xcompiler-option --debuggable $@"
elif [ "$os_version" -eq "28" ]; then
cmd="$cmd -XjdwpProvider:adbconnection -XjdwpOptions:suspend=n,server=y -Xcompiler-option --debuggable $@"
else
cmd="$cmd -XjdwpProvider:adbconnection -XjdwpOptions:suspend=n,server=y $@"
fi
exec $cmd