كيفية اكتشاف ما إذا كان ثنائي ARM ELF عائمًا صلبًا (ARMHF) أو عائمًا ناعمًا (ARMEL)

  • الدليل الرئيسي لـ ARMHF مقابل ARMEL في ELF هو سمة Tag_ABI_VFP_args.
  • يعرض readelf -A معلومات تعتمد على الهندسة المعمارية، بما في ذلك FP، وThumb، وNEON.
  • يمكن أن يتعايش arm-linux-gnueabihf وarm-linux-gnueabi عبر multiarch، لذا كن حذرًا حتى لا تخلط بينهما.

خادم الذراع

عند العمل مع الملفات القابلة للتنفيذ والمكتبات الخاصة بـ ARM، يطرح السؤال عاجلاً أم آجلاً: هل تم تجميعه باستخدام التعويم الصلب (ARMHF) أو باستخدام التعويم الناعم (ARMEL)؟ الفرق كبير، إذ يؤثر على توافقية الثنائيات وأدائها في عمليات الفاصلة العائمة. لحسن الحظ، يحتوي ثنائي ELF نفسه على الأدلة اللازمة لتحديد ذلك بدقة.

في هذه المقالة نستعرض كيفية فحص ARM ELF باستخدام الأداة المساعدة اقرأ نفسك للتمييز بين الإصدارين، سنتناول التسميات التي يجب البحث عنها، واختلافات الإخراج التي قد تجدها حسب إصدار الأداة، وكيفية تفسير تفاصيل مثل Thumb أو NEON. سنناقش أيضًا سبب اتخاذ قرار ARMEL مقابل ARMHF أثناء التجميع. ليس في نظام وقت التشغيلونقوم بتوضيح الشكوك الشائعة حول بيئات multiarch حيث يتعايش arm-linux-gnueabihf وarm-linux-gnueabi.

ماذا يعني ARMHF (التعويم الصلب) و ARMEL (التعويم الناعم)؟

يتم تعريف هذا السلوك بواسطة AAPCS (معيار استدعاء إجراء هندسة ARM)، والذي يصف كيفية تمرير المعلمات وإرجاع القيم. لدى AAPCS متغيراتوالذي يهمنا التمييز بين ARMHF هو المرتبط بـ VFP، وهو مؤشر سنراه ينعكس في سمات الثنائي.

ELF وعنوانه: لماذا يمنحنا كل المعلومات

ELF (تنسيق قابل للتنفيذ والربط) هو المعيار الفعلي في Linux ويخزن البيانات في أقسام الرأس والسمات الخاصة به. معلومات حول الهندسة المعمارية المستهدفة واتفاقيات ABI المستخدمة لتجميع الملف التنفيذي أو المكتبة. إذا كنت مهتمًا بتفاصيل شاملة، فما عليك سوى البحث في مواصفات رأس ELF للاطلاع على جميع الحقول الموجودة.

لتفقد ELF، الأداة اقرأ نفسك إنه الطريق المباشر. الخيار -أ يقلب كل شيء تقريبًا، والخيار -أ يسمح التركيز على المعلومات المعتمدة على الهندسة المعمارية (ARM في حالتنا)، مع عرض سمات مثل نوع النقطة العائمة، وما إذا كان Thumb ممكّنًا، ودعم NEON، والأعلام الأخرى ذات الصلة.

إعداد البيئة مع ARMEL و ARMHF

إذا كنت ترغب في مقارنة النتائج الفعلية، فإن الطريقة العملية هي تثبيت سلاسل أدوات gcc/g++ لكلا الإصدارين على جهاز Ubuntu. بهذه الطريقة، ستحصل على مكتبات النظام لـ armel و armhf تم تثبيتهما جنبًا إلى جنب بفضل multiarch.

بعد التثبيت، مسارات المكتبة النموذجية هي: /usr/arm-linux-gnueabihf/lib لـ ARMHF y /usr/arm-linux-gnueabi/lib لـ ARMELيتيح لك وجود كليهما مقارنة مكتبة الرياضيات libm.so.6 على سبيل المثال وملاحظة كيفية تغير السمات اعتمادًا على المتغير.

الدليل النهائي: Tag_ABI_VFP_args مع readelf

يتضمن الاختبار العملي تحليل ELF باستخدام readelf والبحث عن مراجع لـ FP في السمات. هناك طريقة بسيطة جدًا تتمثل في تصفية الناتج حسب السلسلة FP للتركيز على الأعداد العشرية. نظرًا لأن المؤشر الأكثر كشفًا هو سمة Tag_ABI_VFP_args.

في مكتبة libm.so.6 المترجمة كـ ARMEL (soft-float)، ستشاهد سمات ARM النموذجية، ولكن لن يظهر السطر Tag_ABI_VFP_argsعلى النقيض من ذلك، في ملف libm.so.6 ARMHF (hard-float)، سيتم عرض سطر إضافي بهذه السمة، مما يؤكد استخدام اتفاقية استدعاء VFP.

readelf -A /usr/arm-linux-gnueabi/lib/libm.so.6 | grep FP

في ARMEL، سيؤدي التصفية حسب FP إلى عرض معلومات تتعلق بإمكانيات الفاصلة العائمة العامة، ولكن بدون السمة التي تعلن عن وسيطات VFPعند تكرار ذلك على ARMHF:

readelf -A /usr/arm-linux-gnueabihf/lib/libm.so.6 | grep FP

ستجد إدخالاً إضافيًا من النوع علامة_ABI_VFP_args وهي علامة واضحة على وجود تعويم صلب. هذه التفاصيل هي ما يُفهم عمليًا يسمح لنا هذا بالتصريح بشكل موثوق بأن الثنائي يتبع ABI hard-float.

اختلافات الإخراج اعتمادًا على الإصدار نفسه

بناءً على تطبيق وإصدار readelf، قد يختلف الشكل الدقيق للنص. على سبيل المثال، مع readelf المُجمّع من elftoolchain-0.6.1لا يشير السطر الإضافي إلى السمة فحسب، بل يمكن وصفه أيضًا على النحو التالي: Tag_ABI_VFP_args: AAPCS (متغير VFP).

في نفس عائلة المخرجات، هناك قيمتان أخريان قد تظهران لـTag_ABI_VFP_args: "AAPCS (المتغير الأساسي)" و"محدد لسلسلة الأدوات"تشير الأدبيات المتاحة إلى هذه البدائل، مع أنه ليس من الواضح دائمًا الشروط الدقيقة لإعادة كل منها. المهم هو إدراك أن ذكر متغير VFP فهو مرتبط بحالة التعويم الصلبة.

ما وراء التدريب المهني: -يقوم أيضًا بتدريس الهندسة المعمارية، والإبهام، والنيون

على الرغم من أننا نركز هنا على التمييز بين ARMHF وARMEL، فمن الجدير أن نتذكر أن readelf -A يُتيح رؤية أوسع للثنائي. سيُظهر مُخرجه، بالإضافة إلى سمات الفاصلة العائمة، بنية الهدف الدقيقة، إذا كان الثنائي تم بناؤه باستخدام الإبهام وإذا تم تمكين الدعم نيون، من بين القدرات الأخرى ذات الصلة بالتحسين والتوافق.

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

مثال على سير العمل الموصى به

يمكن أن يكون التسلسل النموذجي لمقارنة كلا المتغيرين من libm.so.6 بسيطًا مثل هذا: قائمة الطرق، وتشغيل readelf، والتصفية حسب FPسيمنحك هذا الفرق الرئيسي بين armel و armhf في لمحة.

# ARMEL (soft-float)
ls -l /usr/arm-linux-gnueabi/lib/libm.so.6
readelf -A /usr/arm-linux-gnueabi/lib/libm.so.6 | grep FP

# ARMHF (hard-float)
ls -l /usr/arm-linux-gnueabihf/lib/libm.so.6
readelf -A /usr/arm-linux-gnueabihf/lib/libm.so.6 | grep FP

إذا لاحظت الخط مع ARMHF علامة_ABI_VFP_args وبما أنه لا يظهر في ARMEL، يمكنك اعتبار الفرق مؤكدًا. وإذا كنت تفضل رؤية كل شيء، يمكنك دائمًا استخدام readelf -a للحصول على نسخة كاملة من العناوين والأقسام والسمات والرموز.

التجميع وليس النظام: من يقرر ARMEL أو ARMHF

ومن المهم التأكيد على مفهوم واحد: يتم تحديد متغير ARMEL/ARMHF بواسطة الكود الثنائي.إن عملية التجميع هي التي تحدد بنية ملف ELF، وليس "النظام" المجرد. إذا جمّعتَ ملفك التنفيذي مع دعم التعويم الثابت، فستحصل على ملف ELF بصيغة ARMHF؛ وإلا، فسيكون ARMEL. ينبع هذا التمييز من عملية البناء، وهو مُضمّن في سمات ملف ELF.

ولهذا السبب، إذا كان ما يقلقك هو تحديد المسار الذي ستتخذه في مشروعك الخاص، فعادةً ما يكون الأمر أبسط. حلها في وقت التجميع مع خيارات المُجمِّع والرابط، ومع شيفرة مُعَدَّة مسبقًا للمعالج. ليس من الشائع التبديل بين ARMEL وARMHF في نفس الملف الثنائي أثناء التشغيل. لأنه ينطوي على ABIs مختلفة.

العناوين التي تم إنشاؤها بواسطة Makefile: تقنية عملية

إذا كنت تريد أن يعلن الملف القابل للتنفيذ نفسه عن "هويته" في وقت البناء، فإن إحدى التقنيات المفيدة للغاية هي إنشاء رأس من ملف Makefile أثناء مرحلة البناء، يكتشف نظام البناء ما إذا كنت تقوم بالتجميع لـ armel أو armhf وينقل ثابتًا إلى ملف رأس، والذي يتم تضمينه بعد ذلك في الكود المصدر.

باستخدام هذا النهج، يمكن للثنائي النهائي أن يعرض، على سبيل المثال، أمرًا -الإصدار يطبع ما إذا كان مُصممًا بصيغة ARMEL أو ARMHF، دون الحاجة إلى "اكتشاف" أي شيء أثناء التشغيل. بشكل عام، تتوافق هذه الممارسة بشكل أفضل مع حقيقة أن يتم تعيين ABI عند التجميع ولا ينبغي أن يتغير ديناميكيًا.

لماذا تريد معرفة ذلك وقت التشغيل؟

من يطرح هذا السؤال يحاول أحيانًا تعديل سلوكه في خضم اللحظة. لكن الحقيقة هي أن الممارسة المعتادة هي فصل الكود باستخدام توجيهات المعالج المسبق وجمع نسخ مختلفة، نسخة لـ armel ونسخة أخرى لـ armhf. دمج النسختين في قطعة أثرية واحدة ليس واقعيًا، لأن كل واحد يعتمد على مجموعة خاصة به من المكتبات و ABI مختلفة.

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

Multiarch: لماذا لديك كل من arm-linux-gnueabihf وarm-linux-gnueabi

إذا لاحظت عند إدراج الدلائل على نظامك أن لديك arm-linux-gnueabihf و arm-linux-gnueabi التعايش ليس بالضرورة خطأ: هذا هو متعدد الأقواسإنه يسمح لك بتثبيت واستخدام العديد من المعماريات أو متغيرات ABI بالتوازي، مما يسهل عمليات التجميع والاختبار المتبادلة.

في بيئات Debian، على سبيل المثال، كانت هناك أوقات تم فيها اتخاذ القرار إزالة multiarch في صور Wheezy الافتراضية لأن الدعم كان أخضرًا، وتسبب في مشاكل أكثر من فوائده. تم تحسين الدعم لـ Jessie والإصدارات الأحدث multiarch، مما يجعل التعايش بين armel/armhf أكثر قابلية للتطبيق دون الكثير من الصداع.

إن تفسير المسارات بشكل صحيح ليس كافياً

رؤية مكتبة في /usr/arm-linux-gnueabihf/lib تشير إلى أنها ARMHF، والأمر نفسه ينطبق على /usr/arm-linux-gnueabi/lib لـ ARMEL. ولكن للتأكد، افتح ملف ELF وانظر إلى خصائصهتُعد المسارات مفيدة كدليل، على الرغم من أنه في الأنظمة المعقدة ذات الأرشيفات المتعددة أو النسخ الاحتياطية اليدوية، يمكن أن تضلل.

مرة أخرى، خروج readelf -A يُقدّم هذا دليلاً قاطعاً: وجود Tag_ABI_VFP_args للترقيم الثابت، وغيابه للترقيم الناعم. علاوةً على ذلك، ستُؤكّد العلامات الأخرى ذلك. التعليمات والإضافات أن الثنائي قد يتطلب ذلك.

ماذا يمكنك أن تتعلم أيضًا من -A، إلى جانب FP؟

قسم سمات ARM الذي يعرض -A لا يُخبرك فقط بوجود VFP، بل يُخبرك أيضًا بوجود الملف الثنائي تم وضع علامة عليه كإبهام، متغير الهندسة المعمارية (على سبيل المثال، ARMv7)، وما إذا كان هناك دعم نيونتساعدك هذه التفاصيل على التحقق من توافق الملف الثنائي مع الأجهزة المستهدفة ومنع المفاجآت أثناء النشر.

على سبيل المثال، خذ في الاعتبار التحقق من صحة بيئة وقت التشغيل: جنبًا إلى جنب مع التحقق من ARMEL مقابل ARMHF، تحقق من الإبهام والنيون يمكنه تنبيهك إلى حالات عدم التوافق الدقيقة التي لا يمكن رؤيتها للوهلة الأولى.

