Una página de descarga dice 32 bits, el archivo aterriza en una Raspberry Pi y el instalador falla con un mensaje que no nombra ninguna parte útil del problema. Dos ejecutables completamente distintos cuentan ambos como 32 bits en el sentido ELF, y solo uno de ellos puede ejecutarse en esa placa. El campo de clase es un hecho, el campo de máquina es otro, y un nombre de archivo no le dice de forma fiable ninguno de los dos. Lea la cabecera antes de cambiar una biblioteca o probar otro espejo.

La clase dice el tamaño de palabra, la máquina dice el conjunto de instrucciones

La referencia ELF de Linux define un campo de clase y un campo de máquina en la cabecera del archivo, y ambos responden preguntas distintas. La clase dice si el archivo usa la forma de 32 bits o la de 64 bits; la máquina dice para qué conjunto de instrucciones se compiló. Una compilación x86 de 32 bits y una compilación ARM de 32 bits coinciden en lo primero y difieren en lo segundo. Así es como una etiqueta que promete el tamaño de palabra correcto entrega igualmente código que el procesador no puede descodificar. El tercer valor que merece leerse es el intérprete solicitado, que las cabeceras de programa nombran cuando el binario declara uno.

readelf -h -- ./vendor-vpn
readelf -l -- ./vendor-vpn
readelf -d -- ./vendor-vpn | grep NEEDED

El primer comando imprime la cabecera, el segundo imprime las cabeceras de programa cuando el archivo tiene alguna, y el tercero lista los objetos compartidos que el cargador necesitará. Anote clase, máquina e intérprete juntos, porque esos tres valores son toda la cuestión de compatibilidad en esta capa. Ninguno de los tres aparece en un botón de descarga, y por eso hay que inspeccionar el archivo en lugar de describirlo.

Qué intérprete pide al núcleo

Un ejecutable que declara un intérprete pide al núcleo una ruta de cargador concreta. Cuando ese cargador falta, el arranque falla aunque el archivo que usted nombró esté justo ahí. Ese es el punto en el que la gente decide que la descarga está corrupta, cuando la respuesta real es un cargador que la distribución no incluye.

Ajuste el cargador al sistema que realmente ejecuta: la versión del sistema operativo, la arquitectura del espacio de usuario y el paquete que proporciona el cargador. Un núcleo de 64 bits puede ejecutar un espacio de usuario de 32 bits solo cuando ese espacio y su cargador están instalados, así que las capacidades del procesador no son el factor decisivo. Una comprobación breve nombra el intérprete en una sola línea, y tarda menos que un ticket de soporte. Un script de shell falla de otra manera, porque su intérprete se nombra en la primera línea y no en una cabecera ELF, y leer esa línea no cuesta nada.

file --brief ./vendor-vpn

Ajuste la descarga a la arquitectura del paquete

Las arquitecturas de paquete de las distribuciones codifican la misma distinción en su propio vocabulario, y ese vocabulario es al que se refiere la declaración de soporte de un proveedor. Compare el valor que informa su gestor de paquetes con el valor que documenta el proveedor, en lugar de comparar una etiqueta de marketing con un nombre de archivo. Los pares que causan problemas son amd64 frente a arm64, y armhf frente a armel, porque cada par parece intercambiable en una lista de descarga. Un nombre de archivo que termina en x64 o ia32 describe un objetivo de compilación, no la máquina que lo contiene.

Label on the downloadELF classe_machineInterpreter the kernel wantsHow it fails on the wrong host
amd64ELF64x86-64/lib64/ld-linux-x86-64.so.2Immediate exec failure on an ARM board
armhfELF32ARM/lib/ld-linux-armhf.so.3Loads on a soft-float system, then fails on a float ABI call
i386ELF32Intel 80386/lib/ld-linux.so.2Exec format error where no 32-bit loader package exists

Cada fila es un caso en el que el tamaño de palabra parece correcto y el código sigue comportándose mal, o en el que arranca y luego falla una capa más abajo. Lea la columna de intérprete como un requisito duro y no como una pista, porque el núcleo resuelve esa ruta antes de que se ejecute cualquier código suyo. La emulación es una decisión de despliegue con sus propias consecuencias de rendimiento y soporte, y nunca la implica un procesador que anuncia un tamaño de palabra mayor.

dpkg --print-architecture

ENOEXEC y ENOENT son fallos distintos

La etapa de arranque informa uno de dos errores, y apuntan a problemas diferentes. Leer el valor del error clasifica el fallo antes de que ejecute cualquier otra cosa.

ENOEXEC significa que el formato no se reconoció: arquitectura equivocada, clase equivocada o algo que no es un ejecutable en absoluto. ENOENT en un archivo ELF suele significar que falta el intérprete, aunque el archivo que pidió existe. El mismo ENOENT también puede significar que falta el intérprete de un script, y por eso importa la primera línea de un script. En cualquier caso el mensaje nombra la capa, y tratar cada «no encontrado» como una configuración ausente envía la investigación en la dirección equivocada. Cite el valor del error en el ticket, porque sobrevive al recuento mejor que la frase que lo rodea.

Qué no hacer cuando el binario no arranca

Forzar un binario no explicado a través de un envoltorio de shell no lo hace funcionar. No ejecute un comprobador de dependencias a la ligera sobre un archivo en el que no confía, porque ejecutarlo puede ejecutar código del binario en algunas circunstancias. No añada enlaces simbólicos del cargador, no cambie bibliotecas del host ni descargue un archivo antiguo de un espejo de terceros para saltarse el mensaje. Cada una de esas cosas amplía la superficie de cambio sin tocar la discrepancia que la cabecera ya nombró.

Cuando se dirija al proveedor, envíe valores y no una historia: la versión del sistema operativo, la arquitectura del paquete, las cadenas de clase y máquina, el intérprete solicitado y la primera línea de error. Ese conjunto resuelve las preguntas de soporte más rápido que una captura de pantalla de un instalador que falla. Los artefactos antiguos y las salidas de foro recordadas no son una matriz de soporte actual, y una vez que un binario nativo carga, el perfil, la autenticación y el enrutamiento siguen siendo trabajo aparte.

Artículos relacionados