3

是什么<some symbol>@GOTPCREL(%rip)意思?

我遇到了这条线mov var@GOTPCREL(%rip), %rax,对奇怪的语法有点困惑。

有人可以推荐我应该阅读的相关文档来理解这一点吗?谢谢!

4

1 回答 1

4

foo@GOTPCREL(%rip)是符号 的 GOT 条目foo,使用 RIP 相对寻址模式访问。

GOT 条目由动态链接器(支持符号插入)填充,并保存符号的绝对地址foo,因此mov foo@GOTPCREL(%rip), %rax 加载&foo到 RAX中。 https://en.wikipedia.org/wiki/Global_Offset_Table。通常,这之后是mov (%rax), %eax或类似地实际获取全局变量的值,例如int foo;,在共享库中,我们对符号的定义可能不是主要可执行文件正在使用的符号。(参见 Thiago Macieira 的博客:Sorry state of dynamic library on Linux from 2012;它早于 PIE 可执行文件,gcc -fno-plt也早于PIE 可执行文件,但共享库访问全局变量的情况并没有改善。)

通常,您只会在共享库中foo@GOTPCREL(%rip)使用全局变量地址,而不是可执行文件(甚至不是 PIE 可执行文件)。编译器假定主可执行文件的全局变量不会被符号插入“遮蔽”。(在共享库中,您可以为符号“隐藏”ELF 可见性,以便编译器直接访问它们,知道它们不会参与符号插入。)

对于int foo,只需mov foo(%rip), %eax加载它或lea foo(%rip), %rdi获取它的地址而不通过 GOT。


但是对于函数调用,如果您想要一个指向库sin函数sin@GOTPCRELmov $sin, %edi如当在您静态链接的任何内容中找不到符号时,sin@plt,只有一个共享库)。GCC 选择使用哪个取决于您的编译方式。(PIE 与传统的位置相关,和/-fno-plt或不相关。) 函数指针局部变量的意外值

或者像gcc -fno-plt模式一样,调用库函数call *sin@gotpcrel(%rip)通过其 GOT 条目使用间接调用,基本上内联 PLT 存根几乎相同的东西,并强制早期绑定而不是惰性(在启动时解析 GOT 条目,而不是在第一次调用时。 )

NASM 等价物是call [rel printf wrt ..got].


请注意,foo(%rip) 使用从此处到foolabel/symbol的相对偏移量,而不是像您可能猜到的那样将其绝对地址添加到该指令的末尾,或者像123(%rip)这样。但是 GOTPCREL 的 PCREL 部分显然是指从这里到 GOT 条目的 PC 相对偏移量。


与@gotpcrel 类似,您可以执行诸如call printf@plt通过 PLT 条目显式调用函数之类的操作。不幸的是,我没有在 GNUas手册中找到 @gotpcrel 文档。 https://sourceware.org/binutils/docs/as/

于 2021-03-19T18:42:11.677 回答