مرحبًا. أريد أن أتحدث عن دورتي أو ما الذي يؤدي إليه الفضول.
لفترة طويلة من لا شيء أفعله أكتب برامج تحت سيمبيان. ومن وقت لآخر صادفت أشياء غريبة أثناء التجميع. كل شيء يشير إلى فائدة elf2e32. وتتمثل مهمتها في تحويل ملف الإدخال الثنائي الخاص بتنسيق elf إلى ملف آخر خاص بصورة Symbian - e32. لقد شعرت بالحيرة لفترة طويلة بسبب الفضول - كيف تعمل هذه الأداة على الإطلاق ولماذا هي في بعض الأحيان عربات التي تجرها الدواب؟ بعد ذلك بقليل ، بدأ سؤال آخر يزعجني - موضوع عمل الدورة =) قررت الجمع بين العمل والمتعة وتنزيل شفرة المصدر الخاصة به. ونذهب بعيدا ...
الالتزام الأول لن
والثاني - نحن ندرج امتدادات دول مجلس التعاون الخليجي غير القياسية ، ونضيف فئات ووظائف مفقودة وثوابت من المصدر. الموضوع يجمع بسعادة ويسقط. التقدم ولكن. نبدأ تحت المصحح - يضع المصحح في فئة تقوم فقط بتهيئة فئة أخرى تهيئ الصف التالي ... مرحى! ميزة حقيقية! تعال. عفوًا اين نحن؟ !!! توقف المصحح! جراح! مشرط! الكحول! خيار! فصول الملحق و Firebox! إعطاء nullptr بدلاً من NULL! لدينا C ++ 14! رائع ، يا له من مُنشئ مرعب لتهيئة كل شيء بالأصفار! ومع ذلك ، مرارًا وتكرارًا - ولكن معنا ، يستدعي C ++ 14 التهيئة الافتراضية للفصول! كل ما هو موجز الآن ...
حسنًا. نقوم بإصلاح أكبر عدد ممكن في وقت واحد. لقد اكتشفت لماذا يقفز المصحح إلى شفرة المصدر مثل الملاءمة - حيث ضربت أفرستس رؤوسهم على التجريد ، مما أدى إلى زيادة ميراث 80 مستوى من فئة UseCaseBase :) ثم ، حلقت فئات المُنشئين من الحالات الثابتة لفصول الرسائل والمعلمات من عيني. سينجلتون مايرز؟ لا ، لم يسمع. تجريد Firebox! ثورة فيفا !!! Viva POD !!!
واو ما مدى إثارة هذه الشجرة. يتم تنفيذ العمل الرئيسي بواسطة الدالة BuildAll (). إذا تم تحديد جميع المعلمات ، فستقوم الدالة بجمع مكتبة الاستيراد ، وملف يحدد أسماء الوظائف والمتغيرات والترتيب الذي تتوفر به في مكتبة الاستيراد والثنائي نفسه. قام جميع أحفاد UseCaseBase بتغيير الخوارزمية من خلال التحميل الزائد. في بعض الأحيان في الأحفاد نقوم بإعداد بيانات مساعدة ، ولكن في أغلب الأحيان يقومون ببساطة بإيقاف إنشاء بعض الملفات. على سبيل المثال ، لم يتم تحديد اسم الملف لتجميع شيء ما - يتم إنشاء فئة جديدة. البلهاء. يكفي مقاطعة تنفيذ جامع الوظائف إذا لزم الأمر. من السهل فهم أفعالي ب-)
نستمر في حذف الفئات الفارغة ، واستبدال NULL بـ nullptr_t ، واستبدال مكرر النطاق بـ لـ (auto x: *).
نقوم بإصلاح الأخطاء في معالجة معلمات سطر الأوامر.
من الضروري التحقق من الرمز باستخدام محلل ثابت. من أين تبدأ؟ همم ، تحت XP ، الخيار صغير - cppcheck ، ويدعمه codeblock خارج الصندوق. رائع ، يا له من صيد! حتى أن هناك حذف لحرف []! لعنة ، أنا أعرف أين ذهبت نصف ذاكرة الوصول العشوائي المجانية =)
لذا نضيف الملفات التي تم إنشاؤها من ملف libcrypto.dll elf-file والملف نفسه الذي يصف معلمات سطر الأوامر لإنشائها.
عفوًا فحص CPPC كان خطأ ... يجب أن يكون (a || b) ...
سأحاول البناء في Visual Studio 15 وسوف تلتصق Win10 بعصا. ضع على آلة افتراضية. تم تنزيل برنامج الاستوديو عبر الإنترنت وتنزيله وتشغيله. ماذا؟ لا تريد حفظ القفزة إلى المجلد المشترك مع المضيف ؟! نعم ، اختنق عليك! قم بتنزيل المكان الذي تدرس فيه ... والآن ننقل التنزيل إلى المجلد ونبدأ التثبيت. ماذا؟ مرة أخرى يتجاهل المجلد المشترك ؟؟! نعم ، اختنق عليك! أصبح حيث تم تعليمك ...
من حيث المبدأ ، عشرات الصدأ على قلب واحد و 3 العربات من الإطار. استوديو للاستوديو! مدروس ، ولكن ليس لفترة طويلة. نفتح مشروعي في الاستوديو ، وأقسم مرة أخرى على المجلد ... كم هو ممكن بالفعل؟ نعم تختنق ... نجمعها ، أقسم على ملحقات غير قياسية. بعيد. بعيد ؟؟؟ بدوره على الدماغ =)
رائع ما هو رمز جذاب:
int ElfFileSupplied::UnWantedSymbolp(const char * aSymbol) { static hash_set<const char*, hash<const char*>, eqstr> aSymbolSet; int symbollistsize=sizeof(Unwantedruntimesymbols)/sizeof(Unwantedruntimesymbols[0]); static bool FLAG=false; while(!FLAG) { for(int i=0;i<symbollistsize;i++) { aSymbolSet.insert(Unwantedruntimesymbols[i]); } FLAG=true; } hash_set<const char*, hash<const char*>, eqstr>::const_iterator it = aSymbolSet.find(aSymbol); if(it != aSymbolSet.end()) return 1; else return 0; }
دعونا نفكر قليلا ... وفويلا:
int ElfFileSupplied::UnWantedSymbolp(const char * aSymbol) { int symbollistsize = sizeof(Unwantedruntimesymbols) / sizeof(Unwantedruntimesymbols[0]); for (int i = 0; i<symbollistsize; i++) { if (strstr(Unwantedruntimesymbols[i], aSymbol)) return 1; } return 0; }
جمالي ...
لذا ، لماذا يرمي البرنامج استثناءً إذا تم تعيين هذه العلامة بشكل غير صحيح أو لم يتم تعيينها على الإطلاق؟ لماذا أنت قاسي جدًا وجميل بعيدًا ... دعنا فقط نعيد تعيين هذا العلم إلى قيمة آمنة. وهذا العلم سيكون لطيفًا أيضًا ... وهذا ، وهذا ، وهذه. أو ربما من الأفضل وضعها في وظيفة منفصلة؟ فكرة جيدة! دعونا نسميها ParameterManager :: CheckOptions ()!
خطوة إلى اليسار هي سقوط ، خطوة إلى اليمين هي استثناء غير معلوم ، قفزة في مكانها - شكرا على الأقل ليس BSOD =)
مملة ... مواطن الخلل والانحناء ...
اوليلا !!! هل تحاكي CleanUpStack Symbian على STL؟:
لا شيء خاص في الأساس:
std::vector<char*> cleanupStack;
التنظيف:
std::vector<char*>::iterator aPos; char *aPtr; aPos = cleanupStack.begin(); while( aPos != cleanupStack.end() ) { aPtr = *aPos; delete[] aPtr; ++aPos; }
يستخدم بعض الرأس الساطع بدلاً من اليسار / اليمين l / r. شكرا cppcheck.
آه ، كسول أمام الشاشة ، سجلات cppcheck لتفكيك ... ماذا سيقدم لنا جيثوب؟ .. الترميز ... نحن نربط المشروع ... فكرت قليلا وهو جاهز! الآن يمكنك قراءة رسائل النجاح في مكافحة الأخطاء التي تقع على الأريكة ^^
لذا ، يبدو أنها ليست عربات التي تجرها الدواب ... دعنا نجمع شيئًا ، على سبيل المثال libcrypto.dll. يعمل ، على الرغم من أن الملف غير المضغوط هو مائة بايت أكثر من الملف الذي تم إنشاؤه بواسطة الأداة المساعدة من SDK. بعد ذلك ، سيتم مقارنة الثنائيات التي تم إنشاؤها بواسطة هذا الإصدار من الأداة ومن SDK باستمرار. خيارات سطر الأوامر متطابقة في حد ذاتها.
الداتشوند ، أين تحصل على التناظرية فرق للملفات الثنائية؟ حسنًا ، احصل على النص على المكبس. الكثير من المعلومات - تحتاج إلى شيء أبسط بكثير. ملف DLL للتعرف على ملف Pdf / djvu - AlternateReaderRecog.dll هو خيار جيد ، والعادم أقل من 4 كيلوبايت. الكلاب الألمانية ، الإزاحات تختلف في قسم الاستيراد. نفتحها في محرر عرافة. البداية هي نفسها ، في نسختي تستمر القمامة ، مباشرة بعد نهاية القسم في النسخة الأصلية. ولكن في إصداري ، يبدأ القسم التالي بعد 100 بايت. بنفس القيمة بالبايت ، تختلف الملفات! كما تشير الإزاحات إلى العناوين الصحيحة ... الثنائي صحيح !!! أههه !!!
بعد شهر. إذن من أين أتت هذه البايت المائة؟
حسنًا ، نظرًا لأنه ليس من الواضح كيف يعمل ، نبدأ في كسر الخوارزمية لإنشاء E32Image. المتابعة للسخرية AlternateReaderRecog.dll. نقوم بزيادة حجم الثنائي في الإخراج - بأي حال من الأحوال ، الكتابة فوق أقسام memset - بأي حال من الأحوال ، تقليل حجم الثنائي - بأي حال من الأحوال. Grrrr. ما هذا !!! أكسر العادم في نسخة الإصدار ، وابدأ التصحيح؟ !!! مرحبًا ، ابدأ من جديد ... تم محو قسم Soooo - حسنًا! زيادة حجم ثنائي! جيد !!! تقليل حجم قسم الاستيراد! يوجد !!! بايت مطابق لنفس القسم في عادم هذه الأداة المساعدة من SDK!
نحن ننظر إلى الكود لإنشاء هذا القسم. "sizeof (char *)" - شيء يذكرنا بالمقالة التي كتبها أندريه كاربوف ، أحد مطوري Pvs-studio ، حول حقيقة أن الأنواع يمكن أن تشغل كميات مختلفة من الذاكرة - وكم من المساحة تستغرق؟ MinGW - 8 بايت ، Visual Studio - 4 !!! نقسم هذه 8 بايت في النصف ، شيء تجاري. FFse! وكيف هو قسم الكود؟ هذا دلل دون المتغيرات العالمية. لا توجد متغيرات عالمية - لا يوجد قسم ... لنأخذ شيئًا أثقل - libcrypto.dll.
الملف في إخراج الأداة المساعدة الخاصة بي الآن أصغر من 100 بايت ... ماذا ؟؟؟ قسم الاستيراد متطابق بايت - جيد. قسم الرمز - لا؟ !!
بالعين ، لا يمكنني مقارنة جدار النص هذا ... سأبحث عن فرق مقارنة البايت ...
بعد يومين ، ما زلت أجد ألعابًا باستخدام بحث Google. vbindiff عبارة عن أداة مساعدة لوحدة تحكم بواجهة ala Norton Commander ، توضح الفرق بين ملفين في لوحين أفقيين. للانتقال إلى مكان الاختلاف ، اضغط على Enter. جيد! يمكنك سحب ملفين على الأيقونة للمقارنة وسيفتحها البرنامج! عظيم !!!
قارن - soooo في الرأس تختلف CRC ووقت الإنشاء. لا شيء من هذا القبيل. هنا البايت مختلف ، ها هي مائة أخرى ... واو !!! عشرات ومئات وآلاف البايت من الاختلاف؟ !!! لذا ، انظر ، انظر إلى القسم الذي ينتمون إليه ... ننظر إلى الإزاحات ... نعم ، قسم البيانات ...
نقوم بالخدعة ، أما بالنسبة لقسم الاستيراد ... فنحن نعيد تعيين الميمز. زيادة حجم القسم ... هبوط ... زيادة. يقدم يد المصحح وقلبه ... لعنة. نفتح وظيفة إنشاء القسم - عصيدة من الوظائف ... Grr.
... آه ، غدا ... حتى أصلح شيء آخر ...
على سبيل المثال ، سأضيف اختبارات ، ولكن هناك فوضى بحيث يستحيل تقسيم البرنامج إلى وحدات صغيرة. لا يمكنك إدراج الاختبارات مباشرة في الرمز - ثم ستفهم الفجل. الفكرة! إطلاق مستمر للبرامج بحجج مختلفة - لقد كنت أختبر البرنامج طوال الوقت ... ودعنا نجعل هذا أفضل كل نص منفصل في الثعبان. نعم ، فكرة عظيمة ، فقط رائعة. يجب أن يستمر البرنامج النصي في العمل عند الإبلاغ عن أخطاء الاختبار ، والإبلاغ عنها ولكن لا يتعطل. انتهى!
نعود إلى كبشنا ... هذه الوظيفة تسمي هذا ، ثم هذا ، نذهب هنا ... لذا ، سيدي ، إلى أين جلبتني؟ آه ، الخلط ... آه ، غدا ... حتى أصلح شيء آخر ...
وهكذا مرت شهرين ...
لعنة ، أين يتم تشكيل هذا القسم من التعليمات البرمجية؟ كان علي أن أذهب إلى إجازة أكاديمية ، لذا على الأقل سأكتشف الأمر معك !!! سووو هنا تذهب رموز القسم إلى الإدخال ... ماذا سيظهر printf؟ كل شيء لا يتناسب مع المخزن المؤقت لوحدة التحكم ... لنحفظ العادم في ملف ... Sooo حتى الآن لا يوجد شيء خاص ... توقف! نفس السطور !!! الكثير من الخطوط المتطابقة !!! من أين؟! إضافة printf إلى كل مصدر بيانات (كان هناك ما يكفي من الصبر لثلاثة من أصل خمسة ، هكتار). إنه فارغ! ننظر إلى إحدى استدعاءات الوظائف المتبقية ... Taak. زيادة المكرر بعد الحلقة ؟؟؟ وتحذير كودو تودو ؟؟؟ ننتقل إلى الدورة. إطلاق !!! هناك تطابق الحجم! هناك تطابق بايت !!! ثابت !!! اللوم git يرفض تسمية البطل ... نحن ننظر إلى الأصل - ليس هذا ما فعلته. أو ربما كانت "قنبلة" للمطورين غير المنتسبين إلى نوكيا؟ Grrr.
تحقق بعناية من اختبارات العادم ، وتحقق من ملفات البايت. كل شيء يعمل كما ينبغي! في الإصدار!
العليا! حان الوقت لتطهير رائع !!! حان الوقت لاقتلاع شجرة UseCaseBase مع الجذر !!!
لقد تم تهالك معظم الأحفاد بالفعل ، ونزيل الوظائف المفيدة لفئة المولد. فقط UseCaseBase وسليله ElfFileSupplied باقون. UseCaseBase - عبارة عن مجمّع فوق فئة يعالج معلمات الأمر ويعلن عن العديد من الوظائف الظاهرية البحتة لفئة ElfFileSupplied. باختصار ، عازف الكمان ليس ضروريًا ... ما السماء زرقاء ، جيدة ... ساعة أخرى ... سأتعامل مع هذا الفصل ويمكنك الذهاب في نزهة ... والتنفس في الهواء ، الاحماء ، جيد ... دعنا نذهب! لذا ، علق على هذه الميزة. جمع! Soooo ، تحتاج إلى التفكير في كيفية إعادة صنعه بشكل جميل ... فعلت !!! الميزة التالية! انتهى التالي! انتهى انتهى نعم فعلا! نعم فعلا! نعم فعلا! آخر وظيفة ... Ufff. اركض بعد التجميع ... سبع مرات لتسريع العمل؟ !!! العادم صحيح ... مضحك. كما تم تقليص إصدار التصحيح بمقدار 2 متر؟ !!! واو !!! يمكنك المشي. في الليل؟ !!! كعك ؟؟؟ أين يومي؟ !!! سأبدأ الاختبارات والاسترخاء ... الاختبارات عملت بهدوء - يمكنك الاسترخاء ...
اسمحوا لي أن أكتب شيئًا خاصًا بي الآن ... أوه ، الفصل الذي يعمل مع الوظائف والمتغيرات المتاحة من الخارج يبدو زاحفًا. مبدأ التشغيل: القراءة من ملف ، تحليل الخطوط وحفظ الملف. لتحليل الخطوط ، تم عزل فئة كاملة من المعكرونة المختارة في S ... Sooooh ... دعونا نفكر ... يا له من جمال ظهر:
نقرأ السطر std :: getline () ، ونزيل المسافات من حواف الخطوط والبقد.
يتبع ... شفرة المصدر - https://github.com/fedor4ever/elf2e32