32位LINUX 2.6可执行文件可以在LINUX 3.2机器上可靠运行吗?(是的,重申标题)显然不是!
32位程序有哪些限制(就哪种程序而言,而不是4GB的限制等)?
是否可以检查特定的标记文件,可执行文件,系统调用来提前确定,以便脚本可以通知用户系统配置不正确?然后,我可以编写一个脚本,说“ canirunhere”,使脚本对用户显而易见,而不是让脚本出现一些奇怪的浮点异常崩溃。
我有一个用于2.6 LINUX的32位二进制版本,该版本具有经典的不兼容堆栈跟踪(如下所示)。它可以在某些计算机上运行,例如x86_64 Linux 3.2机器(在这种情况下为3.2.0-8),而在其他计算机(例如AMD64 Linux 3.2机器(在这种情况下为3.2.44-3))上则不能。
该程序会在动态加载程序本身中死亡。这是信息的“文件”和“ uname -a”位:
文件:
ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.6.9, dynamically linked (uses shared libs), not stripped
非功能系统:
3.2.44-3.2.0.3.1-amd64-10846333 #1 SMP Wed May 29 13:08:01 UTC 2013 x86_64 GNU/Linux
FUNCTIONAL系统,一个运行Ubuntu的x86_64 VM:
3.2.0-58-generic #88-Ubuntu SMP Tue Dec 3 17:37:58 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux
请注意,Ubuntu系统最初不支持32位程序,因此,我必须按照上一个问题中(现在已经死了)链接上的说明进行操作。(单击此处)我无法在无法运行的计算机上执行相同的任务,尽管缺少“找不到文件”错误意味着理论上存在32位支持。
堆栈跟踪:
Program received signal SIGFPE, Arithmetic exception. 0xf7feb876 in do_lookup_x () from /lib/ld-linux.so.2 (gdb) where #0 0xf7feb876 in do_lookup_x () from /lib/ld-linux.so.2 #1 0xf7febc07 in _dl_lookup_symbol_x () from /lib/ld-linux.so.2 #2 0xf7fed251 in _dl_relocate_object () from /lib/ld-linux.so.2 #3 0xf7fe7108 in dl_main () from /lib/ld-linux.so.2 #4 0xf7ff58f1 in _dl_sysdep_start () from /lib/ld-linux.so.2 #5 0xf7fe3c33 in _dl_start () from /lib/ld-linux.so.2 #6 0xf7fe3817 in _start () from /lib/ld-linux.so.2
Strace输出:在响应者的建议下,这是strace的输出(不是完全相同的程序,因此地址会略有不同),这确认它处于动态加载中,希望有助于缩小原因。
strace ./porgram execve("./program", ["./program"...], [/* 63 vars */]) = 0 brk(0) = 0x80ea000 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xf77c5000 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory) open("/etc/ld.so.cache", O_RDONLY) = 3 fstat64(3, {st_mode=S_IFREG|0644, st_size=47552, ...}) = 0 mmap2(NULL, 47552, PROT_READ, MAP_PRIVATE, 3, 0) = 0xf77b9000 close(3) = 0 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) open("/lib/tls/i686/cmov/libc.so.6", O_RDONLY) = 3 read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\320\222"..., 512) = 512 fstat64(3, {st_mode=S_IFREG|0755, st_size=1265332, ...}) = 0 mmap2(NULL, 1275268, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xf7681000 mmap2(0xf77b2000, 16384, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x130) = 0xf77b2000 mmap2(0xf77b6000, 9604, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xf77b6000 close(3) = 0 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xf7680000 set_thread_area({entry_number:-1 -> 12, base_addr:0xf76806b0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0 --- SIGFPE (Floating point exception) @ 0 (0) ---
假定已将32位支持加载到给定的64位LINUX安装上
基本上可以,内核应该支持较旧的二进制文件,但是如果您是动态链接程序的,则它需要特定版本的glibc和所有其他动态库。
您可以尝试将完整的较旧的32位发行版解压缩到某个子文件夹,然后将其chroot
放入其中,然后在chroot中运行程序。
另外,检查ldd
你的二进制输出(它可能无法正常工作,如果二进制是构建具有非常老的glibc,因为在ld.so
又名ld-linux.so.2
程序加载动态二进制文件和实施LDD)。
在do_lookup_x中有一个SIGFPE的示例(您可以使用以下代码在Google上进行搜索:SIGFPE,算术异常。do_lookup_x):
'int main(){return(0);上的浮点异常(SIGFPE);}' @ stackoverflow.com
对GNU哈希部分的支持是在2006年左右添加到glibc的,并且主线发行版在2007年或2008年左右才开始是仅GNU哈希的。您的Centrino的glibc是2003年的,它早于GNU哈希。
如果ld.so无法理解GNU哈希,它将尝试改用旧的ELF哈希部分,该部分为空。特别是,我怀疑您的崩溃正在elf / do-lookup.h中的此行发生:
for (symidx = map->l_buckets[hash % map->l_nbuckets];
由于链接器可能无法理解GNU哈希,因此l_nbuckets将为0,从而导致崩溃。
因此,您的FPE可能来自较旧的32位linux上的glibc和某些较新的发行版中的32位glibc之间的不兼容。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句