O pagină de descărcare spune 32 de biți, fișierul ajunge pe un Raspberry Pi, iar instalatorul eșuează cu un mesaj care nu numește nicio parte utilă a problemei. Două fișiere executabile complet diferite contează amândouă ca 32 de biți în sensul ELF, și doar unul dintre ele poate rula pe acea placă. Câmpul de clasă este un fapt, câmpul de mașină este altul, iar un nume de fișier nu vă spune în mod fiabil niciunul. Citiți antetul înainte de a schimba o bibliotecă sau de a încerca altă oglindă.

Clasa spune dimensiunea cuvântului, mașina spune setul de instrucțiuni

Referința ELF a Linux definește un câmp de clasă și un câmp de mașină în antetul fișierului, iar cele două răspund la întrebări diferite. Clasa spune dacă fișierul folosește forma de 32 de biți sau de 64 de biți; mașina spune pentru ce set de instrucțiuni a fost construit. Un build x86 de 32 de biți și un build ARM de 32 de biți sunt de acord la primul și diferă la al doilea. Așa o etichetă care promite dimensiunea corectă a cuvântului livrează totuși cod pe care procesorul nu îl poate decodifica. A treia valoare care merită citită este interpretorul cerut, pe care antetele programului îl numesc atunci când binarul declară unul.

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

Prima comandă afișează antetul, a doua afișează antetele programului când fișierul are, iar a treia listează obiectele partajate de care va avea nevoie încărcătorul. Notați clasa, mașina și interpretorul împreună, pentru că aceste trei valori sunt întreaga întrebare de compatibilitate la acest nivel. Niciuna dintre cele trei nu apare pe un buton de descărcare, de aceea fișierul trebuie inspectat, nu descris.

Ce interpretor cere nucleului

Un fișier executabil care declară un interpretor cere nucleului o anumită cale de încărcător. Când acel încărcător lipsește, lansarea eșuează chiar dacă fișierul pe care l-ați numit se află exact acolo. Acesta este punctul în care oamenii decid că descărcarea este coruptă, în timp ce răspunsul real este un încărcător pe care distribuția nu îl furnizează.

Potriviți încărcătorul cu sistemul pe care îl rulați efectiv: versiunea OS, arhitectura spațiului de utilizator și pachetul care furnizează încărcătorul. Un nucleu de 64 de biți poate rula un spațiu de utilizator de 32 de biți doar când acel spațiu și încărcătorul său sunt instalate, deci capacitățile procesorului nu sunt factorul decisiv. O verificare scurtă numește interpretorul pe o singură linie și durează mai puțin decât un tichet de suport. Un script shell eșuează din nou altfel, pentru că interpretorul său este numit pe prima linie și nu într-un antet ELF, iar citirea acelei linii nu costă nimic.

file --brief ./vendor-vpn

Potriviți descărcarea cu arhitectura pachetului

Arhitecturile pachetelor distribuțiilor codifică aceeași distincție în propriul vocabular, iar la acel vocabular se referă declarația de suport a unui furnizor. Comparați valoarea raportată de managerul de pachete cu valoarea documentată de furnizor, în loc să comparați o etichetă de marketing cu un nume de fișier. Perechile care creează probleme sunt amd64 față de arm64 și armhf față de armel, pentru că fiecare pereche pare interschimbabilă într-o listă de descărcare. Un nume de fișier care se termină în x64 sau ia32 descrie o țintă de build, nu mașina care îl conține.

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

Fiecare rând este un caz în care dimensiunea cuvântului pare corectă și codul se comportă totuși greșit, sau în care pornește și apoi eșuează un strat mai jos. Citiți coloana interpretorului ca cerință dură și nu ca indiciu, pentru că nucleul rezolvă acea cale înainte ca orice cod al dumneavoastră să ruleze. Emularea este o decizie de implementare cu propriile consecințe pentru performanță și suport, și nu este niciodată implicată de un procesor care promovează o dimensiune mai mare a cuvântului.

dpkg --print-architecture

ENOEXEC și ENOENT sunt eșecuri diferite

Etapa de lansare raportează una dintre două erori, iar ele indică probleme diferite. Citirea valorii erorii clasifică eșecul înainte de a rula orice altceva.

ENOEXEC înseamnă că formatul nu a fost recunoscut: arhitectură greșită, clasă greșită sau ceva ce nu este deloc executabil. ENOENT pe un fișier ELF înseamnă de obicei că lipsește interpretorul, deși fișierul cerut există. Același ENOENT poate însemna și că lipsește interpretorul unui script, de aceea contează prima linie a unui script. În orice caz mesajul numește stratul, iar tratarea fiecărui „negăsit” ca lipsă de configurare trimite investigația în direcția greșită. Citați valoarea erorii în tichet, pentru că rezistă mai bine la repovestire decât propoziția din jur.

Ce să nu faceți când binarul nu pornește

A forța un binar neexplicat printr-un înveliș shell nu îl face să ruleze. Nu rulați un verificator de dependențe cu ușurință pe un fișier în care nu aveți încredere, pentru că rularea lui poate executa cod din binar în anumite circumstanțe. Nu adăugați legături simbolice ale încărcătorului, nu schimbați biblioteci ale gazdei și nu descărcați o arhivă veche de pe o oglindă terță pentru a ocoli mesajul. Fiecare dintre acestea lărgește suprafața modificării fără a atinge nepotrivirea pe care antetul a numit-o deja.

Când vă adresați furnizorului, trimiteți valori, nu o poveste: versiunea OS, arhitectura pachetului, șirurile de clasă și mașină, interpretorul cerut și prima linie de eroare. Acel set rezolvă întrebările de suport mai repede decât o captură de ecran a unui instalator care eșuează. Artefactele vechi și ieșirile de forum ținute minte nu sunt o matrice de suport actuală, iar după ce se încarcă un binar nativ, profilul, autentificarea și rutarea rămân muncă separată.

Articole similare