الأسئلة الشائعة والنصائح السريعة

  • هل يمكنني اكتشافه بدون readelf؟ من الناحية الفنية، يمكنك استنتاج ذلك من المسار أو كيفية بناء مشروعك الخاص، ولكن الطريقة الموثوقة هي فحص ملف ELF. يوفر الأمر `readelf -A` الدليل داخل الملف الثنائي نفسه.
  • هل يكفي رؤية "VFP" عند الخروج؟ إن رؤية المراجع العامة لـ VFP تشير إلى القدرات، ولكن الخط الحاسم هو علامة_ABI_VFP_args في ARMHF. غيابه في ARMEL مهم بنفس القدر.
  • ماذا لو كان قارئي يقول "AAPCS (متغير VFP)"؟ إنه شكل بديل لنفس الفكرة التي نراها في بعض الإصدارات، مثل تلك المستندة إلى elftoolchain-0.6.1قد يظهر أيضًا "AAPCS (المتغير الأساسي)" أو "سلسلة الأدوات المحددة".
  • لماذا قمت بتثبيت كلا الإصدارين؟ من قبل متعدد الأقواسهذا أمر طبيعي في بعض البيئات. فقط تأكد من ربط وتشغيل مجموعة المكتبة التي تتوافق مع الملف الثنائي الذي تستخدمه.

ملاحظة موجزة عن المصادر وتمويلها

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

قائمة التحقق الذهنية عند تدقيق ثنائي

قبل قبول مكتبة أو ملف قابل للتنفيذ لجهازك، راجع النقاط التالية: استعلام القراءة الذاتية -A، يبحث عن وجود أو غياب علامة_ABI_VFP_argsقم بإلقاء نظرة على بنية الهدف، وتحقق مما إذا كان Thumb وNEON يتناسبان مع الأجهزة التي ستعمل عليها.

إذا كنت تعمل مع سلاسل أدوات متعددة مثبتة عبر multiarch، إنتبه بشكل خاص إلى الطرق يجب تهيئة متغيرات بيئة المُجمِّع والرابط لتجنب خلط عناوين ومكتبات ARMEL مع ثنائيات ARMHF، أو العكس. قد يُسبب أي إهمال بسيط مشاكل. أعراض مربكة في وقت الارتباط أو وقت التشغيل.

الأخطاء الشائعة التي يجب تجنبها

إن الخطأ الكلاسيكي هو أن تكون واثقًا جدًا وتفترض أن المكتبة عائمة تمامًا لأنها تقع تحت arm-linux-gnueabihf، دون تأكيد سمات ELFهناك خطأ شائع آخر وهو محاولة ربط ملف ARMHF القابل للتنفيذ بمكتبات ARMEL (أو العكس)، وهو ما يؤدي عادةً إلى فشل الرموز أو سلوك غريب.

من الشائع أيضًا الرغبة في "الكشف أثناء التشغيل" لتغيير مسارات المكتبة تلقائيًا. تذكر أن لا يتم ارتجال اختيار ARMEL/ARMHF في وقت التشغيلإنه مُدمج في الملف الثنائي. عدّل عمليات النشر والحزم لديك بحيث يتلقى كل ملف قابل للتنفيذ المكتبات الخاصة بنسخته الخاصة.

إذا كنت بحاجة إلى مرجع سريع، ففكر في الخطوات التالية: حدد موقع المكتبة أو الملف القابل للتنفيذ (على سبيل المثال، libm.so.6)، إطلاق readelf -A مقابل الملف، قم بالتصفية حسب FP إذا كنت تريد الوصول إلى النقطة مباشرة، وتحقق مما إذا كان هناك خط علامة_ABI_VFP_args (عائم ثابت) أو في حال عدم وجوده (عائم ناعم). بعد ذلك، تحقق من البنية، وThumb، وNEON لإكمال الملف الثنائي.

عند مقارنة ARMEL و ARMHF في نفس النظام، تذكر سياق التعدد المعماري يكمن الاختلاف الرئيسي في واجهة برمجة التطبيقات الثنائية (ABI) ذات الفاصلة العائمة المُعرّفة من قِبل AAPCS. من هذا المنظور، يُصبح تفسير سمات readelf عملية سريعة ودقيقة.

من الواضح أنه باستخدام الأداة المناسبة ومعرفة المكان الذي يجب البحث فيه، إن تحديد ما إذا كان ARM ELF هو ARMHF أو ARMEL هو مسألة ثوانٍالمفتاح هو تحديد سمة Tag_ABI_VFP_args للترميز الثابت، والاستفادة من الأمر readelf -A للحصول على سياق إضافي حول البنية، وThumb، وNEON. مع مراعاة خصوصيات بنية multiarch، وأن اختيار ABI ثابت عند التجميع، ستتجنب الارتباك وتوفر الوقت عند التحقق من صحة الثنائيات والمكتبات في مشاريعك.

ما هما ARM Cortex-R و Cortex-M؟
المادة ذات الصلة:
ARM Cortex-R وCortex-M: ما هما، والاختلافات بينهما، ومتى يجب اختيار كل منهما