查找谁在 ELF 文件中使用符号

ugo*_*ren 5 c linux elf linkage

我有一个包含符号的大二进制文件。我可以在nm或 中看到符号objdump
我知道使用了该符号,否则链接器不会包含它(更准确地说,我知道使用了同一源文件中的某些符号)。
我试图找出它的使用方式。

如果引用是通过函数(例如函数调用函数,使用全局变量的函数),我可以使用objdump -rd反汇编文件并找到引用。
但是如果引用是由一个变量(例如一个全局指针初始化为指向某个变量),反汇编不会显示它。
我没有找到任何可以做到的方法。

这是一个演示它的示例。在这个例子中,很明显谁使用了x,但我不知道如何检查生成的二进制文件并找到它。

// x.c
int x = 3;

// main.c
extern int x;
static int *y = &x;
int main() { 
    return *y;
}

// Build process
gcc -o x.o -c x.c
ar r libx.a x.o
gcc -o main.o -c main.c
gcc -o main main.o -L. -lx
Run Code Online (Sandbox Code Playgroud)

Aja*_*iya 2

我编译了相同的代码(和相同的命令)并运行了objdump -x main.o. 有一个部分

RELOCATION RECORDS FOR [.data]:
OFFSET           TYPE              VALUE
0000000000000000 R_X86_64_64       x
Run Code Online (Sandbox Code Playgroud)

这意味着它是一个64位的重定位记录( R_X86_64_64)。它位于数据部分中的偏移量 0(这是数据部分中 y 的偏移量)。要重定位的值是x(实际上是变量的地址x,因为它是标签)。

为了更好地理解这一点,我添加了另一个变量 -

extern int ** z = &y;
Run Code Online (Sandbox Code Playgroud)

现在符号表看起来像 -

0000000000000000 l     O .data  0000000000000008 y
0000000000000008 l     O .data  0000000000000008 z
Run Code Online (Sandbox Code Playgroud)

第一个显示数据部分中两个变量的偏移量,第二个数字是它们的大小。

重定位表现在也看起来像 -

0000000000000000 R_X86_64_64       x
0000000000000008 R_X86_64_64       .data
Run Code Online (Sandbox Code Playgroud)

您可以看到现在有两个条目。一个 forx的地址存储在y(偏移量 0),另一个是 fory的地址存储在z(偏移量 8)。而不是y您看到的,因为数据部分的地址与因为位于 offset 处.data的地址相同。yy0

因此,通过查看重定位表,您可以找到所有变量(或函数)的绝对引用。