Як визначити, чи є бінарний файл ARM ELF з жорстким плаванням (ARMHF) чи з м'яким плаванням (ARMEL)

  • Ключовою підказкою для порівняння ARMHF та ARMEL в ELF є атрибут Tag_ABI_VFP_args.
  • readelf -A відображає інформацію, що залежить від архітектури, включаючи FP, Thumb та NEON.
  • arm-linux-gnueabihf та arm-linux-gnueabi можуть співіснувати через мультиархітекторію, будьте обережні, щоб не переплутати їх.

сервер arm

Під час роботи з виконуваними файлами та бібліотеками для ARM рано чи пізно виникає питання: Він компілюється з жорстким плаванням (ARMHF) чи з м'яким плаванням (ARMEL)? Різниця суттєва, оскільки впливає на сумісність бінарних файлів та продуктивність операцій з плаваючою комою. На щастя, сам бінарний файл ELF містить необхідні підказки для надійного визначення цього.

У цій статті ми розглянемо, як перевірити ARM ELF за допомогою утиліти перечитайте Щоб розрізнити ці два варіанти, ми розглянемо, на які мітки звертати увагу, які відмінності у виході ви можете знайти залежно від версії інструменту, та як інтерпретувати такі деталі, як Thumb або NEON. Ми також обговоримо, чому рішення щодо ARMEL чи ARMHF приймається під час компіляції. не в системі виконанняі ми роз'яснюємо поширені сумніви щодо мультиархівних середовищ, де співіснують arm-linux-gnueabihf та arm-linux-gnueabi.

