简体   繁体   English

`var@GOTPCREL(%rip)` 是什么意思?

[英]What does `var@GOTPCREL(%rip)` mean?

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

I've come across this line mov var@GOTPCREL(%rip), %rax and was a bit puzzled about the weird syntax.我遇到了这条线mov var@GOTPCREL(%rip), %rax并且对奇怪的语法有点困惑。

Can someone please recommend the relevant docs I should read to understand this?有人可以推荐我应该阅读的相关文档来理解这一点吗? Thanks!谢谢!

foo@GOTPCREL(%rip) is the GOT entry for the symbol foo , accessed with a RIP-relative addressing mode. foo@GOTPCREL(%rip)是符号foo的 GOT 条目,使用 RIP 相对寻址模式访问。

The GOT entry is filled in by the dynamic linker (supporting symbol interposition), and holds the absolute address of the symbol foo , so mov var@GOTPCREL(%rip), %rax loads &foo into RAX . GOT 条目由动态 linker(支持符号插入)填充,并保存符号foo的绝对地址,因此mov var@GOTPCREL(%rip), %rax&foo加载到 RAX中。 https://en.wikipedia.org/wiki/Global_Offset_Table . https://en.wikipedia.org/wiki/Global_Offset_Table Often this is followed by mov (%rax), %eax or similar to actually get the value of a global variable like int foo;通常这之后是mov (%rax), %eax或类似的,以实际获取全局变量的值,如int foo; , in a shared library where our definition of the symbol may not be the one the main executable is using. ,在一个共享库中,我们对符号的定义可能不是主要可执行文件使用的那个。 (See Thiago Macieira's blog: Sorry state of dynamic libraries on Linux from 2012; it pre-dates gcc -fno-plt , and also predates PIE executables , but the situations for shared libraries accessing global variables hasn't improved.) (See Thiago Macieira's blog: Sorry state of dynamic libraries on Linux from 2012; it pre-dates gcc -fno-plt , and also predates PIE executables , but the situations for shared libraries accessing global variables hasn't improved.)

Normally you'd only ever use foo@GOTPCREL(%rip) for a global variable address in a shared library , not an executable (not even a PIE executable).通常,您只会将foo@GOTPCREL(%rip)用于共享库中的全局变量地址,而不是可执行文件(甚至不是 PIE 可执行文件)。 Compilers assume that the main executable's global vars won't be "shadowed" by symbol interposition.编译器假定主可执行文件的全局变量不会被符号插入“遮蔽”。 (In a shared library, you can give symbols "hidden" ELF visibility so compilers will access them directly , knowing they won't participate in symbol interposition.) (在共享库中,您可以为符号“隐藏”ELF 可见性,以便编译器直接访问它们,知道它们不会参与符号插入。)

For int foo , just mov foo(%rip), %eax to load it or lea foo(%rip), %rdi to take its address without going through the GOT.对于int foo ,只需mov foo(%rip), %eax加载它或lea foo(%rip), %rdi获取它的地址而不通过 GOT。


But for function calls, if you want a pointer to a library function like sin , you can certainly get the final address in libm itself from loading a pointer from sin@GOTPCREL , instead of just taking a pointer to its PLT stub with mov $sin, %edi (and letting the linker rewrite sin to sin@plt when the symbol isn't found in anything you're statically linking, only a shared lib).但是对于 function 调用,如果你想要一个指向库 function 的指针,比如sin ,你当然可以通过从sin@GOTPCREL加载指针来获取 libm 本身的最终地址,而不是仅仅使用mov $sin, %edi获取指向其 PLT 存根的指针mov $sin, %edi (并让 linker 将 sin 重写为 sin@plt,当您在静态链接的任何内容中找不到符号时,只有共享库)。 GCC's choice of which do use depends on how you're compiling. GCC 选择使用哪个取决于您的编译方式。 (PIE vs. traditional position-dependent, and/or -fno-plt or not.) Unexpected value of a function pointer local variable (PIE 与传统的位置相关,和/或-fno-plt与否。) function 指针局部变量的意外值

Or like gcc -fno-plt mode, call library functions with call *sin@gotpcrel(%rip) to use an indirect call through its GOT entry, basically inlining almost the same thing the PLT stub would, and forcing early binding instead of lazy (resolve the GOT entries at startup, instead of on first call.)或者像gcc -fno-plt模式,使用call *sin@gotpcrel(%rip)调用库函数以通过其 GOT 条目使用间接调用,基本上内联几乎与 PLT 存根相同的东西,并强制早期绑定而不是惰性(在启动时解决 GOT 条目,而不是在第一次调用时。)

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


Note that foo(%rip) uses the relative offset from here to the foo label/symbol , not adding its absolute address to the end of this instruction like you might guess, or like 123(%rip) does.请注意, foo(%rip) 使用从此处到foo标签/符号的相对偏移量,而不是像您可能猜到的那样将其绝对地址添加到该指令的末尾,或者像123(%rip)那样。 But the PCREL part of GOTPCREL is clearly referring to a PC-relative offset to the GOT entry from here.但是 GOTPCREL 的 PCREL 部分显然是指从这里到 GOT 条目的 PC 相对偏移量。


Similar to @gotpcrel, you can do stuff like call printf@plt to explicitly call a function through a PLT entry.与@gotpcrel 类似,您可以执行诸如call printf@plt之类的操作,以通过 PLT 条目显式调用 function。 I didn't find @gotpcrel documented in the GNU as manual, unfortunately.不幸的as ,我没有在 GNU 手册中找到 @gotpcrel 文档。 https://sourceware.org/binutils/docs/as/ . https://sourceware.org/binutils/docs/as/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM