سؤال

لقد تمكنت من تسجيل منفذ Mach الخاص بي لالتقاط استثناءات Mach في تطبيقاتي ويعمل بشكل جميل عندما أستهدف 32 بت. ومع ذلك ، عندما أستهدف 64 بت ، معالج الاستثناء الخاص بي catch_exception_raise() يتم استدعاؤه ولكن مجموعة رموز الاستثناء التي يتم تمريرها إلى المعالج هي 32 بت. هذا متوقع في بناء 32 بت ولكن ليس في 64 بت.

في الحالة التي ألتقط فيها EXC_BAD_ACCESS الرمز الأول هو رقم الخطأ ويجب أن يكون الرمز الثاني هو عنوان الخطأ. نظرًا لأن الكود الثاني يبلغ عرضه 32 بت ، يتم اقتطاع 32 بت من عنوان خطأ 64 بت.

لقد وجدت العلم في <mach/exception_types.h> يمكنني أن أتحول task_set_exception_ports() اتصل MACH_EXCEPTION_CODES والتي يبدو من النظر إلى مصادر داروين تتحكم في حجم الرموز التي تم تمريرها إلى المعالج. يبدو أنه من المفترض أن يتم تشغيله مع السلوك الذي تم تمريره إلى task_set_exception_ports().

ومع ذلك ، عندما أفعل هذا وأشعل استثناءً ، يتم إخطار منفذ ماخ الخاص بي ، أتصل exc_server() لكن معالجتي لم يتم استدعاؤها مطلقًا ، وعندما يتم إرسال رسالة الرد مرة أخرى إلى kernel ، أحصل على سلوك الاستثناء الافتراضي.

أنا أستهدف 10.6 SDK.

أتمنى حقًا أن توثق Apple هذه الأشياء بشكل أفضل. هل لدي احد اى افكار؟

هل كانت مفيدة؟

المحلول

حسنًا ، لقد اكتشفت ذلك.

للتعامل مع استثناءات Mach ، يجب عليك تسجيل منفذ Mach للاستثناءات التي تهتم بها. ثم تنتظر وصول رسالة إلى المنفذ في موضوع آخر. عند وصول رسالة ، تتصل exc_server() يتم توفير تنفيذها بواسطة System.Library. exec_server() يأخذ الرسالة التي وصلت وتدعو أحد المعالجات الثلاثة التي يجب أن تقدمها. catch_exception_raise(), catch_exception_raise_state(), ، أو catch_exception_raise_state_identity() اعتمادًا على الحجج التي مررت بها task_set_exception_ports(). هذه هي الطريقة التي يتم بها لتطبيق 32 بت.

بالنسبة للتطبيقات التي تبلغ قيمتها 64 بت ، لا تزال طريقة 32 بت تعمل ، لكن البيانات التي تم تمريرها إليك في معالجك قد يتم اقتطاعها إلى 32 بت. للحصول على 64 بت البيانات التي يتم تمريرها إلى معالجاتك تتطلب القليل من العمل الإضافي غير المستقيم إلى الأمام وبقدر ما أستطيع أن أخبره جيدًا. تعثرت على الحل من خلال النظر إلى مصادر GDB.

بدلا من الاتصال exc_server() عندما تصل رسالة إلى المنفذ ، عليك الاتصال mach_exc_server() في حين أن. يجب أن يكون للمعالجات أسماء مختلفة أيضًا catch_mach_exception_raise(), catch_mach_exception_raise_state(), ، و catch_mach_exception_raise_state_identity(). المعلمات للمعالجات هي نفس نظيراتها 32 بت. المشكلة هي mach_exc_server() لم يتم توفيره لك بالطريقة exc_server() هو. للحصول على التنفيذ mach_exc_server() يتطلب استخدام الأداة المساعدة MIG (Mach Interface Generator). يأخذ MIG ملف تعريف الواجهة ويقوم بإنشاء مجموعة من ملفات المصدر التي تتضمن وظيفة الخادم التي ترسل رسائل MACH إلى المعالجات التي تقدمها. تتضمن 10.5 و 10.6 SDKs ملف تعريف MIGu003Cmach_exc.defs> للحصول على رسائل استثناء وسيقوم بإنشاء mach_exc_server() وظيفة. يمكنك بعد ذلك تضمين ملفات المصدر التي تم إنشاؤها في مشروعك ومن ثم أنت على ما يرام.

الشيء الجميل هو أنه إذا كنت تستهدف 10.6+ (وربما 10.5) يمكنك استخدام نفس الاستثناء معالجة كل من 32 و 64 بت. فقط أو سلوك الاستثناء مع MACH_EXCEPTION_CODES عندما تقوم بتعيين منافذ الاستثناء الخاصة بك. ستأتي رموز الاستثناء كقيم 64 بت ولكن يمكنك اقتطاعها إلى 32 بت في بنيتك البالغة 32 بت.

أخذت mach_exc.defs ملف ونسخه إلى دليل المصدر الخاص بي ، وفتح محطة واستخدم الأمر mig -v mach_exc.defs. هذا ولدت mach_exc.h, mach_excServer.c, ، و mach_excUser.c. قمت بعد ذلك بتضمين تلك الملفات في مشروعي ، وأضفت الإعلان الصحيح لوظيفة الخادم في ملف المصدر الخاص بي وقمت بتنفيذ معالجاتي. ثم قمت ببناء تطبيقي وكنت على ما يرام.

حسنًا ، هذا ليس أفضل وصف ، ولكن نأمل أن يساعد شخص آخر.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top