Contents

检查库是32位还是64位

1. 概述

我们可以在 64 位 Linux 系统上安装 32 位和 64 位库来运行我们的应用程序。在这里,我们谈论的是为特定架构编译的 C/C++ 库。

我们有时可能想知道给定的库是 32 位还是 64 位。在这个简短的教程中,我们将学习几种确定库格式的方法。

2. 共享库和静态库

库将一组预编译的代码组合到一个文件中,以便可以在不同的程序中使用。

在 Linux 中,我们有两种类型的库:

  • 静态——在编译时静态绑定到程序,通常命名为“ *.a
  • Shared — 在程序启动时加载并在运行时加载到内存中,通常命名为“ *.so

静态库不是可执行文件。相反,它是ar 格式 的文件。它只是其他文件的存档,例如ELF 目标文件

另一方面,共享库是 ELF 文件

ELF 标头定义库是使用 32 位还是 64 位地址。

在本教程中,我们将使用fileobjdump 命令来确定库的格式。我们将看看这如何适用于静态库和共享库。

3. 使用file命令

file命令是检查文件类型的便捷实用程序。我们可以使用file 来告诉我们库的格式。

3.1.共享库

首先,让我们在两个共享库上对其进行测试:

$ file /usr/lib/libc-2.33.so
/usr/lib/libc-2.33.so: ELF 64-bit LSB shared object, x86-64, version 1 (GNU/Linux), dynamically linked, ....
$ file /usr/lib32/libc-2.33.so
/usr/lib32/libc-2.33.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (GNU/Linux), dynamically linked, ...

在这里,我们在 32 位和 64 位库文件上执行了文件。正如我们所见,file命令读取 ELF 头并报告每个库的详细信息,包括它使用的地址宽度。

3.2. 静态库

接下来,让我们对静态库进行类似的测试:

$ file /usr/lib/libc.a
/usr/lib/libc.a: current ar archive
$ file /usr/lib32/libc.a
/usr/lib32/libc.a: current ar archive

这一次,file命令只是告诉我们它们是ar档案,但不报告它们是 32-bit 还是 64-bit。 这是因为静态库只是一个存档而不是 ELF 文件。file命令不会查看静态库中的所有 ELF 目标文件并读取它们的标题。

4. 使用objdump命令

objdump命令是GNU Binutils 包的成员 。它显示来自目标文件的信息。

我们可以使用*-f*选项来读取 ELF 文件的标头。

4.1. 共享库

首先,让我们看看 如果我们在一些共享库上执行objdump会输出什么:

$ objdump -f /usr/lib/libc-2.33.so
/usr/lib/libc-2.33.so:     file format elf64-x86-64
architecture: i386:x86-64, flags 0x00000150:
HAS_SYMS, DYNAMIC, D_PAGED
start address 0x0000000000027c60
$ objdump -f /usr/lib32/libc-2.33.so
/usr/lib32/libc-2.33.so:     file format elf32-i386
architecture: i386, flags 0x00000150:
HAS_SYMS, DYNAMIC, D_PAGED
start address 0x0001ebc0

在上面的输出中,“文件格式”字段报告 ELF 文件使用 64 位 ( elf64-… ) 或 32 位 ( elf32-… ) 地址。

因此,“ /usr/lib/libc-2.33.so ”文件是64位库,另一个是32位库。此外,如果我们查看它们的“起始地址”字段,它们分别具有 64 位和 32 位宽的地址。

4.2. 静态库

接下来,让我们在静态库上运行相同的命令:

$ objdump -f /usr/lib/libc.a
In archive /usr/lib/libc.a:
init-first.o:     file format elf64-x86-64
architecture: i386:x86-64, flags 0x00000011:
HAS_RELOC, HAS_SYMS
start address 0x0000000000000000
libc-start.o:     file format elf64-x86-64
architecture: i386:x86-64, flags 0x00000011:
HAS_RELOC, HAS_SYMS
start address 0x0000000000000000
sysdep.o:     file format elf64-x86-64
architecture: i386:x86-64, flags 0x00000000:
start address 0x0000000000000000
...

上面的输出显示了objdump命令处理静态库中输出其 ELF 标头的所有目标文件。

**此解决方案有效,但可以产生大量输出。**例如,上面的输出运行超过 10,000 行。

4.3. 获得直接的输出

为了总结 ELF 头信息,我们可以通过管道将objdump的输出传递给awk ,以通过search 和 replace 提取文件格式值,并删除重复项

$ objdump -f /usr/lib/libc.a | awk 'sub(/.*file format /,"") && !a[$0]++'
elf64-x86-64

现在,输出意味着静态库中的所有目标文件都使用 64 位地址。所以,我们可以说*/usr/lib/libc.a*是一个 64 位的静态库。

最后,让我们在 32 位静态库上测试该命令:

$ objdump -f /usr/lib32/libc.a | awk 'sub(/.*file format /,"") && !a[$0]++'
elf32-i386

“ elf32-*”表示库中的所有目标文件都使用 32 位地址。因此,它是一个 32 位库。