在Linux中确定二进制文件(库或可执行文件)的目标ISA扩展。

61
我们有一个关于Java应用程序的问题,它在一台使用Via C3处理器的老旧Advantech POS主板下运行FC3。该Java应用程序有几个通过JNI访问的编译共享库。
Via C3处理器应该是i686兼容的。不久前,在一块具有相同处理器的MiniItx主板上安装Ubuntu 6.10后,我发现之前的说法并非完全正确。由于C3处理器中缺少i686集的某些特定和可选指令,Ubuntu内核在启动时挂起。GCC编译器在使用i686优化时会默认使用i686集合中缺失的这些指令。在这种情况下,解决方案是选择i386编译版本的Ubuntu分发版。
Java应用程序的基本问题是,FC3分发版是通过从另一台PC(这次是Intel P4)的硬盘镜像进行克隆安装的,因此需要进行一些黑客操作才能使其运行,例如将某些软件包(例如内核软件包)替换为i386编译版本。
问题在于,系统在工作一段时间后完全挂起,没有任何迹象。我担心某些i686代码仍然留存在系统中,并可能随时随地随机执行(例如在恢复暂停模式后或类似情况下)。
我的问题是:
  • 是否有工具或方法可以查找二进制文件(可执行文件或库)所需的特定架构扩展?file提供的信息不足。
6个回答

113

unix.linux的file命令非常适合这个任务。它通常可以检测给定二进制文件的目标架构和操作系统(并且自1973年以来一直在维护。哇!)

当然,如果您不是在unix/linux下运行,您可能会有些困难。我目前正在尝试找到一个基于Java的端口,在运行时可以调用它...但是没有这样的运气。

Unix file命令提供类似以下的信息:

hex: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.4.17, not stripped

可以使用(unix)objdump -f <fileName>命令来获取有关体系结构详细信息的暗示,该命令将返回以下内容:

architecture: arm, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x0000876c

这个可执行文件是由gcc交叉编译器编译的(在i86机器上编译,以ARM处理器为目标)


5
这个问题特别要求超越“文件”,但我是根据标题来到这里的,而“文件”正是我想要的。因此,这个回答是否真的好,值得怀疑,因为它没有回答实际问题,但它回答了我的问题和aaronstacy的问题! - pattivacek
2
非常抱歉,我不知道“flags”所代表的含义——可能需要搜索gcc代码来查找。 (或者使用它们来比较各个目标机器上的设置)。补充一下关于(unix) 'objdump -f'命令的信息,这超越了'file'命令。 - Ribo
当我尝试最后一个时,我得到了objdump: Unknown command line argument '-f'. Try: 'objdump -help' - Ky -

31

我决定为那些来到这里的人添加一种解决方案:在我个人的情况下,fileobjdump提供的信息不足以解决问题,而grep也没有太大的帮助——我通过readelf -a -W解决了我的问题。

请注意,这会给你提供相当多的信息。与架构相关的信息位于开头和结尾。以下是一个示例:

ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           ARM
  Version:                           0x1
  Entry point address:               0x83f8
  Start of program headers:          52 (bytes into file)
  Start of section headers:          2388 (bytes into file)
  Flags:                             0x5000202, has entry point, Version5 EABI, soft-float ABI
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         8
  Size of section headers:           40 (bytes)
  Number of section headers:         31
  Section header string table index: 28
...
Displaying notes found at file offset 0x00000148 with length 0x00000020:
  Owner                 Data size   Description
  GNU                  0x00000010   NT_GNU_ABI_TAG (ABI version tag)
    OS: Linux, ABI: 2.6.16
Attribute Section: aeabi
File Attributes
  Tag_CPU_name: "7-A"
  Tag_CPU_arch: v7
  Tag_CPU_arch_profile: Application
  Tag_ARM_ISA_use: Yes
  Tag_THUMB_ISA_use: Thumb-2
  Tag_FP_arch: VFPv3
  Tag_Advanced_SIMD_arch: NEONv1
  Tag_ABI_PCS_wchar_t: 4
  Tag_ABI_FP_rounding: Needed
  Tag_ABI_FP_denormal: Needed
  Tag_ABI_FP_exceptions: Needed
  Tag_ABI_FP_number_model: IEEE 754
  Tag_ABI_align_needed: 8-byte
  Tag_ABI_align_preserved: 8-byte, except leaf SP
  Tag_ABI_enum_size: int
  Tag_ABI_HardFP_use: SP and DP
  Tag_CPU_unaligned_access: v6

免责声明:仅当您已知道文件是ELF文件时,此方法才有效。Mach-O二进制文件(在iPhone和Macbook上运行)是一种不是ELF的二进制格式的示例。 - ryanrhee
@ryanrhee 嗯,如果你还不知道它是否是 ELF 格式,那么运行命令后你肯定会知道的 ☺ - Hi-Angel
1
如果你只需要体系结构信息,可以使用 readelf -A - Andrew Wagner

17

我认为你需要一个工具来检查每个指令,以确定它属于哪个特定集合。C3处理器实现的特定指令集是否有官方名称?如果没有,情况会更加复杂。

一个快速且简单的变体可能是在文件中进行原始搜索,如果你可以确定不允许的指令的位模式。只需直接测试它们,例如可以通过简单的objdump | grep命令链执行。


3
使用objdump -d命令可以获得汇编代码表示,然后您只需搜索不良操作码即可。 - Kent Fredric
我想我会按照你提出的方式去做。我只需要找出如何反编译vmlinuz(我不能确定内核本身是i386还是i686版本)。 - Fernando Miguélez
+1. 在我的情况下这并没有太大帮助,但我真的很喜欢这种hacky的方式! - Hi-Angel
2
我使用这个命令来提取目标文件的架构信息... objdump -x <file> | grep Architektur: | cut --delimiter=" " -f 2 | cut --delimiter="," -f 1 - b00r00x0

5
为回答一个关于Via C3是不是i686等级处理器的模糊问题:它不是,它是一个i586等级的处理器。
尽管Cyrix在6x86MX和MII部件中进行了市场推广,但他们从未生产过真正的686等级处理器。除了其他缺失的指令之外,他们没有的两个重要指令是CMPXCHG8b和CPUID,这些指令是运行Windows XP及更高版本所必需的。
National Semiconductor、AMD和VIA都基于Cyrix 5x86/6x86核心(NxP MediaGX、AMD Geode、VIA C3/C7、VIA Corefusion等)生产了CPU设计,这导致出现了奇怪的设计,其中你有一个带有SSE1/2/3指令集的586等级处理器。
如果你遇到上述任何CPU,而且不是用于复古计算机项目(即Windows 98SE及之前版本),那么我的建议是立即远离它。否则你将被困在慢速的i386/486 Linux上,或者不得不重新编译所有针对Cyrix特定优化的软件。

4

在@Hi-Angel的回答基础上,我找到了一个检查静态库位宽的简单方法:

readelf -a -W libsomefile.a | grep Class: | sort | uniq

libsomefile.a 是我的静态库。对于其他 ELF 文件也适用。


3
最快找到架构的方法是执行以下操作:

objdump -f testFile | grep architecture

这对于二进制也适用。


我收到了 objdump: 未知的命令行参数‘-f’。请尝试使用 ‘objdump -help’ - Ky -
这在我的端上使用 -f 或 -x 是有效的。 - mmerle

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接