32位LINUX 2.6可执行文件可以在LINUX 3.2机器上可靠运行吗?

时间:2014-03-13 19:50:38

标签: linux x86 x86-64 glibc strace

假设已将32位支持加载到给定的64位LINUX安装:

  • 32位LINUX 2.6可执行文件能否在LINUX 3.2机器上可靠运行? (是的,重申标题)显然不是!

  • 对32位程序有什么限制(根据什么类型的程序,而不是4GB限制等)?

  • 是否有特定的标记文件,可执行文件,系统调用可以检查以提前确定,以便脚本可以通知用户系统配置不正确?然后我可以写一个剧本,说" canirunhere"这可能会让用户明白,而不仅仅是让一些离奇的FLOATING POINT EXCEPTION崩溃。

    • 尝试运行程序(在脚本中)并查看它是否崩溃 一个选项,因为该程序可能正在进行除零!

背景故事:

我有一个针对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位程序,因此I had to follow the instructions on the (now sadly dead) link in this previous question. (click here)我无法在非功能机器上执行相同的任务,尽管找不到"文件&# 34;错误意味着理论上存在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的输出(不是完全相同的程序,因此地址会略有不同),这证实它处于动态加载状态,希望有助于缩小原因。 / p>

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) ---

2 个答案:

答案 0 :(得分:3)

  

假设已将32位支持加载到给定的64位LINUX安装

基本上是的,内核应该支持更旧的二进制文件,但在你的情况下程序是动态链接的,所以它需要特定版本的glibc和所有其他动态库。

您可以尝试将完整的旧32位分发包解压缩到某个子文件夹,然后执行chroot,然后在chroot中运行您的程序。

另外,检查二进制文件的ldd输出(如果使用非常旧的glibc构建二进制文件,它可能无效,因为有ld.so又名ld-linux.so.2程序来加载动态二进制文件和实施ldd)。

do_lookup_x中有一个SIGFPE示例(您可以使用以下内容进行搜索:SIGFPE, Arithmetic exception. do_lookup_x):

Floating point exception ( SIGFPE ) on 'int main(){ return(0); }' @ stackoverflow.com

  

2006年左右,glibc增加了对GNU哈希部分的支持   主线发行版在2007年或2008年左右开始只是GNU-hash。你的   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之间的相同不兼容性。

答案 1 :(得分:0)

正如other answer中正确指出的,您的问题与内核版本无关。

相反,目标(非功能)机器上的glibc太旧了。

通常,在较新的glibc系统上构建并在较旧的glibc系统上运行的结果会导致动态链接器错误GLIBC_2.x version not found (required by ...),但在这种情况下,甚至在您到达该点之前就会崩溃。

现在,如果您可以使用-Wl,--hash-style=sysv重建应用程序,则可以解决SIGFPE问题,并最终得到一个正在运行的应用程序(有些不太可能)或出现GLIBC_2.x not found错误(非常可能)。

This answer显示了解决这个问题的一些方法。

注意:大多数UNIX系统支持向后兼容性(旧二进制文件继续在较新的系统上运行)但不支持向前兼容性(在较旧的机器上构建的二进制文件运行在较旧的机器上)。