是什么<some symbol>@GOTPCREL(%rip)
意思?
我遇到了这条线mov var@GOTPCREL(%rip), %rax
,对奇怪的语法有点困惑。
有人可以推荐我应该阅读的相关文档来理解这一点吗?谢谢!
是什么<some symbol>@GOTPCREL(%rip)
意思?
我遇到了这条线mov var@GOTPCREL(%rip), %rax
,对奇怪的语法有点困惑。
有人可以推荐我应该阅读的相关文档来理解这一点吗?谢谢!
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@GOTPCREL
(mov $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)
使用从此处到foo
label/symbol的相对偏移量,而不是像您可能猜到的那样将其绝对地址添加到该指令的末尾,或者像123(%rip)
这样。但是 GOTPCREL 的 PCREL 部分显然是指从这里到 GOT 条目的 PC 相对偏移量。
与@gotpcrel 类似,您可以执行诸如call printf@plt
通过 PLT 条目显式调用函数之类的操作。不幸的是,我没有在 GNUas
手册中找到 @gotpcrel 文档。 https://sourceware.org/binutils/docs/as/。