เมื่อแก้ไขข้อบกพร่องและสร้างโปรไฟล์แอปด้วยโค้ดแบบเนทีฟ การใช้โค้ดประเภทนี้มักจะมีประโยชน์ เครื่องมือแก้ไขข้อบกพร่องที่ต้องเปิดใช้เมื่อเริ่มต้นกระบวนการ ซึ่งจำเป็นต้องดำเนินการต่อไปนี้ คุณเรียกใช้แอปด้วยกระบวนการใหม่ๆ แทนที่จะโคลนจากไซโกต ตัวอย่างเช่น
- การติดตามการเรียกของระบบด้วย strace
- ค้นหาข้อบกพร่องด้านหน่วยความจำด้วย แก้ไขข้อบกพร่องของ Malloc หรือ เครื่องมือล้างที่อยู่ (ASan)
- การทำโปรไฟล์ด้วย Simpleperf
ใช้สคริปต์ Wrap Shell
การใช้ wrap.sh
นั้นง่ายนิดเดียว:
- คอมไพล์ APK ที่กำหนดเองซึ่งแก้ไขข้อบกพร่องได้ซึ่งบรรจุสิ่งต่อไปนี้
- สคริปต์ Shell ชื่อ
wrap.sh
โปรดดู สร้างสคริปต์ Wrap Shell และ ดูรายละเอียดเพิ่มเติมได้ที่ Package wrap.sh - เครื่องมือพิเศษที่สคริปต์ Shell ต้องใช้ (เช่น ไบนารี
strace
ของคุณเอง)
- สคริปต์ Shell ชื่อ
- ติดตั้ง APK ที่แก้ไขข้อบกพร่องได้ในอุปกรณ์
- เปิดแอป
สร้างสคริปต์ Wrap Shell
เมื่อคุณเปิดตัว APK ที่แก้ไขข้อบกพร่องได้ซึ่งมี wrap.sh
ระบบจะเรียกใช้
สคริปต์และส่งคำสั่งเพื่อเริ่มแอปเป็นอาร์กิวเมนต์ สคริปต์คือ
มีหน้าที่เริ่มต้นแอป แต่สามารถทำให้สภาพแวดล้อมหรืออาร์กิวเมนต์ใดๆ
การเปลี่ยนแปลง สคริปต์ควรเป็นไปตาม
ไวยากรณ์ MirBSD Korn shell (mksh)
ข้อมูลโค้ดต่อไปนี้แสดงวิธีเขียนไฟล์ wrap.sh
แบบง่ายที่
เปิดแอป:
#!/system/bin/sh exec "$@"
การแก้ไขข้อบกพร่องของ Malloc
หากต้องการใช้งาน
แก้ไขข้อบกพร่องของ Malloc
ผ่าน wrap.sh
คุณจะใส่บรรทัดต่อไปนี้:
#!/system/bin/sh LIBC_DEBUG_MALLOC_OPTIONS=backtrace logwrapper "$@"
อาซาน
เราได้แสดงตัวอย่างวิธีดำเนินการนี้สำหรับ ASan ใน เอกสารประกอบของ ASan
แพ็กเกจ wrap.sh
APK ของคุณจะต้องแก้ไขข้อบกพร่องได้ เพื่อใช้ประโยชน์จาก wrap.sh
โปรดตรวจสอบว่า
android:debuggable="true"
มีการกำหนดค่าที่ต้องการใน
<application>
ในไฟล์ Manifest ของ Android หรือหากคุณกำลังใช้ Android Studio ที่
คุณได้กำหนดค่าบิลด์การแก้ไขข้อบกพร่องใน
build.gradle
จำเป็นต้องตั้งค่า useLegacyPackaging
ด้วย
ไปยัง true
ในไฟล์ build.gradle
ของแอป ในกรณีส่วนใหญ่ ตัวเลือกนี้จะตั้งค่า
เป็น 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/
เท่านั้น ดังนั้นหาก
คุณเป็นผู้ใช้ Android Studio คุณจะต้องวางไฟล์ wrap.sh
ใน
src/main/resources/lib/*
ไดเรกทอรีแทน เพื่อให้มีการรวมเป็นแพ็กเกจ
อย่างถูกต้อง
โปรดทราบว่า resources/lib/x86
จะแสดงใน UI เป็น
lib.x86
แต่จริงๆ แล้วควรเป็นไดเรกทอรีย่อย:
แก้ไขข้อบกพร่องเมื่อใช้ wrap.sh
หากคุณต้องการแนบโปรแกรมแก้ไขข้อบกพร่องเมื่อใช้ wrap.sh
สคริปต์ของ Shell จะ
ต้องเปิดใช้การแก้ไขข้อบกพร่องด้วยตนเอง ซึ่งจะแตกต่างกันไปตามแต่ละรุ่น
ตัวอย่างนี้แสดงวิธีการเพิ่มตัวเลือกที่เหมาะสมสำหรับการเผยแพร่ทั้งหมดที่
สนับสนุน 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