Kscrash: تتبعات مكدس غير صحيحة لاستثناءات C ++ في أطر العمل المضمنة

تم إنشاؤها على ٢٠ فبراير ٢٠١٧  ·  12تعليقات  ·  مصدر: kstenerud/KSCrash

يبدو أنه لا يتم استدعاء وظيفة __cxa_throw في KSCrashMonitor_CPPException.c عند طرح استثناء C ++ في إطار عمل مضمن ، على سبيل المثال CrashLib في تطبيق Crash-Tester.

لم أتمكن من التوصل إلى حل لهذا. بالنسبة لي ، يبدو أن أي مكتبة مضمنة ستستخدم دائمًا __cxa_throw من libc ++ ، وليس التنفيذ في KSCrash.

بالإضافة إلى ذلك: عند طرح استثناء C ++ غير معالج في إطار عمل مضمن ، سوف يتعطل KSCrash أثناء الإبلاغ ، نظرًا لأن stackCursor-> advanceCursor سيساوي NULL في KSCrashReport.c: writeBacktrace ().

تحرير: المعلومات المضافة KSCrash تحطم أثناء الإبلاغ.

التعليق الأكثر فائدة

بعد مزيد من التحقيق ، يبدو أن تعليقي السابق كان غير صحيح:

أعتقد أنه يجب إعادة تسمية هذه المشكلة إلى شيء مثل _ "تتبعات المكدس المفقودة لاستثناءات C ++ التي تم إلقاؤها من الصور غير المرتبطة بشكل ثابت بـ KSCrash" _.

في حالة ربط KSCrash بالتطبيق الرئيسي كمكتبة ثابتة:

  • MyApplication ( main.o ، libKSCrash.a )

    • libDynamicLibrary.dylib ( lib.o )

    • /usr/lib/libc++abi.dylib

أي استثناءات يتم طرحها من MyApplication ستدخل libKSCrash.a::__cxa_throw . في الإضافات ، نظرًا لأن libKSCrash.a يعلن __cxa_throw كـ weak ، لا يفشل ربط MyApplication إذا كان main.o يمتلك __cxa_throw تجاوز libDynamicLibrary.dylib لن تؤدي إلى تشغيل libKSCrash.a::__cxa_throw ، وستنتهي في /usr/lib/libc++abi.dylib::__cxa_throw .

في حالة ربط KSCrash بالتطبيق الرئيسي كمكتبة ديناميكية:

  • MyApplication ( main.o )

    • libKSCrash.dylib

    • /usr/lib/libc++abi.dylib

    • libDynamicLibrary.dylib ( lib.o )

    • /usr/lib/libc++abi.dylib

أي استثناءات يتم طرحها من MyApplication ستدخل libKSCrash.dylib::__cxa_throw ، ولكن فقط إذا:

  1. يتم تصدير __cxa_throw من libKSCrash.dylib
  2. __cxa_throw لم يتم تمييزه كـ weak

إذا تم تمييز __cxa_throw كـ weak ( 0000000000002e90 (__TEXT,__text) weak external ___cxa_throw ) ، فعند ربط libKSCrash.dylib يبدو الرابط وكأنه ينظر إلى /usr/lib/libc++abi.dylib ، ابحث عن غير - ضعيف __cxa_throw ، واستنتج أنه يجب تجاهل libKSCrash.dylib::__cxa_throw . أثناء البحث عن رمز وقت التشغيل في وقت العرض من MyApplication ، ثم يتم تجاهل libKSCrash.dylib::__cxa_throw .

يقودني هذا إلى الاعتقاد بأنه يجب إضافة السمة weak بشكل مشروط فقط عند إنشاء KSCrash كمكتبة ثابتة.

كما هو الحال بالنسبة لحالة الاستخدام الأولى ، فإن أي استثناءات يتم طرحها من libDynamicLibrary.dylib لن تؤدي إلى libKSCrash.dylib::__cxa_throw ، وستنتهي في /usr/lib/libc++abi.dylib::__cxa_throw .

من المحتمل أن يتم إصلاح هذه المشكلة من خلال تصحيح وقت تشغيل منخفض المستوى للصور المحملة بمراجع غير محددة إلى __cxa_throw . باستخدام تطبيق الاختبار المشار إليه في المقالة ، لقد تحققت من أن هذه التقنية تعمل بالفعل مقابل __cxa_throw أيضًا.

cooked_throw

ال 12 كومينتر

أي حظ مع هذا؟ أحاول دمج KSCrash في تطبيقي ، لكنني عالق بسبب الإطار المضمن.
يرجى إعلامي إذا كان لديك أي حل لهذا الغرض.

لا حظ ، ولا أعتقد أنه ممكن ، على الأقل ليس في حالة الاستخدام لدينا. هذا هو فهمي للوضع:

