L’installer VPN dice 32 bit: controllate invece l’intestazione ELF
La dimensione della parola non identifica il set di istruzioni. Procedura per leggere classe, macchina e interprete, poi chiedere una build adatta all’host.
Una pagina di download dice 32 bit, il file atterra su un Raspberry Pi e l’installer fallisce con un messaggio che non nomina nessuna parte utile del problema. Due eseguibili completamente diversi contano entrambi come 32 bit nel senso ELF, e solo uno di essi può girare su quella scheda. Il campo classe è un fatto, il campo macchina è un altro, e un nome di file non vi dice in modo affidabile nessuno dei due. Leggete l’intestazione prima di cambiare una libreria o provare un altro mirror.
La classe dice la dimensione della parola, la macchina dice il set di istruzioni
Il riferimento ELF di Linux definisce un campo classe e un campo macchina nell’intestazione del file, e i due rispondono a domande diverse. La classe dice se il file usa la forma a 32 bit o a 64 bit; la macchina dice per quale set di istruzioni è stato compilato. Una build x86 a 32 bit e una build ARM a 32 bit concordano sul primo e differiscono sul secondo. Così un’etichetta che promette la dimensione di parola giusta consegna comunque codice che il processore non riesce a decodificare. Il terzo valore che vale la pena leggere è l’interprete richiesto, che le intestazioni di programma nominano quando il binario ne dichiara uno.
readelf -h -- ./vendor-vpn
readelf -l -- ./vendor-vpn
readelf -d -- ./vendor-vpn | grep NEEDED
Il primo comando stampa l’intestazione, il secondo stampa le intestazioni di programma quando il file ne ha, e il terzo elenca gli oggetti condivisi che il loader richiederà. Annotate classe, macchina e interprete insieme, perché questi tre valori sono tutta la questione di compatibilità a questo livello. Nessuno dei tre compare su un pulsante di download, perciò il file va ispezionato invece che descritto.
Quale interprete chiede al kernel
Un eseguibile che dichiara un interprete chiede al kernel un percorso di loader preciso. Quando quel loader manca, l’avvio fallisce anche se il file che avete nominato è proprio lì. È il punto in cui le persone decidono che il download è corrotto, mentre la risposta reale è un loader che la distribuzione non fornisce.
Fate corrispondere il loader al sistema che eseguite davvero: la versione del sistema operativo, l’architettura dello spazio utente e il pacchetto che fornisce il loader. Un kernel a 64 bit può eseguire uno spazio utente a 32 bit solo quando quello spazio e il suo loader sono installati, quindi le capacità del processore non sono il fattore decisivo. Un breve controllo nomina l’interprete su una sola riga, e richiede meno tempo di un ticket di supporto. Uno script shell fallisce ancora in un altro modo, perché il suo interprete è nominato sulla prima riga e non in un’intestazione ELF, e leggere quella riga non costa nulla.
file --brief ./vendor-vpn
Fate corrispondere il download all’architettura del pacchetto
Le architetture dei pacchetti delle distribuzioni codificano la stessa distinzione nel proprio vocabolario, ed è a quel vocabolario che rimanda la dichiarazione di supporto di un fornitore. Confrontate il valore che il vostro gestore di pacchetti riporta con il valore che il fornitore documenta, invece di confrontare un’etichetta di marketing con un nome di file. Le coppie che creano problemi sono amd64 contro arm64, e armhf contro armel, perché ogni coppia sembra intercambiabile in un elenco di download. Un nome di file che termina in x64 o ia32 descrive un obiettivo di build, non la macchina che lo contiene.
| Label on the download | ELF class | e_machine | Interpreter the kernel wants | How it fails on the wrong host |
|---|---|---|---|---|
| amd64 | ELF64 | x86-64 | /lib64/ld-linux-x86-64.so.2 | Immediate exec failure on an ARM board |
| armhf | ELF32 | ARM | /lib/ld-linux-armhf.so.3 | Loads on a soft-float system, then fails on a float ABI call |
| i386 | ELF32 | Intel 80386 | /lib/ld-linux.so.2 | Exec format error where no 32-bit loader package exists |
Ogni riga è un caso in cui la dimensione di parola sembra giusta e il codice si comporta comunque male, o in cui parte e poi fallisce uno strato più in basso. Leggete la colonna dell’interprete come un requisito rigido e non come un indizio, perché il kernel risolve quel percorso prima che qualsiasi vostro codice venga eseguito. L’emulazione è una decisione di distribuzione con le proprie conseguenze di prestazioni e supporto, e non è mai implicata da un processore che pubblicizza una dimensione di parola più ampia.
dpkg --print-architecture
ENOEXEC ed ENOENT sono guasti diversi
La fase di avvio riporta uno di due errori, e puntano a problemi diversi. Leggere il valore dell’errore classifica il guasto prima che eseguiate qualsiasi altra cosa.
ENOEXEC significa che il formato non è stato riconosciuto: architettura sbagliata, classe sbagliata o qualcosa che non è affatto un eseguibile. ENOENT su un file ELF di solito significa che manca l’interprete, anche se il file che avete chiesto esiste. Lo stesso ENOENT può anche significare che manca l’interprete di uno script, ed è per questo che conta la prima riga di uno script. In ogni caso il messaggio nomina lo strato, e trattare ogni «non trovato» come configurazione assente manda l’indagine nella direzione sbagliata. Citare il valore dell’errore nel ticket, perché sopravvive al racconto meglio della frase che lo circonda.
Cosa non fare quando il binario non parte
Forzare un binario non spiegato attraverso un involucro shell non lo fa funzionare. Non eseguite un controllo delle dipendenze alla leggera su un file di cui non vi fidate, perché eseguirlo può in alcune circostanze eseguire codice dal binario. Non aggiungete link simbolici del loader, non scambiate librerie dell’host e non scaricate un archivio vecchio da un mirror di terze parti per aggirare il messaggio. Ognuna di queste azioni allarga la superficie di modifica senza toccare la discrepanza che l’intestazione ha già nominato.
Quando vi rivolgete al fornitore, inviate valori e non una storia: la versione del sistema operativo, l’architettura del pacchetto, le stringhe di classe e macchina, l’interprete richiesto e la prima riga di errore. Quell’insieme risolve le domande di supporto più in fretta di uno screenshot di un installer che fallisce. Gli artefatti vecchi e le uscite di forum ricordate non sono una matrice di supporto attuale, e una volta che un binario nativo si carica, profilo, autenticazione e instradamento restano lavoro separato.