问题标签 [got]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
assembly - PIC 代码中的位置相关数据类型部分?
我有一个依赖于几个共享库的二进制文件,我想生成一个 PIC 二进制文件,除了一个只读表。
我希望所有代码部分都能够在不遵守.GOTPCREL
. 我不关心该表驻留在哪种数据段(.bss
、.data
或等)中,但我希望它肯定是只读的,并且可以由所有共享库和主二进制文件直接访问。因此,我想它应该进入二进制而不是共享库之一。
目前我将它放在.data.rel.ro
部分中并且它是只读的,但是为了访问它的数据,我需要通过.GOT
这样的方式获取它的地址:TABLENAME@GOTPCREL(%rip)
然后使用该地址。我问这个的原因是我想使用bt
指令并给它表的地址,我需要两条指令,还有一个临时寄存器。如果表不可重定位,我可以在链接阶段给出它的地址,例如:bt %REG, TABLENAME
,只需要一条指令而无需任何额外的寄存器。
这是可以实现的吗?
这是一个更具体的例子:
主程序代码:
共享库之一:
cmake - 如何在 valgrind 中抑制 GOT 的“无效读取”警告?
我正在运行 valgrind memcheck 作为单元测试的一部分。Valgrind 为特定的测试视图发出“大小为 8 的无效读取”并修改进程的 GOT(全局偏移表)。我想最好仅针对 GOT 禁止此警告(即应发出其他“无效读取”警告)。有没有办法在不定义 valgrind 抑制文件的情况下做到这一点?作为论点的一部分,我可以通过 CMake/CTest 传递给 valgrind?
linux - 每个进程如何在共享库中拥有自己的全局数据副本
我知道由于共享库不知道动态加载器将它们放置在哪里,它们必须依靠 GOT 来解析对全局数据的所有引用。例如,一个共享库有一个名为 的全局变量globe
,访问该变量的可能方法是这样的mov eax,DWORD PTR [ecx-0x10]
,假设它ecx
包含 GOT 的地址和 is 的偏移globe
量0x10
。现在,假设进程 A 使用此共享库,紧随其后的是进程 B。我知道共享库的代码可以在进程之间共享,但数据不能,因为每个进程都可能根据其执行情况更改数据。因此,每个进程都会得到它自己的 GOT,这意味着,多亏了虚拟内存,地址ecx + 0x10
将指向完全两个不同的 GOT,具体取决于运行该代码的进程。0x10
但是然后说其中一个进程在其 GOT中的偏移量处加载具有不同全局数据成员的第二个共享库。如果两个库都在同一个虚拟地址,那么使用这两个库的进程如何访问每个库的全局数据?
c++ - 为什么要对共享库本身中定义的符号使用全局偏移表?
考虑以下简单的共享库源代码:
库.cpp:
-fPIC
使用clang 中的选项编译,它会产生这个对象程序集(x86-64):
由于符号是在库中定义的,因此编译器按预期使用 PC 相对寻址:mov eax, dword ptr [rip + global]
但是,如果我们更改static int global = 10;
为int global = 10;
使其成为具有外部链接的符号,则生成的程序集是:
正如您所看到的,编译器在全局偏移表中添加了一个间接层,在这种情况下这似乎完全没有必要,因为符号仍然在同一个库(和源文件)中定义。
如果符号是在另一个共享库中定义的,则 GOT 将是必要的,但在这种情况下,它感觉是多余的。为什么编译器仍在将这个符号添加到 GOT 中?
注意:我相信这个问题与此类似,但是可能由于缺乏细节,答案并不相关。
elf - 关于 ELF header 中 GOT & PLT 结构的必要性
在某些可以使用 PC(RIP) 相对寻址模式引用数据 (mov eg) 和代码 (jmp, call) 的架构(如 x86_64)中,是否真的有技术原因证明需要这种结构(got, plt ) ?
我的意思是,如果我想将全局数据(例如)移动到寄存器中,我可以执行以下指令(标准 PIE):
mov rax,QWORD PTR [rip+0x2009db]
mov eax,DWORD PTR [rax]
(其中 0x2009db 是 rip 和 get 中包含符号地址的正确条目之间的偏移量)
为什么我们不能做这样的事情:
mov rax, 翻录+0xYYYYYY
mov eax,DWORD PTR [rax]
(0xYYYYYYY 是 RIP 值和符号之间的直接增量(例如全局变量))
我不习惯做 ASM,所以我的例子可能是错误的。但我的想法是:为什么不简单地根据 RIP 计算符号的绝对地址,将其放入 EAX,然后访问其内容。如果指令集允许使用相对寻址做任何我们想做的事情,为什么要使用这样的结构 (got, plt) ?
同样的问题也适用于 call/jmp 指令。
是因为指令集不允许吗?是不是因为偏移值不能覆盖整个地址空间?但是..重要吗?由于一个节的结构被维护一个映射到进程的虚拟寻址空间(例如.dat 节后跟.got 或类似的东西)。我的意思是,为什么直接引用符号地址而不是 get 中的入口地址时偏移量会更大?其他原因?
谢谢 !
c++ - 如何借助模板元编程测试全局偏移表的限制大小?
我想测试 gcc 的global offset table的限制。IIUC,我需要外部变量或共享库函数的色调才能达到限制,可以使用模板元编程作为代码生成工具来获得限制吗?
如果 tmp 不可行,还有其他简单的方法吗?
c++ - 如何填写全局偏移表?
动机:
我想在我的 arch(x86) 上测试 gcc 对全局偏移表的限制大小。
我做了什么:
在共享库中使用多个未声明的函数 ( gcc -nostdlib -shared -o got.so ./got.c
)
和readelf --relocs ./got.so
:
如上所示,全局偏移表由 填充fun1-8
,但要填充到限制大小,还远远不够。我可以想到两种方法:
- 使用像 emacs 这样不错的编辑器来生成更多这样的功能
- 使用一个像样的代码生成器在预处理时生成这样的代码,比如宏(但我找不到宏的解决方案)
当然,可能还有更多方法可以实现这一目标。
问题:
如何达到全局偏移表的极限?
linux - How to access a C global variable through GOT in GAS assembly on x86-64 Linux?
My problem
I am trying to write a shared library(not an executable, so please do not tell me to use -no-pie
) with assembly and C in separate files(not inline assembly).
And I would like to access a C global variable through Global Offset Table in assembly code, because the function called might be defined in any other shared libraries.
I know the PLT/GOT stuff but I do not know for sure how to tell the compiler to correctly generate relocation information for the linker(what is the syntax), and how to tell the linker to actually relocate my code with that information(what is the linker options).
My code compiles with a linking error
Furthermore, it would be better if someone could share some detailed documentation on the GAS assembly about relocation. For example, an exhaustive list on how to interpolate between C and assembly with GNU assembler.
Source Code
Compile the C and assembly code and link the into ONE shared library.
Expectation and Result
I expect the linker to happily link my object files but it says
and commenting out the line
makes the error disappear.
Solution.
The keyword GOTPCREL
will tell the compiler this is a PC-relative relocation to GOT table. The linker will calculate the offset from current rip
to the target GOT table entry.
You can verify with
Thanks to Peter.
Some information that might be related or not
1. I can call a C function withobjdump
shows it calls into the correct PLT entry.
lea
a PLT entry address correctly
0xffffff23 is -0xdd, 0x1109 - 0xdd = 102c
Environment
- Arch Linux 20190809
rust - 为什么完全静态的 Rust ELF 二进制文件有一个全局偏移表 (GOT) 部分?
x86_64-unknown-linux-musl
此代码在为目标编译时会生成一个.got
部分:
根据类似 C 代码的这个答案.got
,该部分是可以安全删除的工件。但是,它对我来说是段错误:
查看反汇编,我看到 GOT 基本上保存了静态函数地址:
数字404350
来自50434000 00000000
,它是一个小端序0x00000000000404350
(这并不明显;我必须在 GDB 下运行二进制文件才能弄清楚!)
这很令人困惑,因为维基百科说
[GOT] 被执行程序用于在运行时查找全局变量的地址,在编译时是未知的。全局偏移表由动态链接器在进程引导中更新。
- 为什么会出现 GOT?从反汇编来看,编译器似乎知道所有需要的地址。据我所知,动态链接器没有进行引导:我的二进制文件中既没有
INTERP
也没有DYNAMIC
程序头; - 为什么 GOT 存储函数指针?维基百科说 GOT 仅用于全局变量,函数指针应包含在 PLT 中。
linux - 当涉及多个共享库时,GOT 如何工作?
假设有多个共享库链接到一个可执行文件。假设 libaaa.so 引用了一个全局变量aaa
,而 libbbb.so 引用了一个全局变量bbb
。
我的理解是代码通过 GOT 使用偏移量间接访问这些变量。我无法理解 libaaa.so 中的偏移量aaa
和 libbbb.so 中的偏移量如何bbb
设法避免相互冲突。
共享库的代码是如何生成的,以使所有库中的所有引用都以 GOT 中的不同偏移量结束?
我确定我错过了一些愚蠢的东西。