الطريقة التي يسجل بها KSCrash تتبع المكدس هي عن طريق إنشاء تطبيقه الخاص لـ __cxa_throw ، والذي يسمح بالوصول إلى المكدس قبل أن يتم التخلص منه بواسطة libc ++. يعمل هذا طالما أن KSCrash مرتبط بشكل ثابت برمز C ++ ، حيث سيجد الرابط ويستخدم __cxa_throw form KSCrash بدلاً من التنفيذ في libc ++. ولكن في حالة وجود إطار عمل مضمن يرتبط بـ libc ++ ، فسيتم استخدام تنفيذ __cxa_throw من libc ++ ، نظرًا لأن إطار العمل لا يعرف الكود في KSCrash. ربما يكون هناك حل بديل إذا كنت تتحكم في إطار العمل المضمن ، لكن هذا لن ينجح في حالة الاستخدام الخاصة بنا.

واسمحوا لي أن أعرف إذا وجدت حلا.

لدي سيطرة على الإطار المضمن. لكن لست متأكدًا من كيفية إصلاحه.
لقد جربت أيضًا PLCrashReporter ، نفس المشكلة معها.

هل هذا يعني أنه يجب بناء KSCrash بشكل مثالي كمكتبة ثابتة وربطها بالتطبيق ، على الأقل للقبض على استثناءات C ++ التي تم إلقاؤها في كود التطبيق؟

لكن هذا من شأنه أن يترك أي استثناءات تم إلقاؤها في أي مكتبة ديناميكية غير معلومة بواسطة KSCrash إذا فهمت تقرير الخطأ الخاص بك بشكل صحيح pdrtrifork ؟ إذا كنا نتحكم في libs الديناميكية المضمنة ، فهل يمكننا الربط في lib ثابت بكل منها باستخدام هذا __cxa_throw stub فقط ، والذي من شأنه أن يرجح إلى معالج KSCrash المشترك؟

هاه ، لذا عند التحقيق في هذا انتهى بي الأمر هنا http://stackoverflow.com/questions/36846628/conditionally-overriding-cxa-throw ، والذي تم افتتاحه بواسطة kstenerud الخاص بنا 😄

على أي حال ، يجب أن يمنع PR # 219 على الأقل التعطل أثناء الإبلاغ عن الأعطال.

kstenerud أعتقد أنه يجب إعادة تسمية هذه المشكلة إلى شيء مثل _ "تتبعات المكدس المفقودة لاستثناءات C ++ التي تم إلقاؤها من الصور غير المرتبطة بشكل ثابت بـ KSCrash" _. بقدر ما أستطيع أن أقول ، فإن تجاوز __cxa_throw يعمل فقط في نفس الصورة مثل KSCrash ، لذلك:

  • إذا تم إنشاء KSCrash كمكتبة ثابتة ومرتبط بالتطبيق الرئيسي ، فستحصل على آثار خلفية لاستثناء C ++ إذا تم طرح الاستثناء في التطبيق الرئيسي ، ولكن ليس عند طرحه من مكتبات محملة ديناميكيًا
  • إذا تم إنشاء KSCrash كمكتبة ثابتة وربطها بمكتبة ديناميكية (مجمعة) ، فستحصل على آثار خلفية لاستثناء C ++ إذا تم طرح الاستثناء من تلك المكتبة الديناميكية ، ولكن ليس عند طرحها من التطبيق الرئيسي ، أو مكتبات أخرى محملة ديناميكيًا
  • إذا تم إنشاء KSCrash كمكتبة مشتركة (إطار عمل) ، فستحصل على آثار خلفية لاستثناء C ++ إذا تم طرح الاستثناء من KSCrash ، ولكن ليس عند طرحه من التطبيق الرئيسي ، أو مكتبات أخرى محملة ديناميكيًا

سيؤثر الأخير على العملاء مثل sentry-swift ، https://docs.sentry.io/clients/cocoa/ ، والذي يدمج KSCrash كإطار عمل.

بعد مزيد من التحقيق ، يبدو أن تعليقي السابق كان غير صحيح:

أعتقد أنه يجب إعادة تسمية هذه المشكلة إلى شيء مثل _ "تتبعات المكدس المفقودة لاستثناءات C ++ التي تم إلقاؤها من الصور غير المرتبطة بشكل ثابت بـ KSCrash" _.

في حالة ربط KSCrash بالتطبيق الرئيسي كمكتبة ثابتة:

  • MyApplication ( main.o ، libKSCrash.a )

    • libDynamicLibrary.dylib ( lib.o )

    • /usr/lib/libc++abi.dylib

أي استثناءات يتم طرحها من MyApplication ستدخل libKSCrash.a::__cxa_throw . في الإضافات ، نظرًا لأن libKSCrash.a يعلن __cxa_throw كـ weak ، لا يفشل ربط MyApplication إذا كان main.o يمتلك __cxa_throw تجاوز libDynamicLibrary.dylib لن تؤدي إلى تشغيل libKSCrash.a::__cxa_throw ، وستنتهي في /usr/lib/libc++abi.dylib::__cxa_throw .

في حالة ربط KSCrash بالتطبيق الرئيسي كمكتبة ديناميكية:

  • MyApplication ( main.o )

    • libKSCrash.dylib

    • /usr/lib/libc++abi.dylib

    • libDynamicLibrary.dylib ( lib.o )

    • /usr/lib/libc++abi.dylib