Що означають ARMHF (жорсткий флоат) та ARMEL (м'який флоат)?

Така поведінка визначена стандартом AAPCS (стандарт виклику процедур архітектури ARM), який описує, як передаються параметри та повертаються значення. AAPCS має варіантиІ той, що нас цікавить для диференціації ARMHF, це той, що пов'язаний з VFP, індикатором, який ми побачимо відображеним в атрибутах бінарного файлу.

ELF та його заголовок: чому він надає нам всю інформацію

ELF (Executable and Linkable Format) є фактичним стандартом у Linux і зберігає дані в розділах заголовка та атрибутів. інформація про цільову архітектуру та ABI-конвенції, що використовуються для компіляції виконуваного файлу або бібліотеки. Якщо вас цікавить вичерпна інформація, просто знайдіть специфікацію заголовка ELF, щоб побачити всі існуючі поля.

Для перевірки ELF інструмент перечитайте Це прямий шлях. Варіант -a перевертає практично все, а варіант -A дозволяє зосередитися на інформації, що залежить від архітектури (ARM у нашому випадку), показуючи такі атрибути, як тип чисел з плаваючою комою, чи ввімкнено Thumb, підтримку NEON та інші відповідні прапорці.

Підготуйте середовище за допомогою ARMEL та ARMHF

Якщо ви хочете порівняти реальний результат, практичним способом є встановлення наборів інструментів gcc/g++ для обох варіантів на машині Ubuntu. Таким чином, Ви отримаєте системні бібліотеки для armel та armhf встановлюються поруч завдяки багатоарочній системі.

Після встановлення типові маршрути бібліотеки такі: /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 не відображатиметьсяНатомість, у файлі ARMHF (hard-float) libm.so.6 буде відображено додатковий рядок із цим атрибутом, що підтверджує використання конвенції викликів 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 що є безпомилковою ознакою твердого поплавця. Саме ця деталь на практиці Це дозволяє нам надійно стверджувати, що бінарний файл відповідає ABI з жорсткою float-числом..

Варіації виводу залежно від версії readelf

Залежно від реалізації та версії readelf, точна форма тексту може відрізнятися. Наприклад, якщо readelf скомпільовано з elftoolchain-0.6.1Додатковий рядок не лише вказує на атрибут, але й може бути описаний як: Tag_ABI_VFP_args: AAPCS (варіант VFP).

У тій самій родині виводів є два інших значення, які можуть з'являтися для Tag_ABI_VFP_args: «AAPCS (базовий варіант)» та «специфічний для інструментарію»У доступній літературі згадуються ці альтернативи, хоча не завжди зрозуміло, за яких саме умов повертається кожна з них. Важливо усвідомити, що згадка про варіант VFP Це пов'язано з корпусом з жорстким поплавком.

Окрім професійної підготовки: -A також викладає архітектуру, Thumb та NEON

Хоча тут ми зосереджуємося на розмежуванні ARMHF та ARMEL, варто пам'ятати, що читати сам -А Він пропонує ширший огляд бінарного файлу. Його вивід покаже, окрім атрибутів чисел з плаваючою комою, точну цільову архітектуру, якщо бінарний файл Він побудований за допомогою Thumb і якщо підтримку було ввімкнено НЕОН, серед інших відповідних можливостей для оптимізації та сумісності.

Все це допомагає перевірити, чи відповідає бінарний файл не лише очікуваному вами варіанту 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 А оскільки цього немає в ARMEL, ви можете вважати різницю перевіреною. А якщо ви бажаєте бачити все, ви завжди можете скористатися читати сам -a для повного дампа заголовків, розділів, атрибутів та символів.

Компіляція, а не система: хто вирішує, ARMEL чи ARMHF

Важливо підкреслити одну концепцію: Варіант ARMEL/ARMHF визначається двійковим кодом.Структуру ELF-файлу визначає процес компіляції, а не абстрактна «система». Якщо ви скомпілюєте виконуваний файл з підтримкою hard-float, ви отримаєте ARMHF ELF; інакше це буде ARMEL. Ця відмінність випливає з процесу збірки та жорстко закодована в атрибутах ELF.

З цієї причини, якщо вас турбує рішення про те, яким шляхом піти у власному проєкті, зазвичай це простіше. вирішити це під час компіляції з опціями компілятора та лінкера, а також з кодом, обумовленим препроцесором. Нечасто виникає бажання перемикатися між ARMEL та ARMHF в одному бінарному файлі під час виконання. оскільки це стосується різних ABI.

Заголовки, згенеровані Makefile: практичний прийом

Якщо ви хочете, щоб сам виконуваний файл оголошував свою "ідентичність" під час збірки, дуже корисним методом є генерація заголовок з Makefile Під час фази збірки система збірки визначає, чи компілюєте ви для armel чи armhf, і записує константу у заголовковий файл, який потім включається до вихідного коду.

За такого підходу кінцевий бінарний файл може містити, наприклад, команду -версію який виводить, чи було воно побудовано як ARMEL чи ARMHF, без необхідності "виявляти" щось під час виконання. Загалом, ця практика краще відповідає тому факту, що ABI встановлюється під час компіляції і вона не повинна змінюватися динамічно.

Навіщо вам це знати під час виконання?

Ті, хто ставлять це питання, іноді намагаються адаптувати свою поведінку в розпал моменту. Але реальність така, що Звичайна практика полягає в розділенні коду за допомогою директив препроцесора та скомпілювати різні варіанти, один для armel, а інший для armhf. Змішування обох в одному артефакті нереалістичне, оскільки кожен залежить від власного набору бібліотек та інший ABI.

Отже, загальна рекомендація полягає в тому, щоб прийняти рішення перед компіляцієюі під час виконання просто перевірте, чи цільове середовище має відповідні бібліотеки для бінарного файлу, який ви збираєтеся запустити. Щоб виконати аудит вже зібраного бінарного файлу, перечитайте Він залишається найпрямішим інструментом.

Мультиархітектор: Чому у вас є і arm-linux-gnueabihf, і arm-linux-gnueabi

Якщо під час перерахування каталогів у вашій системі ви бачите, що у вас є arm-linux-gnueabihf та arm-linux-gnueabi співіснування не обов'язково є помилкою: це багатоарковийЦе дозволяє встановлювати та використовувати кілька архітектур або варіантів ABI паралельно, що спрощує крос-компіляції та тестування.

Наприклад, у середовищах Debian були випадки, коли вирішувалося Видалити мультиархів у стандартних образах Wheezy тому що підтримка була «зеленою» та спричиняла більше проблем, ніж користі. Згодом, Покращена підтримка Jessie та пізніших версій багатоархівність, що робить співіснування armel/armhf більш життєздатним без численних головних болів.

Правильної інтерпретації маршрутів недостатньо

Знаходження бібліотеки в /usr/arm-linux-gnueabihf/lib говорить про ARMHF, і те саме стосується /usr/arm-linux-gnueabi/lib для ARMEL. Але якщо ви хочете бути впевненими, Відкрийте ELF та перегляньте його атрибутиШляхи корисні як орієнтир, хоча в складних системах з кількома архівами або ручним резервним копіюванням, може ввести в оману.

Знову ж таки, вихід з читати сам -А Це надає переконливий доказ: наявність Tag_ABI_VFP_args для hard-float та його відсутність для soft-float. Крім того, інші прапорці підтвердять це. інструкції та розширення що може вимагати бінарний файл.

Чого ще можна навчитися з -A, окрім FP

Розділ атрибутів ARM, у якому показано -A, не лише повідомляє вам про наявність VFP. Він також повідомляє вам, чи є бінарний файл Позначено як «Мініатюра», варіант архітектури (наприклад, ARMv7) та чи є підтримка НЕОНЦі відомості допоможуть вам перевірити сумісність бінарного файлу з цільовим обладнанням і запобігти несподіванкам під час розгортання.

Розглянемо, наприклад, перевірку середовища виконання: разом із перевіркою ARMEL проти ARMHF, Великий палець і NEON Це може попередити вас про ледь помітні несумісності, які не видно на перший погляд.

Часті запитання та короткі поради

  • Чи можу я виявити це без readelf? Технічно, ви можете зробити висновок про це зі шляху або того, як був зібраний ваш власний проєкт, але надійний метод — перевірити ELF-файл. `readelf -A` надає докази в самому бінарному файлі.
  • Чи достатньо побачити на виході "VFP"? Загальні посилання на VFP вказують на можливості, але вирішальним є Аргументи_тегу_ABI_VFP в ARMHF. Його відсутність в ARMEL є не менш важливою.
  • Що робити, якщо мій читач каже «AAPCS (варіант VFP)»? Це альтернативна форма тієї ж ідеї, яку можна побачити в певних збірках, таких як ті, що базуються на elftoolchain-0.6.1Також може з'являтися «AAPCS (базовий варіант)» або «специфічний для інструментарію».
  • Чому у мене встановлено обидві версії? За багатоарковийЦе нормально в деяких середовищах. Просто переконайтеся, що ви компонуєте та запускаєте з набором бібліотек, який відповідає бінарному файлу, який ви використовуєте.

Коротка примітка про джерела та їх фінансування

Деякі технічні публікації, що стосуються цих тем, містять повідомлення для підтримати їхню роботу через пожертви у криптовалюті, платформи, такі як Patreon, або партнерські посилання на магазини, такі як Amazon чи AliExpress. Це поширена практика в незалежних ЗМІ, які іноді Вони використовують партнерські посилання у своїх статтях, щоб отримати комісію, якщо ви здійсните покупку після кліку.

Ментальний контрольний список під час аудиту бінарних файлів

Перш ніж прийняти бібліотеку або виконуваний файл для вашого пристрою, перегляньте ці пункти: запит readelf -A, шукає наявність або відсутність Аргументи_тегу_ABI_VFPПерегляньте цільову архітектуру та перевірте, чи підходять Thumb та NEON до обладнання, на якому ви збираєтеся її запускати.

Якщо ви працюєте з кількома ланцюжками інструментів, встановленими через мультиархітекторію, Зверніть особливу увагу на маршрути Змінні середовища компілятора та компонувальника мають бути налаштовані таким чином, щоб уникнути змішування заголовкових файлів та бібліотек ARMEL з бінарними файлами ARMHF або навпаки. Невеликий недогляд може спричинити проблеми. незрозумілі симптоми під час компонування або виконання.

Типові помилки, яких слід уникати

Класична помилка — бути надмірно впевненим і вважати, що бібліотека є жорстко-плаваючою, оскільки вона розташована під arm-linux-gnueabihf, без підтвердження атрибутів ELFЩе однією поширеною помилкою є спроба зв'язати виконуваний файл ARMHF з бібліотеками ARMEL (або навпаки), що зазвичай призводить до помилок символів або дивної поведінки.

Також часто виникає бажання "виявляти під час виконання", щоб змінювати шляхи бібліотек на льоту. Пам'ятайте, що Вибір ARMEL/ARMHF не імпровізується під час виконанняЦе жорстко закодовано у двійковому файлі. Налаштуйте свої розгортання та пакети так, щоб кожен виконуваний файл отримував бібліотеки для свого власного варіанту.

Якщо вам потрібна швидка довідка, подумайте про такі кроки: знайдіть бібліотеку або виконуваний файл (наприклад, libm.so.6), запустити readelf -A Якщо хочете одразу перейти до суті файлу, відфільтруйте його за FP та перевірте, чи є рядок. Аргументи_тегу_ABI_VFP (жорстке число з плаваючою точкою) або, якщо відсутнє (м'яке число з плаваючою точкою). Потім перевірте архітектуру, Thumb та NEON, щоб завершити бінарний профіль.

При порівнянні ARMEL та ARMHF в одній системі, пам'ятайте про мультиархітекторський контекст І той факт, що ключова відмінність полягає в ABI з плаваючою комою, визначеному AAPCS. З цієї точки зору, інтерпретація атрибутів readelf стає швидкою та точною вправою.

Зрозуміло, що за наявності правильного інструменту та знання того, де шукати, Визначення того, чи є ARM ELF ARMHF чи ARMEL, є питанням секунд.Ключовим є визначення атрибута Tag_ABI_VFP_args для hard-float та використання readelf -A для отримання додаткового контексту щодо архітектури, Thumb та NEON. Беручи до уваги особливості мультиархітекторної структури та те, що вибір ABI фіксується під час компіляції, Ви уникнете плутанини та заощадите час під час перевірки бінарних файлів та бібліотек у ваших проектах.

Що таке ARM Cortex-R та Cortex-M?
Пов'язана стаття:
ARM Cortex-R та Cortex-M: що це таке, відмінності та коли обрати кожен з них