Cómo detectar si un binario ARM ELF es hard-float (ARMHF) o soft-float (ARMEL)

  • La pista clave para ARMHF frente a ARMEL en ELF es el atributo Tag_ABI_VFP_args.
  • readelf -A muestra información dependiente de arquitectura, incluidos FP, Thumb y NEON.
  • arm-linux-gnueabihf y arm-linux-gnueabi pueden coexistir por multiarch, ojo con confusiones.

arm server

Cuando trabajas con ejecutables y bibliotecas para ARM, tarde o temprano surge la duda: ¿está compilado con hard-float (ARMHF) o con soft-float (ARMEL)? La diferencia no es menor, porque afecta a la compatibilidad de binarios y al rendimiento en operaciones de coma flotante. Por suerte, el propio binario ELF contiene las pistas necesarias para averiguarlo de forma fiable.

En este artículo repasamos cómo inspeccionar un ELF de ARM con la utilidad readelf para distinguir ambas variantes, qué etiquetas mirar, qué diferencias de salida puedes encontrar según la versión de la herramienta y cómo interpretar detalles como Thumb o NEON. Además, comentamos por qué la decisión ARMEL vs ARMHF se toma en la compilación, no en el sistema en tiempo de ejecución, y aclaramos dudas comunes sobre entornos con multiarch donde conviven arm-linux-gnueabihf y arm-linux-gnueabi.

Qué significan ARMHF (hard-float) y ARMEL (soft-float)

Este comportamiento está definido por la AAPCS (ARM Architecture Procedure Call Standard), que describe cómo se pasan parámetros y se devuelven valores. La AAPCS cuenta con variantes, y la que nos interesa para diferenciar ARMHF es la asociada a VFP, indicador que veremos reflejado en los atributos del binario.

ELF y su cabecera: por qué nos da toda la información

El formato ELF (Executable and Linkable Format) es el estándar de facto en Linux y guarda en su cabecera y secciones de atributos información sobre la arquitectura objetivo y convenciones ABI utilizadas para compilar el ejecutable o la biblioteca. Si te interesa el detalle exhaustivo, basta con buscar la especificación del encabezado ELF para ver todos los campos que existen.

Para inspeccionar un ELF, la herramienta readelf es la vía directa. La opción -a vuelca prácticamente todo, y la opción -A permite centrarse en la información dependiente de la arquitectura (ARM en nuestro caso), mostrando atributos como el tipo de coma flotante, si se ha habilitado Thumb, soporte NEON, y otras banderas relevantes.

Preparar un entorno con ARMEL y ARMHF

Si quieres comparar salidas reales, una manera práctica es instalar en una máquina Ubuntu los toolchains de gcc/g++ para ambas variantes. Al hacerlo, obtendrás bibliotecas de sistema para armel y armhf instaladas lado a lado gracias a multiarch.

Tras la instalación, las rutas típicas de las bibliotecas son: /usr/arm-linux-gnueabihf/lib para ARMHF y /usr/arm-linux-gnueabi/lib para ARMEL. Tener ambas te permite contrastar, por ejemplo, la biblioteca matemática libm.so.6 y observar cómo cambian los atributos en función de la variante.

La pista definitiva: Tag_ABI_VFP_args con readelf

La comprobación práctica consiste en analizar el ELF con readelf y buscar referencias a FP en los atributos. Una táctica muy directa es filtrar la salida por la cadena FP para centrarte en los puntos flotantes, ya que el indicador más esclarecedor es el atributo Tag_ABI_VFP_args.

En la biblioteca libm.so.6 compilada como ARMEL (soft-float), verás los atributos típicos de ARM, pero no aparecerá la línea Tag_ABI_VFP_args. En cambio, en la libm.so.6 de ARMHF (hard-float) se mostrará una línea adicional con ese atributo que confirma el uso de la convención de llamadas de VFP.

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

En ARMEL, el filtrado por FP mostrará información relacionada con capacidades de coma flotante generales, pero sin el atributo que declara argumentos VFP. Al repetirlo sobre ARMHF:

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

Encontrarás una entrada adicional del tipo Tag_ABI_VFP_args que es la señal inequívoca de hard-float. Este detalle es el que, en la práctica, nos permite afirmar de forma fiable que el binario sigue la ABI hard-float.

Variaciones de salida según la versión de readelf

Según la implementación y versión de readelf, la forma exacta del texto puede variar. Por ejemplo, con readelf compilado a partir de elftoolchain-0.6.1, la línea adicional no solo indica el atributo, sino que puede describirse como: Tag_ABI_VFP_args: AAPCS (VFP variant).

En esa misma familia de salidas, hay otros dos valores que te pueden aparecer para Tag_ABI_VFP_args: «AAPCS (base variant)» y «toolchain-specific». La literatura disponible menciona estas alternativas, si bien no siempre queda claro en qué condiciones exactas se devuelven cada una de ellas. Lo importante es reconocer que la mención a la variante VFP está asociada al caso hard-float.