أي استثناءات يتم طرحها من MyApplication ستدخل libKSCrash.dylib::__cxa_throw ، ولكن فقط إذا:

  1. يتم تصدير __cxa_throw من libKSCrash.dylib
  2. __cxa_throw لم يتم تمييزه كـ weak

إذا تم تمييز __cxa_throw كـ weak ( 0000000000002e90 (__TEXT,__text) weak external ___cxa_throw ) ، فعند ربط libKSCrash.dylib يبدو الرابط وكأنه ينظر إلى /usr/lib/libc++abi.dylib ، ابحث عن غير - ضعيف __cxa_throw ، واستنتج أنه يجب تجاهل libKSCrash.dylib::__cxa_throw . أثناء البحث عن رمز وقت التشغيل في وقت العرض من MyApplication ، ثم يتم تجاهل libKSCrash.dylib::__cxa_throw .

يقودني هذا إلى الاعتقاد بأنه يجب إضافة السمة weak بشكل مشروط فقط عند إنشاء KSCrash كمكتبة ثابتة.

كما هو الحال بالنسبة لحالة الاستخدام الأولى ، فإن أي استثناءات يتم طرحها من libDynamicLibrary.dylib لن تؤدي إلى libKSCrash.dylib::__cxa_throw ، وستنتهي في /usr/lib/libc++abi.dylib::__cxa_throw .

من المحتمل أن يتم إصلاح هذه المشكلة من خلال تصحيح وقت تشغيل منخفض المستوى للصور المحملة بمراجع غير محددة إلى __cxa_throw . باستخدام تطبيق الاختبار المشار إليه في المقالة ، لقد تحققت من أن هذه التقنية تعمل بالفعل مقابل __cxa_throw أيضًا.

cooked_throw

أحاول التحقق من التعطل في إطار عمل في تطبيقي. عندما أحاول الحصول على سجل الأعطال ، أرى أن تتبع المكدس لا يظهر الانهيار الفعلي ، وبدلاً من ذلك يتعطل KSCrash.

هل هذه نفس المشكلة؟

الموضوع 0 تحطم:
0 libsystem_kernel.dylib 0x0000000181cc5348 0x181ca4000 + 136008 (__pthread_kill + 8)
1 libsystem_pthread.dylib 0x0000000181ddd7a4 0x181dd6000 + 30628 (+ 360)
2 libsystem_c.dylib 0x0000000181c34fd8 0x181bd2000 + 405464 (إحباط + 140)
3 libc ++ abi.dylib 0x0000000181698068 0x181696000 + 8296 (+ 132)
4 libc ++ abi.dylib 0x0000000181698210 0x181696000 + 8720 (+ 304)
5 libobjc.A.dylib 0x00000001816c0810 0x1816b8000 + 34832 (+ 124)
6 KSCrash 0x00000001054a0590 0x10549c000 + 17808 (kscm_cppexception_getAPI + 280)
7 libc ++ abi.dylib 0x00000001816b054c 0x181696000 + 107852 (+ 16)
8 libc ++ abi.dylib 0x00000001816b0158 0x181696000 + 106840 (__cxa_rethrow + 144)
9 libobjc.A.dylib 0x00000001816c06e8 0x1816b8000 + 34536 (objc_exception_rethrow + 44)
10 CoreFoundation 0x0000000182072344 0x18206a000 + 33604 (CFRunLoopRunSpecific + 544)
11 خدمات الرسومات 0x0000000183f03f84 0x183ef9000 + 44932 (GSEventRunModal + 100)
12 UIKit 0x000000018b61e880 0x18b5ab000 + 473216 (تطبيق UIAMain + 208)

torarnv مرحبًا ، هل يمكنك مشاركة العرض التوضيحي الناجح الخاص بك معنا؟ واجهت EXC_BAD_ACCESS عندما أحاول mach_hook __cxa_throw.

void ter_handler(){
    printf("custom handler\n");
}

void test(){
    throw std::runtime_error("test function");
}

static void (*orig_throw)(void * thrown_exception, std::type_info *tinfo, void (*dest)(void *));

void hooked_throw(void * thrown_exception, std::type_info *tinfo, void (*dest)(void *)){
    printf("hooked_throw...\n");
    return orig_throw(thrown_exception, tinfo, dest);
}

int main(int argc, char * argv[])
{
    <strong i="5">@autoreleasepool</strong> {

        struct rebinding binds[1];
        struct rebinding bind1 = {"__cxa_throw", (void *)hooked_throw, (void **)&orig_throw};
        binds[0] = bind1;
        rebind_symbols(binds, 1);

        std::set_terminate(ter_handler);
        try {
            throw std::runtime_error("test error");
        }
        catch (...){
            printf  ("catch exception\n");
        }

        test();
    }
}

جرب هذا ... حظا سعيدا

لقد واجهت حادثًا واحدًا مع KSCrash ،
kscrash

كيفية حلها؟

لقد أنشأنا خطافًا ديناميكيًا تنفيذيًا للعلاقات العامة المذكور أعلاه بواسطة huakucha : # 375

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات