— x86_64 커널 지원으로 컴파일된 경우 x86_64 커널을 사용하여 x86_32 프로그램을 실행할 수 있다는 것은 잘 알려져 있습니다. 그러나 동적 링커는 32비트 프로그램에 대해 사전 로드된 별도의 라이브러리 세트를 정의하는 방법을 제공하지 않으므로 이러한 프로그램을 실행할 때마다 x86_64 사전 로드를 수행하면 다음과 같은 오류 메시지가 표시됩니다.
ERROR: ld.so: object '… … …' from /etc/ld.so.preload cannot be preloaded (wrong ELF class: ELFCLASS64): ignored.
미리 로드하기 위해 동일한 x86_32 라이브러리 목록을 거기에 넣으면 제대로 작동하게 되지만 모든 순수 x86_64 실행도 불평을 하기 시작합니다.
분명히 가장 좋은 접근 방식은 별도의 파일에서 사전 로드를 지원하도록 동적 로더를 수정하는 것이지만, 아무리 말해도 시간이 오래 걸리는 프로세스입니다. 깨끗한 솔루션을 생각해 볼 수 있나요?
이제 필요한 파일을 스스로 로드할 수 있는 것을 생각하고 있지만 multi-class-pre-load.so
, 제가 볼 때 ELF에는 "멀티클래스" 지원이 없습니다.
답변1
ld.so.preload에서는 경로에 명시적인 "lib" 또는 "lib64"가 아닌 "$LIB"를 지정하려고 합니다. 따라서 Redhat 스타일 배포판에서 32비트 프로세스의 경우 "/usr/alternates/$LIB/libfoo.so"는 "/usr/alternates/lib/libfoo.so" 및 "/usr/alternates/lib64/"가 됩니다. 64비트 프로세스의 경우 libfoo.so"입니다. Debian 스타일 배포판에서 "/usr/alternates/$LIB/libfoo.so"는 "/usr/alternates/lib/i386-linux-gnu/libfoo.so" 및 "/usr/alternates/x86_64-linux-"가 됩니다. gnu/libfoo.so"입니다. 그런 다음 두 아키텍처 모두에 대한 라이브러리로 트리를 채워야 합니다.
"rpath 토큰 확장"을 참조하세요.ld.so(8) 매뉴얼 페이지이에 대해 자세히 알아보세요.
그러나 로드를 수정하려는 바이너리를 컴파일하는 경우 라이브러리를 미리 로드하는 것보다 설정을 통해 경로를 수정하는 것이 더 나을 수도 있습니다.DT_RUNPATH링크 라인에서(동일한 "$LIB" 스타일 경로를 사용하여 시스템 기본값보다 라이브러리 위치를 선호하도록 바이너리를 구성합니다.
또는 다른 사람들이 지적했듯이 ELF 파일을 편집하여 컴파일되지 않은 바이너리에 DT_RUNPATH를 설정할 수 있습니다.
다음은 x86_64 Centos 6.5 시스템에 적용됩니다.
cd /tmp
mkdir lib lib64
wget http://carrera.databits.net/~ksb/msrc/local/lib/snoopy/snoopy.h
wget http://carrera.databits.net/~ksb/msrc/local/lib/snoopy/snoopy.c
gcc -m64 -shared -fPIC -ldl snoopy.c -o /tmp/lib64/snoopy.so
gcc -m32 -shared -fPIC -ldl snoopy.c -o /tmp/lib/snoopy.so
cat > true.c <<EOF
int main(void)
{ return 0; }
EOF
gcc -m64 true.c -o true64
gcc -m32 true.c -o true32
sudo bash -c "echo '/tmp/\$LIB/snoopy.so' > /etc/ld.so.preload"
strace -fo /tmp/strace64.out /tmp/true64
strace -fo /tmp/strace32.out /tmp/true32
sudo rm /etc/ld.so.preload"
strace 출력에서 strace64.out에는 다음이 포함됩니다.
open("/tmp/lib64/snoopy.so", O_RDONLY) = 3
strace32.out에는 다음이 포함됩니다.
open("/tmp/lib/snoopy.so", O_RDONLY) = 3
ld.so.preload의 내용은 다음과 같습니다.
/tmp/$LIB/snoopy.so
답변2
사전 로드는 의도된 것이 아닙니다.정상시스템 운영. 일반적으로 사용하려는 라이브러리에 대해 실제로 링크해야 합니다.
여러 아키텍처에서 프로그램을 실행할 때 사전 로드가 필요한 소수의 사람들은 무해한 오류 메시지에 신경 쓰지 않는 것으로 생각됩니다.
또는 프로그램이 다른 아키텍처의 다른 프로그램을 실행하지 않는 한 LD_PRELOAD
잘못된 라이브러리 부분이 있는 프로그램을 사용하는 것이 더 나을 수도 있습니다.
그러나 실제로는 편집 단계에서 ELF 파일에 나열된 라이브러리를 수정하는 것이 더 좋지만 나중에 ELF를 편집할 수 있는 도구도 있습니다.
(참고: 처음에는 귀하의 질문이 x64_32에 관한 것이라고 생각했습니다. 완전히 다르며 몇 가지 흥미로운 버그가 있습니다)