다운로드 페이지는 32비트라고 말하고, 파일은 Raspberry Pi에 내려가며, 설치 관리자는 문제의 유용한 부분을 하나도 지목하지 않는 메시지로 실패합니다. 전혀 다른 두 실행 파일이 ELF 의미에서 둘 다 32비트로 계산되며, 그 보드에서 실행될 수 있는 것은 그중 하나뿐입니다. 클래스 필드는 하나의 사실이고 머신 필드는 또 다른 사실이며, 파일 이름은 둘 중 어느 것도 확실히 알려 주지 않습니다. 라이브러리를 바꾸거나 다른 미러를 시도하기 전에 헤더를 읽으십시오.

클래스는 워드 크기를, 머신은 명령어 집합을 말합니다

Linux ELF 참조는 파일 헤더에 클래스 필드와 머신 필드를 정의하며, 두 가지는 서로 다른 질문에 답합니다. 클래스는 파일이 32비트 형식인지 64비트 형식인지 말하고, 머신은 어느 명령어 집합을 위해 빌드되었는지 말합니다. 32비트 x86 빌드와 32비트 ARM 빌드는 전자에서 일치하고 후자에서 어긋납니다. 그래서 올바른 워드 크기를 약속하는 라벨도 프로세서가 디코딩할 수 없는 코드를 전달합니다. 읽을 가치가 있는 세 번째 값은 요청된 인터프리터이며, 바이너리가 하나를 선언할 때 프로그램 헤더가 이를 지목합니다.

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

첫 명령은 헤더를 출력하고, 둘째는 파일에 있으면 프로그램 헤더를 출력하며, 셋째는 로더가 필요로 할 공유 객체를 나열합니다. 클래스, 머신, 인터프리터는 이 세 값이 이 계층에서의 호환성 문제 전부이기 때문에 함께 기록하십시오. 셋 중 어느 것도 다운로드 버튼에 나타나지 않으므로 파일은 설명하는 것이 아니라 검사해야 합니다.

커널에 어떤 인터프리터를 요구하는가

인터프리터를 선언하는 실행 파일은 커널에 특정 로더 경로 하나를 요구합니다. 그 로더가 없으면 지목한 파일이 바로 거기에 있어도 시작이 실패합니다. 사람들이 다운로드가 손상되었다고 결정하는 지점이 여기이며, 실제 답은 배포판이 제공하지 않는 로더입니다.

로더는 OS 릴리스, 사용자 공간 아키텍처, 로더를 제공하는 패키지로 이루어진 실제 실행 시스템에 맞추십시오. 64비트 커널은 사용자 공간과 그 로더가 설치되어 있을 때만 32비트 사용자 공간을 실행할 수 있으므로 프로세서의 능력이 결정적 요인은 아닙니다. 짧은 확인 한 번이 인터프리터를 한 줄로 지목하며, 지원 티켓보다 시간이 적게 듭니다. 셸 스크립트는 인터프리터가 ELF 헤더가 아니라 첫 줄에 적혀 있기 때문에 또 다른 방식으로 실패하며, 그 줄을 읽는 데는 비용이 들지 않습니다.

file --brief ./vendor-vpn

다운로드를 패키지 아키텍처에 맞추십시오

배포판의 패키지 아키텍처는 같은 구분을 자기 어휘로 부호화하며, 공급업체의 지원 성명이 가리키는 것도 그 어휘입니다. 마케팅 라벨을 파일 이름과 비교하는 대신 패키지 관리자가 보고하는 값을 공급업체가 문서화한 값과 비교하십시오. 문제를 일으키는 쌍은 어느 쌍이든 다운로드 목록에서 교환 가능해 보이기 때문에 amd64 대 arm64, armhf 대 armel입니다. x64나 ia32로 끝나는 파일 이름은 빌드 대상을 설명하며, 그것을 담고 있는 머신을 설명하지 않습니다.

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

각 행은 워드 크기가 맞아 보이는데도 코드가 잘못 동작하는 사례, 또는 시작한 뒤 한 계층 아래에서 실패하는 사례입니다. 인터프리터 열은 커널이 여러분의 코드가 실행되기 전에 그 경로를 해석하기 때문에 힌트가 아니라 엄격한 요구 사항으로 읽으십시오. 에뮬레이션은 자체적인 성능과 지원 결과를 지닌 배포 결정이며, 더 넓은 워드 크기를 광고하는 프로세서가 그것을 암시하지는 않습니다.

dpkg --print-architecture

ENOEXEC와 ENOENT는 서로 다른 실패입니다

시작 단계는 두 오류 중 하나를 보고하며, 둘은 서로 다른 문제를 가리킵니다. 오류 값을 읽으면 다른 무엇을 실행하기 전에 실패를 분류할 수 있습니다.

ENOEXEC는 아키텍처가 틀렸거나, 클래스가 틀렸거나, 실행 파일이 아닌 무언가로 형식이 인식되지 않았다는 뜻입니다. ELF 파일에서 ENOENT는 보통 요청한 파일이 존재해도 인터프리터가 없다는 뜻입니다. 같은 ENOENT는 스크립트의 인터프리터가 없다는 뜻일 수도 있으며, 그래서 스크립트의 첫 줄이 중요합니다. 어느 쪽이든 메시지는 계층을 지목하며, 모든 ‘찾을 수 없음’을 설정 누락으로 다루면 조사가 잘못된 방향으로 갑니다. 티켓에는 주변 문장보다 다시 설명하기에 더 잘 견디기 때문에 오류 값을 인용하십시오.

바이너리가 시작되지 않을 때 하지 말아야 할 일

설명되지 않은 바이너리를 셸 래퍼로 억지로 통과시켜도 실행되지 않습니다. 신뢰하지 않는 파일에는 상황에 따라 바이너리의 코드를 실행할 수 있기 때문에 의존성 검사기를 가볍게 실행하지 마십시오. 로더 심볼릭 링크를 추가하거나, 호스트 라이브러리를 바꾸거나, 메시지를 피하려고 외부 미러에서 오래된 아카이브를 받지 마십시오. 그 각각은 헤더가 이미 지목한 불일치를 건드리지 않은 채 변경 범위만 넓힙니다.

공급업체에 연락할 때는 이야기가 아니라 OS 릴리스, 패키지 아키텍처, 클래스와 머신 문자열, 요청한 인터프리터, 첫 오류 줄이라는 값을 보내십시오. 그 집합은 실패하는 설치 관리자의 스크린샷보다 지원 질문을 빠르게 해결합니다. 오래된 산출물과 기억에 의존한 포럼 출력은 현재 지원 매트릭스가 아니며, 네이티브 바이너리가 로드된 뒤에도 프로필, 인증, 라우팅은 별도의 작업으로 남습니다.

관련 글