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

Posted

技术标签:

【中文标题】确定 Linux 中二进制文件的目标 ISA 扩展名(库或可执行文件)【英文标题】:Determine target ISA extensions of binary file in Linux (library or executable) 【发布时间】:2010-09-21 01:01:47 【问题描述】:

我们遇到了一个问题,该问题与在带有 Via C3 处理器的 Advantech POS 板上的(相当旧的)FC3 下运行的 Java 应用程序有关。 Java 应用程序有几个通过 JNI 访问的已编译共享库。

Via C3 处理器应该与 i686 兼容。前段时间在具有相同处理器的 MiniItx 板上安装 Ubuntu 6.10 后,我发现前面的说法并非 100% 正确。由于缺少C3处理器中设置的i686的一些特定和可选指令,Ubuntu内核在启动时挂起。在使用 i686 优化时,GCC 编译器默认使用 i686 集的 C3 实现中缺少的这些指令。在这种情况下,解决方案是使用 i386 编译版本的 Ubuntu 发行版。

Java 应用程序的基本问题是 FC3 发行版是通过从另一台 PC(这次是 Intel P4)的 HD 映像克隆而安装在 HD 上的。之后,该发行版需要进行一些修改才能使其运行,例如用 i386 编译版本替换一些软件包(例如内核)。

问题是工作一段时间后系统完全挂掉了。恐怕有些 i686 代码会留在系统某处,随时可能随机执行(例如从挂起模式恢复后或类似的情况)。

我的问题是:

是否有任何工具或方法可以找出二进制文件(可执行文件或库)需要哪些特定架构扩展? file 没有提供足够的信息。

【问题讨论】:

【参考方案1】:

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 处理器为目标)

【讨论】:

这个问题特别要求超越file,但我是根据标题来到这里的,而file正是我想要的。所以这是否真的是一个好的答案值得怀疑,因为它没有回答实际的问题,但它确实回答了我的问题,而且显然 aaronstacy 也是! (我添加了一些关于(unix)“objdump -f”命令的信息,这些信息超出了“文件”命令。遗憾的是,我不知道“标志”中的位是什么意思——可能需要搜索gcc代码。(或使用它们来比较各种目标机器上的设置)) 当我尝试最后一个时,我得到objdump: Unknown command line argument '-f'. Try: 'objdump -help'【参考方案2】:

我决定为任何来到这里的人添加一个解决方案:就我个人而言,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 好吧,如果你还不知道它是不是 ELF,那么在你运行命令之后你一定会知道☺ 我只想要架构信息,可以使用readelf -A【参考方案3】:

我认为您需要一个工具来检查每条指令,以确定它属于哪个集合。 C3 处理器实现的特定指令集是否有正式名称?如果没有,那就更毛了。

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

【讨论】:

objdump -d 应该为您提供 ASM 表示,然后您可以使用 grep 查找错误的操作码。 我想我会按照你建议的方式去做。我只需要了解如何反编译vmlinuz(我无法确定内核本身是i386还是i686版本)。 +1。这对我来说没有多大帮助,但我真的很喜欢这种 hacky 方式! 我用这个命令提取目标文件架构信息...objdump -x <file> | grep Architektur: | cut --delimiter=" " -f 2 | cut --delimiter="," -f 1【参考方案4】:

回答 Via C3 是否是 i686 类处理器的歧义:不是,它是 i586 类处理器。

Cyrix 从未生产过真正的 686 级处理器,尽管他们在市场上声称使用 6x86MX 和 MII 部件。在其他缺失的指令中,他们没有的两个重要指令是 CMPXCHG8b 和 CPUID,它们是运行 Windows XP 及更高版本所必需的。

美国国家半导体、AMD 和威盛都生产了基于 Cyrix 5x86/6x86 内核(NxP MediaGX、AMD Geode、威盛 C3/C7、威盛 Corefusion 等)的 CPU 设计,这导致了奇特的设计,你有具有 SSE1/2/3 指令集的 586 类处理器。

我的建议是,如果您遇到上面列出的任何 CPU 并且它不是用于老式计算机项目(即 Windows 98SE 和更早版本),那么请远离它。您将被困在缓慢的 i386/486 Linux 上,或者必须使用 Cyrix 特定的优化重新编译所有软件。

【讨论】:

【参考方案5】:

根据@Hi-Angel 的回答,我找到了一种检查静态库位宽的简单方法:

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

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

【讨论】:

【参考方案6】:

找到架构的最快方法是执行:

objdump -f testFile | grep architecture

这甚至适用于二进制。

【讨论】:

我收到objdump: Unknown command line argument '-f'. Try: 'objdump -help'

以上是关于确定 Linux 中二进制文件的目标 ISA 扩展名(库或可执行文件)的主要内容,如果未能解决你的问题,请参考以下文章

20145205 《信息安全系统设计基础》第5周学习总结

C++ 常用命令行开发工具(Linux)

在 LLVM-C API 中确定和设置主机目标三元组和指令扩展

确定 Linux 二进制文件的直接共享对象依赖关系?

Linux中一些约定俗成的文件扩展名

linux下nm命令的使用