Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 查找在ELF文件中使用符号的用户_C_Linux_Elf_Linkage - Fatal编程技术网

C 查找在ELF文件中使用符号的用户

C 查找在ELF文件中使用符号的用户,c,linux,elf,linkage,C,Linux,Elf,Linkage,我有一个大的二进制文件,它包含一个符号。我可以在nm或objdump中看到符号 我知道使用了该符号,因为否则链接器不会包含它(更准确地说,我知道使用了同一源文件中的某个符号)。 我想知道它到底是怎么用的 如果引用是由函数(例如调用函数的函数、使用全局变量的函数)生成的,我可以使用objdump-rd反汇编文件并查找引用。 但是,如果引用是由一个变量(例如初始化为指向某个变量的全局指针)进行的,反汇编不会显示它。 我找不到任何这样做的方法 这里有一个例子来说明这一点。在本例中,很明显是谁使用了x,

我有一个大的二进制文件,它包含一个符号。我可以在
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
我编译了相同的代码(和相同的命令),并运行了
objdump-xmain.o
。有一个部分

RELOCATION RECORDS FOR [.data]:
OFFSET           TYPE              VALUE
0000000000000000 R_X86_64_64       x
这意味着它是一个64位重定位记录(
R\u X86\u 64\u 64
)。它位于数据段中的偏移量0处(这是数据段中y的偏移量)。要重新定位的值是
x
(实际上是变量
x
的地址,因为它是标签)

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

extern int ** z = &y;
现在符号表看起来像-

0000000000000000 l     O .data  0000000000000008 y
0000000000000008 l     O .data  0000000000000008 z
0000000000000000 R_X86_64_64       x
0000000000000008 R_X86_64_64       .data
第一个显示数据部分中两个变量的偏移量,第二个数字是它们的大小

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

0000000000000000 l     O .data  0000000000000008 y
0000000000000008 l     O .data  0000000000000008 z
0000000000000000 R_X86_64_64       x
0000000000000008 R_X86_64_64       .data
您可以看到现在有两个条目。一个用于存储在
y
中的
x
地址(偏移量0),另一个用于存储在
z
中的
y
地址(偏移量8)。您看到的不是
y
,而是
.data
,因为数据段的地址与
y的地址相同,因为
y
位于偏移量
0


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

这是我找到的方法。它适用于这个简单的例子,但不幸的是不适用于我的真实案例。我不知道有什么区别

我正在寻找二进制
main
中symbol
x
的用户:

$ objdump -t main | grep -w x
0000000000000000 l    df *ABS*  0000000000000000              x.c
0000000000601040 g     O .data  0000000000000004              x
所以x在偏移量
00601040
中。我寻找这个地址,颠倒过来(我想是因为endianity):

因此
.data
中偏移量
601030
处的符号包含此地址

$ objdump -t main | grep 601030
0000000000601030 g     O .data  0000000000000008              y
因此,参考来自
y


在我的实际情况中,地址在
.dynsym
部分中找到,并且
objdump-t
在那里找不到任何符号。

main.o
将在x的数据部分中有一个重定位条目。让我复制并展示确切的措辞。谢谢。但是单独检查二进制
main
是否可以找到它?重新创建中间文件并不总是那么简单。@ugoren可执行文件也存在相同的重新定位表。因为这些是64位引用。虽然如果二进制文件被剥离,一些名称可能已经消失,但重新定位项在
main
中不存在。我没有去掉它-我编译的和我的问题完全一样。@ugoren哦,那是因为gcc链接器丢弃了重定位表,因为可执行文件通常是不可重定位的。i、 它们总是在同一地址执行。您可以将(您的最后一个命令)链接为
gcc-Wl,-q…
以指示
gcc
保留重定位表。