如何解决`var@GOTPCREL(%rip)` 是什么意思?
<some symbol>@GOTPCREL(%rip)
是什么意思?
我遇到过这行 mov var@GOTPCREL(%rip),%rax
并且对奇怪的语法有点困惑。
有人可以推荐我应该阅读的相关文档以了解这一点吗? 谢谢!
解决方法
foo@GOTPCREL(%rip)
是符号 foo
的 GOT 条目,使用 RIP 相对寻址模式访问。
GOT入口由动态链接器填充(支持符号插入),保存符号foo
的绝对地址,所以mov var@GOTPCREL(%rip),%rax
将&foo
加载到RAX 。 https://en.wikipedia.org/wiki/Global_Offset_Table。通常后面跟着 mov (%rax),%eax
或类似的,以便在共享库中实际获取全局变量(如 int foo;
)的值,其中我们对符号的定义可能不是主要可执行文件正在使用的符号。 (参见 Thiago Macieira 的博客:2012 年的 Sorry state of dynamic libraries on Linux;它早于 gcc -fno-plt
,也早于 PIE executables,但共享库访问全局变量的情况并没有改善。)>
通常,您只会将 foo@GOTPCREL(%rip)
用于全局变量地址 in a shared library,而不是可执行文件(甚至不是 PIE 可执行文件)。编译器假定主可执行文件的全局变量不会被符号插入“遮蔽”。 (在共享库中,您可以give symbols "hidden" ELF visibility so compilers will access them directly,知道它们不会参与符号插入。)
对于int foo
,只需mov foo(%rip),%eax
加载它或lea foo(%rip),%rdi
获取其地址而无需通过GOT。
但是对于函数调用,如果你想要一个指向像sin
这样的库函数的指针,你当然可以通过从sin@GOTPCREL
加载一个指针来获得libm本身的最终地址,而不是仅仅取一个使用 mov $sin,%edi
指向其 PLT 存根的指针(并在您静态链接的任何内容中找不到符号时,让链接器将 sin 重写为 sin@plt,只有共享库)。 GCC 选择使用哪个取决于您的编译方式。 (PIE 与传统的位置相关,和/或 -fno-plt
与否。)Unexpected value of a function pointer local variable
或者像 gcc -fno-plt
模式一样,使用 call *sin@gotpcrel(%rip)
调用库函数以通过其 GOT 条目使用间接调用,基本上内联 PLT 存根几乎相同的内容,并强制提前绑定而不是延迟(在启动时解析 GOT 条目,而不是在第一次调用时。)
NASM 等价物是 call [rel printf wrt ..got]
。
请注意 foo(%rip)
uses the relative offset from here to the foo
label/symbol,不要像您可能猜到的那样将其绝对地址添加到该指令的末尾,或者像 123(%rip)
那样。但该
GOTPCREL 的 PCREL 部分显然是指从这里到 GOT 条目的 PC 相对偏移量。
与@gotpcrel 类似,您可以执行 call printf@plt
之类的操作,通过 PLT 条目显式调用函数。不幸的是,我没有在 GNU as
手册中找到 @gotpcrel 的文档。 https://sourceware.org/binutils/docs/as/。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。