Más allá del FP: -A también enseña arquitectura, Thumb y NEON

Aunque aquí nos centramos en distinguir ARMHF y ARMEL, conviene recordar que readelf -A ofrece una panorámica más amplia del binario. En su salida podrás ver, además de atributos de punto flotante, la arquitectura destino exacta, si el binario está construido con Thumb y si se ha habilitado soporte NEON, entre otras capacidades relevantes para optimización y compatibilidad.

Todo eso ayuda a validar que el binario no solo corresponde a la variante de FP que esperas, sino que está alineado con el conjunto de instrucciones y extensiones que tienes disponibles en el dispositivo donde se ejecutará.

Ejemplo de flujo de trabajo recomendado

Una secuencia típica para cotejar ambas variantes de libm.so.6 podría ser tan simple como esta: listar rutas, ejecutar readelf y filtrar por FP. Con ello obtendrás la diferencia clave entre armel y armhf de un vistazo.

# 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

Si en ARMHF observas la línea con Tag_ABI_VFP_args y en ARMEL no aparece, puedes dar por verificada la diferencia. Y si prefieres ver todo, siempre puedes usar readelf -a para un volcado completo de cabeceras, secciones, atributos y símbolos.

Compilación, no sistema: quién decide ARMEL o ARMHF

Es importante subrayar un concepto: la variante ARMEL/ARMHF la determina el binario, por cómo se ha compilado, no «el sistema» en abstracto. Si compilas tu ejecutable con soporte hard-float, obtendrás un ELF de ARMHF; si no, será ARMEL. Esta distinción se arrastra desde el proceso de construcción y está codificada en los atributos del ELF.

Por ese motivo, si lo que te preocupa es decidir qué camino tomar en tu propio proyecto, suele ser más sencillo resolverlo en tiempo de compilación con opciones del compilador y del enlazador, y con código condicionado por preprocesador. No es habitual querer conmutar entre ARMEL y ARMHF en el mismo binario en tiempo de ejecución, porque implica ABIs distintas.

Cabeceras generadas por el Makefile: una técnica práctica

Si te interesa que el propio ejecutable declare su «identidad» en tiempo de construcción, una técnica muy útil es generar una cabecera desde el Makefile en la fase de build. El sistema de construcción detecta si estás compilando para armel o armhf y vuelca una constante a un fichero de cabecera que luego se incluye en el código fuente.

Con ese enfoque, el binario final puede exponer, por ejemplo, un comando –version que imprima si fue construido como ARMEL o ARMHF, sin necesidad de «detectar» nada en ejecución. En general, esta práctica encaja mejor con el hecho de que el ABI se fija al compilar y no debe variar dinámicamente.

¿Por qué querrías saberlo en tiempo de ejecución?

Quienes plantean esta pregunta a veces buscan adaptar el comportamiento en caliente. Pero la realidad es que lo habitual es separar el código con directivas del preprocesador y compilar variantes distintas, una para armel y otra para armhf. Mezclar ambas en un mismo artefacto no es realista, porque cada una depende de su propio conjunto de bibliotecas y de una ABI diferente.

De ahí que la recomendación general sea tomar la decisión antes de compilar, y en tiempo de ejecución limitarse a validar que el entorno de destino tiene las bibliotecas adecuadas para el binario que vas a lanzar. Para auditar un binario ya construido, readelf sigue siendo la herramienta más directa.

Multiarch: por qué tienes arm-linux-gnueabihf y arm-linux-gnueabi a la vez

Si al listar directorios en tu sistema ves que tienes arm-linux-gnueabihf y arm-linux-gnueabi coexistiendo, no es necesariamente un error: eso es multiarch. Permite instalar y usar múltiples arquitecturas o variantes ABI en paralelo, facilitando compilaciones cruzadas y pruebas.

En entornos Debian, por ejemplo, hubo momentos en los que se decidió retirar multiarch en imágenes por defecto de wheezy porque el soporte estaba verde y causaba más problemas que beneficios. Posteriormente, Jessie y versiones posteriores mejoraron el soporte multiarch, haciendo más viable la coexistencia armel/armhf sin tantos dolores de cabeza.

Interpretar bien las rutas no es suficiente

Ver una biblioteca en /usr/arm-linux-gnueabihf/lib sugiere que es ARMHF, y lo mismo con /usr/arm-linux-gnueabi/lib para ARMEL. Pero si quieres estar seguro, abre el ELF y mira sus atributos. Las rutas ayudan como guía, aunque en sistemas complejos con multiarch o con copias manuales, pueden inducir a error.

De nuevo, la salida de readelf -A aporta la prueba concluyente: presencia de Tag_ABI_VFP_args para hard-float, y su ausencia en soft-float. Además, el resto de flags te corroborarán instrucciones y extensiones que puede requerir el binario.

Qué más puedes aprender de -A, además del FP

La sección de atributos de ARM que muestra -A no solo te cuenta si hay VFP. También te dice si el binario está marcado como Thumb, la variante de arquitectura (por ejemplo, ARMv7), y si hay soporte NEON. Estos detalles te ayudan a corroborar que el binario es compatible con el hardware objetivo y evitan sorpresas al desplegar.

Piensa, por ejemplo, en validar un entorno de ejecución: junto con la verificación de ARMEL vs ARMHF, comprobar Thumb y NEON puede avisarte de incompatibilidades sutiles que no se ven a simple vista.

Preguntas frecuentes y consejos rápidos

  • ¿Puedo detectarlo sin readelf? Técnicamente, podrías inferirlo por la ruta o por cómo fue construido tu propio proyecto, pero el método sólido es inspeccionar el ELF. readelf -A ofrece la evidencia dentro del propio binario.
  • ¿Basta con ver «VFP» en la salida? Ver referencias generales a VFP indica capacidades, pero la línea decisiva es Tag_ABI_VFP_args en ARMHF. Su ausencia en ARMEL es igual de significativa.
  • ¿Y si mi readelf dice «AAPCS (VFP variant)»? Es una forma alternativa de la misma idea vista en ciertas builds, como las basadas en elftoolchain-0.6.1. También pueden aparecer «AAPCS (base variant)» o «toolchain-specific».
  • ¿Por qué tengo las dos variantes instaladas? Por multiarch. Es normal en algunos entornos. Solo asegúrate de enlazar y ejecutar con el conjunto de bibliotecas que corresponda al binario que uses.

Pequeña nota sobre las fuentes y su financiación

Algunas publicaciones técnicas que abordan estos temas incluyen mensajes para apoyar su trabajo a través de donaciones en criptomonedas, plataformas como Patreon o mediante enlaces de afiliado a tiendas como Amazon o Aliexpress. Es una práctica común en medios independientes, que a veces utilizan enlaces de afiliado en sus artículos para obtener una comisión si realizas una compra tras hacer clic.

Checklist mental cuando audites un binario

Antes de dar por buena una librería o ejecutable para tu dispositivo, repasa estos puntos: consulta readelf -A, busca la presencia o ausencia de Tag_ABI_VFP_args, mira la arquitectura objetivo, y verifica si Thumb y NEON encajan con el hardware en el que lo vas a correr.

Si trabajas con varias toolchains instaladas por multiarch, presta especial atención a las rutas y a las variables de entorno del compilador y enlazador, para no mezclar cabeceras y bibliotecas de ARMEL con binarios de ARMHF o viceversa. Un pequeño despiste puede causar síntomas confusos en tiempo de enlace o ejecución.

Errores típicos que conviene evitar

Un clásico es confiarse y asumir que una biblioteca está en hard-float porque se encuentra bajo arm-linux-gnueabihf, sin confirmar los atributos del ELF. Otro error frecuente es intentar enlazar un ejecutable ARMHF con bibliotecas ARMEL (o al revés), lo que suele terminar en fallos de símbolo o comportamientos extraños.

También es habitual que se quiera «detectar en ejecución» para cambiar rutas de bibliotecas sobre la marcha. Recuerda que la elección ARMEL/ARMHF no se improvisa en tiempo de ejecución; está grabada en el binario. Ajusta tus despliegues y paquetes para que cada ejecutable reciba las bibliotecas de su propia variante.

Si necesitas una referencia rápida, piensa en estos gestos: localiza la biblioteca o ejecutable (por ejemplo, libm.so.6), lanza readelf -A contra el fichero, filtra por FP si quieres ir al grano, y comprueba si hay línea Tag_ABI_VFP_args (hard-float) o si falta (soft-float). Luego, revisa arquitectura, Thumb y NEON para cuadrar el perfil completo del binario.

Cuando compares ARMEL y ARMHF en un mismo sistema, recuerda el contexto de multiarch y el hecho de que la diferencia clave reside en la ABI de coma flotante definida por la AAPCS. Con esa perspectiva, interpretar los atributos de readelf se vuelve un ejercicio rápido y certero.

Queda claro que, con la herramienta adecuada y sabiendo dónde mirar, determinar si un ELF de ARM es ARMHF o ARMEL es cuestión de segundos. La clave está en identificar el atributo Tag_ABI_VFP_args para hard-float y aprovechar readelf -A para obtener contexto adicional sobre la arquitectura, Thumb y NEON. Teniendo presentes las particularidades de multiarch y que la elección de ABI se fija en la compilación, evitarás confusiones y ahorrarás tiempo al validar binarios y bibliotecas en tus proyectos.

qué son los ARM Cortex-R y Cortex-M
Artículo relacionado:
ARM Cortex-R y Cortex-M: qué son, diferencias y cuándo elegir cada uno