سؤال

أنا أبحث عن إجابة على غرار الفائض اللطيف على السؤال الأول في منشور المدونة القديم حجم رمز C ++, ، والتي سأكررها أدناه:

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

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

المحلول

يبدو أنه يجب أن يكون هناك شيء كهذا ، لكنني لم أستخدم أي شيء مثله. أستطيع أن أخبرك كيف سأذهب إلى البرمجة النصية معًا. ربما تكون هناك طرق Swifter و/أو أكثر جنسية للقيام بذلك.

أولا بعض الأشياء التي قد تعرفها بالفعل:

يأخذ الأمر AddR2Line في عنوان ويمكنه إخبارك بمكان رمز المصدر الذي ينفذه رمز الجهاز هناك. يجب بناء القابلة للتنفيذ مع رموز تصحيح الأخطاء ، وربما لا ترغب في تحسينه كثيرًا (-O0 أو -O1 أو -OS على الأرجح كما تريد الذهاب في البداية على أي حال). يحتوي AddR2Line على العديد من الأعلام ، وستحتاج إلى قراءة صفحتها اليدوية ، لكنك ستحتاج بالتأكيد إلى استخدام -C أو - -Demangle إذا كنت تريد رؤية أسماء وظائف C ++ التي منطقية في الإخراج.

يمكن لأمر OBJDUMP طباعة جميع أنواع الأشياء المثيرة للاهتمام حول الأشياء في العديد من أنواع ملفات الكائنات. أحد الأشياء التي يمكن أن تفعلها هو طباعة جدول يمثل الرموز في ملف كائن أو يشار إليه (بما في ذلك التنفيذيين).

الآن ، ماذا تريد أن تفعل ذلك:

ما تريده هو أن يخبرك ObjDump بعنوان وحجم قسم النص. هذا هو المكان الذي يعيش فيه رمز الجهاز القابل للتنفيذ الفعلي. هناك عدة طرق للقيام بذلك ، ولكن الأسهل (لهذا ، على أي حال) هو أن تفعل:

objdump -h my_exe | grep text

يجب أن يؤدي ذلك إلى شيء مثل:

 12  .text       0000049  000000f000  0000000f000 00000400  2**4

إذا لم تقم بإعدادها ، فسوف يمنحك عنوانًا مثل:

Idx  Name        Size     VMA         LMA         File off  Algn

أعتقد أن VMA و LMA يجب أن يكونا متماثلين ، لذلك لن يكون من المهم الذي تستخدمه ، لكنني أعتقد أن LMA هي الأفضل. ستحتاج أيضًا إلى الحجم.

مع LMA والحجم ، يمكنك الاتصال مرارًا وتكرارًا بـ AddR2Line لطلب أصل رمز المصدر لرمز الجهاز. لست متأكدًا من كيفية عمل هذا إذا قمت بتمرير عنوان كان ضمن تعليمات واحدة ، لكنني أعتقد أنه يجب أن ينجح.

addr2line -e my_exe <address>

سيكون الإخراج من هذا مسارًا/اسمًا ملفًا ، وقولون ، ورقم خط. إذا كنت تريد حساب حدوث كل مسار/ملف فريد: يجب أن تكون قادرًا على النظر إلى تلك التي لديها أعلى التهم.بيرل تجزئة باستخدام المسار/الملف: NUM كمفتاح وعداد كقيمة ستكون وسيلة سهلة لتنفيذ ذلك ، على الرغم من وجود طرق أسرع إذا وجدت أنها تعمل بطيئة للغاية. يمكنك أيضًا تصفية الأشياء التي يمكنك تحديدها لا تحتاج إلى إدراجها مبكرًا. لعرض الإخراج الخاص بك ، قد ترغب في تصفية خطوط مختلفة من نفس الوظيفة ، ولكن قد تلاحظ أن الخطوط المختلفة داخل وظيفة واحدة لها تعدادات مختلفة ، والتي قد تكون مثيرة للاهتمام. على أي حال ، يمكن القيام بذلك إما عن طريق جعل AddR2Line يخبرك باسم الوظيفة أو استخدام OBJDump -T في الخطوة الأولى وعمل وظيفة واحدة في وقت واحد.

إذا رأيت أن بعض رمز القالب أو خطوط التعليمات البرمجية الأخرى تظهر في التنفيذيين في كثير من الأحيان أكثر مما تعتقد أنه ينبغي عليك تحديد موقعها بسهولة وإلقاء نظرة فاحصة. قد تظهر وحدات الماكرو والوظائف المضمنة في نهاية المطاف إظهار نفسها بشكل مختلف عما تتوقع.

إذا لم تكن تعرف ، فإن OBJDump و Addr2Line من Gnu BinuTils الحزمة ، والتي تتضمن العديد من الأدوات المفيدة الأخرى.

نصائح أخرى

إذا كنت تتطلع إلى العثور على مصادر من الكود في رمز C ++ الخاص بك ، فقد استخدمت "NM" لذلك. سيقوم الأمر التالي بإدراج جميع الرموز في تطبيقك بأكبر رمز وقطع بيانات في الأعلى:

nm --demangle --print-size --size-sort --reverse-sort <executable_or_lib_name> | less

لقد كتبت مؤخرًا أداة ، اللوم, ، وهو ما يفعل شيئًا مشابهًا لماذا اقترح NateGoose.

لا أعرف ما إذا كان ذلك سيساعد ولكن هناك علامة على وحدة تعليم مجلس التعاون الخليجي لكتابة رمز التجميع الذي ينشئه إلى ملف نصي لفحصك.

"يستخدم بدلاً من -C للتسبب في إنشاء ملف مصدر المجمع ، باستخدام .s كملحق ، بدلاً من ملف الكائن. قد يكون هذا مفيدًا إذا كنت بحاجة إلى فحص رمز التجميع الذي تم إنشاؤه. "

في معظم المجمعين C ، هناك طريقة لإنشاء ملف .map. يسرد هذا الملف جميع المكتبات المترجمة عنوانها وحجمها. يمكنك استخدام ملف الخريطة هذا لمساعدتك في تحديد الملفات التي يجب أن تتطلع إلى تحسينها أولاً.

لا أعرف كيفية تعيين الكود-> التجميع الذي تم إنشاؤه بشكل عام.

بالنسبة إلى إنشاءات القالب ، يمكنك استخدام شيء مثل "الأوتار -a | grep | sort -u | gc ++ filt" للحصول على صورة تقريبية لما يتم إنشاؤه.

العنصران الآخران اللتان ذكرتهما يبدوان شخصيًا جدًا. ما هو "الكثير" المضمون؟ هل أنت قلق من تضخيم ملفك الثنائي؟ الشيء الوحيد الذي يجب القيام به هو في الواقع الذهاب إلى GDB وتفكيك المتصل لمعرفة ما الذي تم إنشاؤه ، لا شيء للتحقق من وجود "مفرط" في الإطار بشكل عام.

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

في Visual C ++ ، هذا هو في الأساس ما هي ملفات .pdb ل.

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