تتضمّن الأقسام التالية الأنواع الشائعة من الأعطال الأصلية، وتحليلًا لملف تفريغ ذاكرة
نموذجي للأعطال، ومناقشة حول ملفّات السجلّات. يتضمّن كل نوع من أنواع الأعطال مثالاً على debuggerd
مع تمييز الأدلة الرئيسية لمساعدتك في التمييز بين النوع المحدّد من الأعطال.
إلغاء
إنّ عمليات الإلغاء مثيرة للاهتمام لأنّها مقصودة. هناك العديد من
الطرق المختلفة للإيقاف (بما في ذلك استدعاء
abort(3)
،
أو عدم إكمال
assert(3)
،
أو استخدام أحد أنواع التسجيلات الخطيرة الخاصة بنظام التشغيل Android)، ولكن جميعها تتضمن
استدعاء abort
. تشير المكالمة إلى abort
إلى سلسلت الرسائل
التي تتصل بها باستخدام SIGABRT، لذا فإنّ الإطار الذي يعرض "إيقاف" في libc.so
بالإضافة إلى
SIGABRT هما ما يجب البحث عنه في إخراج debuggerd
للتعرّف على هذه الحالة.
قد يكون هناك سطر "رسالة إلغاء" صريح. يجب أيضًا الاطّلاع على logcat
output للاطّلاع على ما سجّلته سلسلة المحادثات هذه قبل إغلاقها عمدًا، لأنّ abort(3)
لا تقبل رسالة على عكس assert(3)
أو مرافق تسجيل
الخطأ الفادح على مستوى عالٍ.
تُدرج الإصدارات الحالية من Android طلب النظام
tgkill(2)
في النص، لذا تكون مجموعات استدعاء الدوالّ أسهل قراءة، مع طلب
abort(3) في أعلى الصفحة:
pid: 4637, tid: 4637, name: crasher >>> crasher <<< signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr -------- Abort message: 'some_file.c:123: some_function: assertion "false" failed' r0 00000000 r1 0000121d r2 00000006 r3 00000008 r4 0000121d r5 0000121d r6 ffb44a1c r7 0000010c r8 00000000 r9 00000000 r10 00000000 r11 00000000 ip ffb44c20 sp ffb44a08 lr eace2b0b pc eace2b16 backtrace: #00 pc 0001cb16 /system/lib/libc.so (abort+57) #01 pc 0001cd8f /system/lib/libc.so (__assert2+22) #02 pc 00001531 /system/bin/crasher (do_action+764) #03 pc 00002301 /system/bin/crasher (main+68) #04 pc 0008a809 /system/lib/libc.so (__libc_init+48) #05 pc 00001097 /system/bin/crasher (_start_main+38)
اتّبعت الإصدارات القديمة من Android مسارًا معقّدًا بين طلب التوقف الأصلي (الإطار 4 هنا) والإرسال الفعلي للإشارة (الإطار 0 هنا).
كان هذا صحيحًا بشكل خاص على معالجات ARM 32 بت، التي أضافت
__libc_android_abort
(الإطار 3 هنا) إلى تسلسل
raise
/pthread_kill
/tgkill
على الأنظمة الأساسية الأخرى:
pid: 1656, tid: 1656, name: crasher >>> crasher <<< signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr -------- Abort message: 'some_file.c:123: some_function: assertion "false" failed' r0 00000000 r1 00000678 r2 00000006 r3 f70b6dc8 r4 f70b6dd0 r5 f70b6d80 r6 00000002 r7 0000010c r8 ffffffed r9 00000000 sl 00000000 fp ff96ae1c ip 00000006 sp ff96ad18 lr f700ced5 pc f700dc98 cpsr 400b0010 backtrace: #00 pc 00042c98 /system/lib/libc.so (tgkill+12) #01 pc 00041ed1 /system/lib/libc.so (pthread_kill+32) #02 pc 0001bb87 /system/lib/libc.so (raise+10) #03 pc 00018cad /system/lib/libc.so (__libc_android_abort+34) #04 pc 000168e8 /system/lib/libc.so (abort+4) #05 pc 0001a78f /system/lib/libc.so (__libc_fatal+16) #06 pc 00018d35 /system/lib/libc.so (__assert2+20) #07 pc 00000f21 /system/xbin/crasher #08 pc 00016795 /system/lib/libc.so (__libc_init+44) #09 pc 00000abc /system/xbin/crasher
يمكنك إعادة إنشاء مثيل من هذا النوع من الأعطال باستخدام crasher
abort
.
إزالة الإشارة إلى المؤشر الفارغ
هذا هو نوع الأعطال الكلاسيكي في التطبيقات الأصلية، وعلى الرغم من أنّه مجرد حالة خاصة من نوع الانهيار التالي، إلا أنّه يستحق الذكر بشكل منفصل لأنّه عادةً ما يتطلب أقل قدر من التفكير.
في المثال أدناه، على الرغم من أنّ الدالة التي تؤدي إلى حدوث العُطل موجودة في libc.so
، يمكنك استنتاج أنّه تم استدعاء strlen(3)
باستخدام مؤشر فارغ، لأنّ دوال السلاسل تعمل فقط على مؤشرات
التي يتم منحها، ومن المفترض أن ينتقل هذا العُطل مباشرةً إلى libc.so
مؤلف الرمز البرمجي الذي يستدعي الدالة. في هذه الحالة، الإطار رقم 01 هو المتصل غير المرغوب فيه.
pid: 25326, tid: 25326, name: crasher >>> crasher <<< signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0 r0 00000000 r1 00000000 r2 00004c00 r3 00000000 r4 ab088071 r5 fff92b34 r6 00000002 r7 fff92b40 r8 00000000 r9 00000000 sl 00000000 fp fff92b2c ip ab08cfc4 sp fff92a08 lr ab087a93 pc efb78988 cpsr 600d0030 backtrace: #00 pc 00019988 /system/lib/libc.so (strlen+71) #01 pc 00001a8f /system/xbin/crasher (strlen_null+22) #02 pc 000017cd /system/xbin/crasher (do_action+948) #03 pc 000020d5 /system/xbin/crasher (main+100) #04 pc 000177a1 /system/lib/libc.so (__libc_init+48) #05 pc 000010e4 /system/xbin/crasher (_start+96)
يمكنك إعادة إنشاء مثيل من هذا النوع من الأعطال باستخدام crasher
strlen-NULL
.
إزالة الإشارة إلى المؤشر الفارغ في العنوان المنخفض
في كثير من الحالات، لن يكون عنوان الخطأ 0، بل سيكون رقمًا منخفضًا آخر. إنّ العناوين المكونة من رقمين أو
ثلاثة أرقام على وجه الخصوص شائعة جدًا، في حين أنّه من المؤكد تقريبًا أنّ العنوان المكوّن من ستة أرقام
ليس إشارة إلى عنصر غير محدد، لأنّ ذلك
سيتطلب إزاحة 1 ميغابايت. يحدث ذلك عادةً عندما يكون لديك رمز برمجي
يزيل إشارة مؤشر فارغ كما لو كان بنية صالحة. الدوالّ الشائعة هي
fprintf(3)
(أو أيّ دالة أخرى تأخذ FILE*) و
readdir(3)
،
لأنّ الرمز البرمجي غالبًا ما يتعذّر عليه التحقّق من نجاح استدعاء
fopen(3)
أو
opendir(3)
أولاً.
في ما يلي مثال على readdir
:
pid: 25405, tid: 25405, name: crasher >>> crasher <<< signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0xc r0 0000000c r1 00000000 r2 00000000 r3 3d5f0000 r4 00000000 r5 0000000c r6 00000002 r7 ff8618f0 r8 00000000 r9 00000000 sl 00000000 fp ff8618dc ip edaa6834 sp ff8617a8 lr eda34a1f pc eda618f6 cpsr 600d0030 backtrace: #00 pc 000478f6 /system/lib/libc.so (pthread_mutex_lock+1) #01 pc 0001aa1b /system/lib/libc.so (readdir+10) #02 pc 00001b35 /system/xbin/crasher (readdir_null+20) #03 pc 00001815 /system/xbin/crasher (do_action+976) #04 pc 000021e5 /system/xbin/crasher (main+100) #05 pc 000177a1 /system/lib/libc.so (__libc_init+48) #06 pc 00001110 /system/xbin/crasher (_start+96)
في ما يلي السبب المباشر للتعطُّل وهو أنّه
pthread_mutex_lock(3)
حاول الوصول إلى العنوان 0xc (الإطار 0). ولكن أول إجراء يقوم به الرمز البرمجي
pthread_mutex_lock
هو إلغاء الإشارة إلى عنصر state
من العنصر pthread_mutex_t*
الذي تم منحه. إذا اطّلعت على مصدر
، يمكنك ملاحظة أنّ العنصر يقع في الإزاحة 0 في البنية، ما يشير إلى
أنّه تم منح pthread_mutex_lock
المؤشر غير الصالح 0xc. من
الإطار 1، يمكنك الاطّلاع على أنّه تم منح هذا المؤشر من خلال readdir
،
الذي يستخرج حقل mutex_
من DIR*
الذي يتم
منحه. عند الاطّلاع على هذه البنية، يمكنك ملاحظة أنّ mutex_
يقع عند
الإزاحة sizeof(int) + sizeof(size_t) + sizeof(dirent*)
في
struct DIR
، والتي تبلغ على جهاز 32 بت 4 + 4 + 4 = 12 = 0xc، وبالتالي
عثرت على الخطأ: تم تمرير مؤشر فارغ إلى readdir
من قِبل
المُتصل. في هذه المرحلة، يمكنك لصق تسلسل استدعاء الدوال البرمجية في أداة تسلسل استدعاء الدوال البرمجية لمعرفة
مكان حدوث ذلك في logcat.
struct DIR { int fd_; size_t available_bytes_; dirent* next_; pthread_mutex_t mutex_; dirent buff_[15]; long current_pos_; };
في معظم الحالات، يمكنك تخطي هذا التحليل. عادةً ما يعني عنوان خطأ
منخفض بما يكفي أنّه يمكنك تخطّي أيّ إطارات libc.so
في ملف
التجميع والإشارة مباشرةً إلى الرمز البرمجي الذي يُجري عملية الاتصال. ولكن ليس دائمًا، وإليك كيفية
تقديم طلب مقنع.
يمكنك إعادة إنشاء حالات من هذا النوع من الأعطال باستخدام crasher
fprintf-NULL
أو crasher readdir-NULL
.
تعذُّر FORTIFY
تُعدّ أخطاء FORTIFY حالة خاصة من حالات الإيقاف التي تحدث عندما ترصد مكتبة C
مشكلة قد تؤدي إلى ثغرة أمنية. تم تعزيز العديد من وظائف مكتبة C، فهي تأخذ وسيطة إضافية تُعلمها
بحجم المخزن المؤقت الفعلي وتتحقّق في وقت التشغيل مما إذا كانت العملية
التي تحاول تنفيذها مناسبة. في ما يلي مثال يحاول فيه الرمز
read(fd, buf, 32)
في مخزن مؤقت لا يتجاوز حجمه 10 بايت
في الواقع...
pid: 25579, tid: 25579, name: crasher >>> crasher <<< signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr -------- Abort message: 'FORTIFY: read: prevented 32-byte write into 10-byte buffer' r0 00000000 r1 000063eb r2 00000006 r3 00000008 r4 ff96f350 r5 000063eb r6 000063eb r7 0000010c r8 00000000 r9 00000000 sl 00000000 fp ff96f49c ip 00000000 sp ff96f340 lr ee83ece3 pc ee86ef0c cpsr 000d0010 backtrace: #00 pc 00049f0c /system/lib/libc.so (tgkill+12) #01 pc 00019cdf /system/lib/libc.so (abort+50) #02 pc 0001e197 /system/lib/libc.so (__fortify_fatal+30) #03 pc 0001baf9 /system/lib/libc.so (__read_chk+48) #04 pc 0000165b /system/xbin/crasher (do_action+534) #05 pc 000021e5 /system/xbin/crasher (main+100) #06 pc 000177a1 /system/lib/libc.so (__libc_init+48) #07 pc 00001110 /system/xbin/crasher (_start+96)
يمكنك إعادة إنشاء مثيل من هذا النوع من الأعطال باستخدام crasher
fortify
.
تم رصد تلف في الذاكرة المحفوظة في الذاكرة العلوية بواسطة -fstack-protector
يُدرج خيار -fstack-protector
في المُجمِّع عمليات تحقّق في الدوال التي تستخدم ملفّات تخزين مؤقت على الذاكرة لتجنّب تجاوز سعة ملف التخزين المؤقت. يتم تفعيل هذا الخيار
تلقائيًا لرمز النظام الأساسي ولكن ليس للتطبيقات. عند تفعيل
هذا الخيار، يضيف المُجمِّع تعليمات إلى
مقدّمة الدوال لكتابة قيمة عشوائية بعد العنصر المحلي الأخير في الحزمة مباشرةً،
وإلى خاتمة الدالة لقراءتها مرة أخرى والتحقّق من عدم تغييرها. إذا
تغيّرت هذه القيمة، تم استبدالها بقيمة أخرى بسبب تجاوز مساحة التخزين المؤقت، لذا تُطلِق المقاطعة
دالة __stack_chk_fail
لتسجيل رسالة وإيقاف التنفيذ.
pid: 26717, tid: 26717, name: crasher >>> crasher <<< signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr -------- Abort message: 'stack corruption detected' r0 00000000 r1 0000685d r2 00000006 r3 00000008 r4 ffd516d8 r5 0000685d r6 0000685d r7 0000010c r8 00000000 r9 00000000 sl 00000000 fp ffd518bc ip 00000000 sp ffd516c8 lr ee63ece3 pc ee66ef0c cpsr 000e0010 backtrace: #00 pc 00049f0c /system/lib/libc.so (tgkill+12) #01 pc 00019cdf /system/lib/libc.so (abort+50) #02 pc 0001e07d /system/lib/libc.so (__libc_fatal+24) #03 pc 0004863f /system/lib/libc.so (__stack_chk_fail+6) #04 pc 000013ed /system/xbin/crasher (smash_stack+76) #05 pc 00001591 /system/xbin/crasher (do_action+280) #06 pc 00002219 /system/xbin/crasher (main+100) #07 pc 000177a1 /system/lib/libc.so (__libc_init+48) #08 pc 00001144 /system/xbin/crasher (_start+96)
يمكنك تمييز هذا النوع من أنواع الإنهاء الأخرى من خلال ظهور
__stack_chk_fail
في تتبع الرجوع ورسالة الإنهاء المحدّدة.
يمكنك إعادة إنشاء مثيل من هذا النوع من الأعطال باستخدام crasher
smash-stack
.
Seccomp SIGSYS من طلب نظام غير مسموح به
يفرض نظام seccomp (وتحديدًا seccomp-bpf) قيودًا على الوصول إلى طلبات النظام. لمزيد من
المعلومات عن seccomp لمطوّري الأنظمة الأساسية، يُرجى الاطّلاع على مشاركة المدونة
فلتر Seccomp
في Android O. سيتلقّى مؤشر التسلسل الذي يستدعي طلب نظام محظورًا
إشارة SIGSYS بالرمز SYS_SECCOMP. سيتم
عرض رقم طلب النظام في سطر السبب، بالإضافة إلى البنية. من المهم الإشارة إلى أنّه
تختلف أرقام طلبات النظام بين المعماريات. على سبيل المثال، طلب النظام
readlinkat(2)
هو رقم 305 على x86 ولكن 267 على x86-64.
يختلف رقم الاتصال مرة أخرى على كلٍّ من arm وarm64. بما أنّ أرقام طلبات النظام
تختلف بين المعماريات، من الأسهل عادةً استخدام تتبع تسلسل استدعاء الدوال البرمجية
لمعرفة طلب النظام الذي تم رفضه بدلاً من البحث عن رقم
طلب النظام في العناوين.
pid: 11046, tid: 11046, name: crasher >>> crasher <<< signal 31 (SIGSYS), code 1 (SYS_SECCOMP), fault addr -------- Cause: seccomp prevented call to disallowed arm system call 99999 r0 cfda0444 r1 00000014 r2 40000000 r3 00000000 r4 00000000 r5 00000000 r6 00000000 r7 0001869f r8 00000000 r9 00000000 sl 00000000 fp fffefa58 ip fffef898 sp fffef888 lr 00401997 pc f74f3658 cpsr 600f0010 backtrace: #00 pc 00019658 /system/lib/libc.so (syscall+32) #01 pc 00001993 /system/bin/crasher (do_action+1474) #02 pc 00002699 /system/bin/crasher (main+68) #03 pc 0007c60d /system/lib/libc.so (__libc_init+48) #04 pc 000011b0 /system/bin/crasher (_start_main+72)
يمكنك تمييز طلبات النظام غير المسموح بها عن الأعطال الأخرى من خلال ظهور الرمز
SYS_SECCOMP
في سطر الإشارة والوصف في سطر السبب.
يمكنك إعادة إنشاء مثيل من هذا النوع من الأعطال باستخدام crasher
seccomp
.
انتهاك ذاكرة التنفيذ فقط (Android 10 فقط)
بالنسبة إلى arm64 في Android 10 فقط، تم ربط الأجزاء القابلة للتنفيذ من ملفَي برمجة ثنائية ومكتبتَين في ذاكرة للتنفيذ فقط (غير قابلة للقراءة) كأسلوب لتعزيز الأمان ضد هجمات إعادة استخدام الرموز البرمجية. تداخلت هذه الحلول بشكلٍ سيئ مع الحلول الأخرى، وتمّت إزالتها لاحقًا.
يؤدي جعل الرمز غير قابل للقراءة إلى عمليات قراءة مقصودة وغير مقصودة في أجزاء الذاكرة التي تم وضع علامة عليها قائلةً
تنفيذ فقط لرمي SIGSEGV
بالرمز SEGV_ACCERR
. قد يحدث ذلك
نتيجة خطأ أو ثغرة أمنية أو بيانات مختلطة مع الرمز البرمجي (مثل مجموعة ثوابت)
أو فحص الذاكرة بشكل مقصود.
يفترض المُجمِّع عدم اختلاط الرموز البرمجية بالبيانات، ولكن يمكن أن تنشأ مشاكل من تعليمات التجميع المكتوبة يدويًا. في كثير من الحالات، يمكن حلّ هذه المشاكل ببساطة عن طريق نقل الثوابت إلى قسم .data
.
إذا كان فحص الرمز البرمجي ضروريًا تمامًا في أقسام التعليمات البرمجية القابلة للتنفيذ، يجب أولاً استدعاء mprotect(2)
لوضع علامة على الرمز البرمجي بأنّه قابل للقراءة، ثم مرة أخرى لوضع علامة عليه بأنّه غير قابل للقراءة بعد اكتمال عملية.
pid: 2938, tid: 2940, name: crasher64 >>> crasher64 <<< signal 11 (SIGSEGV), code 2 (SEGV_ACCERR), fault addr 0x5f2ced24a8 Cause: execute-only (no-read) memory access error; likely due to data in .text. x0 0000000000000000 x1 0000005f2cecf21f x2 0000000000000078 x3 0000000000000053 x4 0000000000000074 x5 8000000000000000 x6 ff71646772607162 x7 00000020dcf0d16c x8 0000005f2ced24a8 x9 000000781251c55e x10 0000000000000000 x11 0000000000000000 x12 0000000000000014 x13 ffffffffffffffff x14 0000000000000002 x15 ffffffffffffffff x16 0000005f2ced52f0 x17 00000078125c0ed8 x18 0000007810e8e000 x19 00000078119fbd50 x20 00000078125d6020 x21 00000078119fbd50 x22 00000b7a00000b7a x23 00000078119fbdd8 x24 00000078119fbd50 x25 00000078119fbd50 x26 00000078119fc018 x27 00000078128ea020 x28 00000078119fc020 x29 00000078119fbcb0 sp 00000078119fba40 lr 0000005f2ced1b94 pc 0000005f2ced1ba4 backtrace: #00 pc 0000000000003ba4 /system/bin/crasher64 (do_action+2348) #01 pc 0000000000003234 /system/bin/crasher64 (thread_callback+44) #02 pc 00000000000e2044 /apex/com.android.runtime/lib64/bionic/libc.so (__pthread_start(void*)+36) #03 pc 0000000000083de0 /apex/com.android.runtime/lib64/bionic/libc.so (__start_thread+64)
يمكنك التمييز بين انتهاكات الذاكرة للتنفيذ فقط والأعطال الأخرى من خلال سطر السبب.
يمكنك إعادة إنشاء مثيل من هذا النوع من الأعطال باستخدام crasher xom
.
خطأ تم رصده بواسطة fdsan
تساعد أداة fdsan لتنقية أوصاف الملفات في Android في رصد الأخطاء الشائعة في أوصاف الملفات، مثل الاستخدام بعد الإغلاق والإغلاق المزدوج. راجِع مستندات fdsan للحصول على مزيد من التفاصيل حول تصحيح أخطاء هذه الفئة من الأخطاء (وتجنُّبها).
pid: 32315, tid: 32315, name: crasher64 >>> crasher64 <<< signal 35 (), code -1 (SI_QUEUE), fault addr -------- Abort message: 'attempted to close file descriptor 3, expected to be unowned, actually owned by FILE* 0x7d8e413018' x0 0000000000000000 x1 0000000000007e3b x2 0000000000000023 x3 0000007fe7300bb0 x4 3033313465386437 x5 3033313465386437 x6 3033313465386437 x7 3831303331346538 x8 00000000000000f0 x9 0000000000000000 x10 0000000000000059 x11 0000000000000034 x12 0000007d8ebc3a49 x13 0000007fe730077a x14 0000007fe730077a x15 0000000000000000 x16 0000007d8ec9a7b8 x17 0000007d8ec779f0 x18 0000007d8f29c000 x19 0000000000007e3b x20 0000000000007e3b x21 0000007d8f023020 x22 0000007d8f3b58dc x23 0000000000000001 x24 0000007fe73009a0 x25 0000007fe73008e0 x26 0000007fe7300ca0 x27 0000000000000000 x28 0000000000000000 x29 0000007fe7300c90 sp 0000007fe7300860 lr 0000007d8ec2f22c pc 0000007d8ec2f250 backtrace: #00 pc 0000000000088250 /bionic/lib64/libc.so (fdsan_error(char const*, ...)+384) #01 pc 0000000000088060 /bionic/lib64/libc.so (android_fdsan_close_with_tag+632) #02 pc 00000000000887e8 /bionic/lib64/libc.so (close+16) #03 pc 000000000000379c /system/bin/crasher64 (do_action+1316) #04 pc 00000000000049c8 /system/bin/crasher64 (main+96) #05 pc 000000000008021c /bionic/lib64/libc.so (_start_main)
يمكنك تمييز هذا النوع من أنواع الإنهاء الأخرى من خلال ظهور
fdsan_error
في تتبع الرجوع ورسالة الإنهاء المحدّدة.
يمكنك إعادة إنشاء مثيل من هذا النوع من الأعطال باستخدام
crasher fdsan_file
أو crasher fdsan_dir
.
التحقيق في ملفات الذاكرة عند تعطّل البرنامج
إذا لم يكن لديك عطل محدّد تُجري تحقيقًا بشأنه الآن، يتضمّن
مصدر المنصة أداة لاختبار debuggerd
تُسمى
أداة تعطيل. إذا كنت تستخدم mm
في system/core/debuggerd/
،
ستحصل على كل من crasher
وcrasher64
في مسارك (سمة
crasher64
تتيح لك اختبار الأعطال في التطبيقات المتوافقة مع الإصدار 64 بت). يمكن أن يتعطّل Crasher بعدد كبير
من الطرق المثيرة للاهتمام استنادًا إلى مَعلمات سطر الأوامر التي تقدّمها.
استخدِم crasher --help
للاطّلاع على الخيارات المتاحة حاليًا.
لتعريفك على الأجزاء المختلفة في ملف "تجميع بيانات الأعطال"، لنطّلِع على مثال على ملف "تجميع بيانات الأعطال":
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** Build fingerprint: 'Android/aosp_flounder/flounder:5.1.51/AOSP/enh08201009:eng/test-keys' Revision: '0' ABI: 'arm' pid: 1656, tid: 1656, name: crasher >>> crasher <<< signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr -------- Abort message: 'some_file.c:123: some_function: assertion "false" failed' r0 00000000 r1 00000678 r2 00000006 r3 f70b6dc8 r4 f70b6dd0 r5 f70b6d80 r6 00000002 r7 0000010c r8 ffffffed r9 00000000 sl 00000000 fp ff96ae1c ip 00000006 sp ff96ad18 lr f700ced5 pc f700dc98 cpsr 400b0010 backtrace: #00 pc 00042c98 /system/lib/libc.so (tgkill+12) #01 pc 00041ed1 /system/lib/libc.so (pthread_kill+32) #02 pc 0001bb87 /system/lib/libc.so (raise+10) #03 pc 00018cad /system/lib/libc.so (__libc_android_abort+34) #04 pc 000168e8 /system/lib/libc.so (abort+4) #05 pc 0001a78f /system/lib/libc.so (__libc_fatal+16) #06 pc 00018d35 /system/lib/libc.so (__assert2+20) #07 pc 00000f21 /system/xbin/crasher #08 pc 00016795 /system/lib/libc.so (__libc_init+44) #09 pc 00000abc /system/xbin/crasher Tombstone written to: /data/tombstones/tombstone_06 *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
يكون صف العلامات النجمية مع المسافات مفيدًا إذا كنت تبحث في سجلّ عن الأعطال الأصلية. نادرًا ما تظهر السلسلة "*** ***" في السجلات بخلاف بداية الأعطال الأصلية.
Build fingerprint: 'Android/aosp_flounder/flounder:5.1.51/AOSP/enh08201009:eng/test-keys'
تتيح لك بصمة الجهاز تحديد الإصدار الذي حدث فيه العُطل بدقة.
وهذا الإجراء هو نفسه الإجراء المُتّبع في نظام ro.build.fingerprint
.
Revision: '0'
تشير المراجعة إلى الجهاز وليس إلى البرنامج. لا يتم استخدام هذا الخيار عادةً، ولكن يمكن أن يكون مفيدًا لمساعدتك في تجاهل الأخطاء التي يُعرف أنّه
تسبّبها الأجهزة المعطّلة تلقائيًا. وهذا الإجراء هو نفسه الإجراء المُتّبع في ملف تعريف النظام
ro.revision
.
ABI: 'arm'
تكون ABI إحدى واجهات التطبيق الثنائية التالية: arm أو arm64 أو x86 أو x86-64. يكون ذلك مفيدًا في الغالب
لنص stack
البرمجي المذكور أعلاه، حتى يعرف
سلسلة الأدوات التي يجب استخدامها.
pid: 1656, tid: 1656, name: crasher >>> crasher <<<
يحدِّد هذا السطر سلسلة المحادثات المحدّدة في العملية التي تعطّلت. في هذه الحالة، كانت سلسلة التعليمات الرئيسية للعملية، لذا يتطابق رقم تعريف العملية مع رقم تعريف سلسلة التعليمات. الاسم الأول هو اسم الخيط، والاسم المحاط بـ >>> و <<< هو اسم العملية. بالنسبة إلى التطبيق، يكون اسم العملية عادةً هو اسم الحزمة المؤهَّلة بالكامل (مثل com.facebook.katana)، وهو مفيد عند الإبلاغ عن الأخطاء أو محاولة العثور على التطبيق في Google Play. يمكن أن يكون رقمَا تعريف العملية tid وpid مفيدَين أيضًا في العثور على سطور السجلّ ذات الصلة التي تسبق العُطل.
signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
يُعلمك هذا السطر بالإشارة التي تم تلقيها (SIGABRT) والمزيد من المعلومات عن كيفية تلقّيها (SI_TKILL). الإشارات التي تم الإبلاغ عنها من قِبل debuggerd
هي
SIGABRT وSIGBUS وSIGFPE وSIGILL وSIGSEGV وSIGTRAP. تختلف الرموز الخاصة بالإشارة استنادًا إلى الإشارة المحدّدة.
Abort message: 'some_file.c:123: some_function: assertion "false" failed'
لن يتضمّن بعض الأعطال سطر رسالة إيقاف، ولكن سيتضمّن ذلك الأعطال. يتم جمع هذه المعلومات تلقائيًا من السطر الأخير من إخراج logcat الخطير لهذا المعرّف التعريفي للعملية/معرّف التعريفي للسلسلة، وفي حال الإيقاف المتعمد، من المرجّح أن يقدّم تفسيرًا لسبب إنهاء البرنامج لنفسه.
r0 00000000 r1 00000678 r2 00000006 r3 f70b6dc8 r4 f70b6dd0 r5 f70b6d80 r6 00000002 r7 0000010c r8 ffffffed r9 00000000 sl 00000000 fp ff96ae1c ip 00000006 sp ff96ad18 lr f700ced5 pc f700dc98 cpsr 400b0010
يعرض جدول تسجيل الوحدات المحتوى في سجلات وحدة المعالجة المركزية في وقت تلقّي إشارة. (يختلف هذا القسم اختلافًا كبيرًا بين ABIs.) ويعتمد مدى فائدة هذه المعلومات على نوع العُطل بالضبط.
backtrace: #00 pc 00042c98 /system/lib/libc.so (tgkill+12) #01 pc 00041ed1 /system/lib/libc.so (pthread_kill+32) #02 pc 0001bb87 /system/lib/libc.so (raise+10) #03 pc 00018cad /system/lib/libc.so (__libc_android_abort+34) #04 pc 000168e8 /system/lib/libc.so (abort+4) #05 pc 0001a78f /system/lib/libc.so (__libc_fatal+16) #06 pc 00018d35 /system/lib/libc.so (__assert2+20) #07 pc 00000f21 /system/xbin/crasher #08 pc 00016795 /system/lib/libc.so (__libc_init+44) #09 pc 00000abc /system/xbin/crasher
يعرض لك "تتبُّع تسلسل استدعاء الدوال البرمجية" الموضع في الرمز البرمجي الذي كنا فيه في وقت حدوث العُطل. العمود
الأول هو رقم الإطار (يتطابق مع أسلوب gdb حيث يكون عمق الإطار
هو 0). تكون قيم وحدات التخزين المؤقتة نسبية إلى موقع المكتبة المشتركة بدلاً من الأرقام المطلقة. العمود التالي هو اسم المنطقة المُحدَّدة
(التي تكون عادةً مكتبة مشترَكة أو ملف قابل للتنفيذ، ولكن قد لا تكون مثلاً
رمزًا مُجمَّعًا باستخدام تقنية JIT). أخيرًا، إذا كانت الرموز متاحة، يتم عرض الرمز الذي تتوافق معه قيمة النقطة المرجعية
، بالإضافة إلى القيمة المرجعية لذلك الرمز في
بايت. يمكنك استخدام هذا مع objdump(1)
للعثور على
تعليمات المُجمِّع المقابلة.
قراءة ملفات Tombstone
Tombstone written to: /data/tombstones/tombstone_06
يوضّح لك ذلك المكان الذي كتب فيه debuggerd
معلومات إضافية.
سيحتفظ debuggerd
بما يصل إلى 10 سجلّات ميتة، وسينتقل من الرقم 00 إلى 09 وسيؤدّي إلى استبدال السجلات الميتة الحالية عند الضرورة.
يحتوي سجلّ الأخطاء على المعلومات نفسها المتوفّرة في ملف "تجميع بيانات الأعطال"، بالإضافة إلى بعض
المعلومات الإضافية. على سبيل المثال، يتضمّن هذا التقرير عمليات تتبُّع للخلف لجميع سلاسل المحادثات (وليس
فقط سلسلة المحادثات التي حدث بها العُطل)، وسجلّات النقطة العائمة، وعمليات تفريغ الذاكرة الخام،
وعمليات تفريغ الذاكرة حول العناوين في السجلات. من بين الميزات الأكثر فائدة أيضًا،
أنّها تتضمّن خريطة ذاكرة كاملة (مثل /proc/pid/maps
).
في ما يلي مثال مشروح من تعذُّر عملية ARM 32 بت:
memory map: (fault address prefixed with --->) --->ab15f000-ab162fff r-x 0 4000 /system/xbin/crasher (BuildId: b9527db01b5cf8f5402f899f64b9b121)
هناك نقطتان يجب ملاحظتهما هنا. السبب الأول هو أنّ هذا السطر مسبوق بـ "--->". تكون الخرائط مفيدة للغاية عندما لا يكون العُطل مجرد إشارة خاطئة لإزالة الإشارة إلى المؤشر. إذا كان عنوان الخطأ صغيرًا، من المحتمل أن يكون أحد الصيغ لإزالة الإشارة إلى مؤشر فارغ. بخلاف ذلك، يمكن أن تقدّم لك الخرائط حول عنوان خطأ معلومات حول ما حدث. في ما يلي بعض المشاكل المحتملة التي يمكن التعرّف عليها من خلال الاطّلاع على الخرائط:
- القراءة/الكتابة بعد نهاية كتلة ذاكرة
- القراءة/الكتابة قبل بداية كتلة ذاكرة
- محاولات تنفيذ تعليمات غير برمجية
- الوصول إلى نهاية حزمة
- يحاول الكتابة في الرمز البرمجي (كما هو موضّح في المثال أعلاه).
والنقطة الثانية التي يجب ملاحظتها هي أنّ ملفات التشغيل والمكتبات المشتركة ستعرض
BuildId (إذا كان متوفّرًا) في الإصدار 6.0 من نظام التشغيل Android والإصدارات الأحدث، حتى تتمكّن من معرفة
بالضبط إصدار الرمز البرمجي الذي تعطّل. تتضمّن الملفات الثنائية للنظام الأساسي رقم تعريف إصدار البنية (BuildId) بشكلٍ تلقائي منذ الإصدار 6.0 من نظام التشغيل Android، وينقل الإصدار r12 من حزمة NDK والإصدارات الأحدث تلقائيًا -Wl,--build-id
إلى أداة الربط أيضًا.
ab163000-ab163fff r-- 3000 1000 /system/xbin/crasher ab164000-ab164fff rw- 0 1000 f6c80000-f6d7ffff rw- 0 100000 [anon:libc_malloc]
في نظام التشغيل Android، لا تكون الحِزمة منطقة واحدة بالضرورة. سيتم وضع علامة [anon:libc_malloc]
على مناطق الذاكرة المؤقتة.
f6d82000-f6da1fff r-- 0 20000 /dev/__properties__/u:object_r:logd_prop:s0 f6da2000-f6dc1fff r-- 0 20000 /dev/__properties__/u:object_r:default_prop:s0 f6dc2000-f6de1fff r-- 0 20000 /dev/__properties__/u:object_r:logd_prop:s0 f6de2000-f6de5fff r-x 0 4000 /system/lib/libnetd_client.so (BuildId: 08020aa06ed48cf9f6971861abf06c9d) f6de6000-f6de6fff r-- 3000 1000 /system/lib/libnetd_client.so f6de7000-f6de7fff rw- 4000 1000 /system/lib/libnetd_client.so f6dec000-f6e74fff r-x 0 89000 /system/lib/libc++.so (BuildId: 8f1f2be4b37d7067d366543fafececa2) (load base 0x2000) f6e75000-f6e75fff --- 0 1000 f6e76000-f6e79fff r-- 89000 4000 /system/lib/libc++.so f6e7a000-f6e7afff rw- 8d000 1000 /system/lib/libc++.so f6e7b000-f6e7bfff rw- 0 1000 [anon:.bss] f6e7c000-f6efdfff r-x 0 82000 /system/lib/libc.so (BuildId: d189b369d1aafe11feb7014d411bb9c3) f6efe000-f6f01fff r-- 81000 4000 /system/lib/libc.so f6f02000-f6f03fff rw- 85000 2000 /system/lib/libc.so f6f04000-f6f04fff rw- 0 1000 [anon:.bss] f6f05000-f6f05fff r-- 0 1000 [anon:.bss] f6f06000-f6f0bfff rw- 0 6000 [anon:.bss] f6f0c000-f6f21fff r-x 0 16000 /system/lib/libcutils.so (BuildId: d6d68a419dadd645ca852cd339f89741) f6f22000-f6f22fff r-- 15000 1000 /system/lib/libcutils.so f6f23000-f6f23fff rw- 16000 1000 /system/lib/libcutils.so f6f24000-f6f31fff r-x 0 e000 /system/lib/liblog.so (BuildId: e4d30918d1b1028a1ba23d2ab72536fc) f6f32000-f6f32fff r-- d000 1000 /system/lib/liblog.so f6f33000-f6f33fff rw- e000 1000 /system/lib/liblog.so
تحتوي المكتبة المشتركة عادةً على ثلاثة إدخالات متجاورة. أحدهما قابل للقراءة
والتنفيذ (الرمز)، والآخر للقراءة فقط (البيانات القابلة للقراءة فقط)، والثالث للقراءة والكتابة
(البيانات القابلة للتغيير). يعرض العمود الأول نطاقات العناوين للربط، ويعرض
العمود الثاني الأذونات (بأسلوب ls(1)
المعتاد في نظام التشغيل Unix)، ويعرض
العمود الثالث القيمة المحورية في الملف (بالتنسيق الست عشري)، ويعرض
العمود الرابع حجم المنطقة (بالتنسيق الست عشري)، ويعرض
العمود الخامس الملف (أو اسم منطقة آخر).
f6f34000-f6f53fff r-x 0 20000 /system/lib/libm.so (BuildId: 76ba45dcd9247e60227200976a02c69b) f6f54000-f6f54fff --- 0 1000 f6f55000-f6f55fff r-- 20000 1000 /system/lib/libm.so f6f56000-f6f56fff rw- 21000 1000 /system/lib/libm.so f6f58000-f6f58fff rw- 0 1000 f6f59000-f6f78fff r-- 0 20000 /dev/__properties__/u:object_r:default_prop:s0 f6f79000-f6f98fff r-- 0 20000 /dev/__properties__/properties_serial f6f99000-f6f99fff rw- 0 1000 [anon:linker_alloc_vector] f6f9a000-f6f9afff r-- 0 1000 [anon:atexit handlers] f6f9b000-f6fbafff r-- 0 20000 /dev/__properties__/properties_serial f6fbb000-f6fbbfff rw- 0 1000 [anon:linker_alloc_vector] f6fbc000-f6fbcfff rw- 0 1000 [anon:linker_alloc_small_objects] f6fbd000-f6fbdfff rw- 0 1000 [anon:linker_alloc_vector] f6fbe000-f6fbffff rw- 0 2000 [anon:linker_alloc] f6fc0000-f6fc0fff r-- 0 1000 [anon:linker_alloc] f6fc1000-f6fc1fff rw- 0 1000 [anon:linker_alloc_lob] f6fc2000-f6fc2fff r-- 0 1000 [anon:linker_alloc] f6fc3000-f6fc3fff rw- 0 1000 [anon:linker_alloc_vector] f6fc4000-f6fc4fff rw- 0 1000 [anon:linker_alloc_small_objects] f6fc5000-f6fc5fff rw- 0 1000 [anon:linker_alloc_vector] f6fc6000-f6fc6fff rw- 0 1000 [anon:linker_alloc_small_objects] f6fc7000-f6fc7fff rw- 0 1000 [anon:arc4random _rsx structure] f6fc8000-f6fc8fff rw- 0 1000 [anon:arc4random _rs structure] f6fc9000-f6fc9fff r-- 0 1000 [anon:atexit handlers] f6fca000-f6fcafff --- 0 1000 [anon:thread signal stack guard page]
اعتبارًا من الإصدار 5.0 من نظام التشغيل Android، تُطلق مكتبة C أسماء على معظم المناطق التي تمّ ربطها بدون هوية، وبالتالي، يقلّ عدد المناطق غير المعروفة.
f6fcb000-f6fccfff rw- 0 2000 [stack:5081]
المناطق التي تحمل الاسم [stack:tid]
هي تجميعات لسلسلة رسائل العميل
المحدّدة.
f6fcd000-f702afff r-x 0 5e000 /system/bin/linker (BuildId: 84f1316198deee0591c8ac7f158f28b7) f702b000-f702cfff r-- 5d000 2000 /system/bin/linker f702d000-f702dfff rw- 5f000 1000 /system/bin/linker f702e000-f702ffff rw- 0 2000 f7030000-f7030fff r-- 0 1000 f7031000-f7032fff rw- 0 2000 ffcd7000-ffcf7fff rw- 0 21000 ffff0000-ffff0fff r-x 0 1000 [vectors]
يعتمد ظهور [vector]
أو [vdso]
على
البنية. تستخدم بنية ARM [vector]
، بينما تستخدم جميع البنى الأخرى
[vdso]
.