简短说明:gp对于所有实际方法,是所有符合 Itanium ABI 的函数的隐藏参数。它是一种this指向函数使用的全局变量的指针。据我所知,没有主流操作系统再这样做了。
GP 代表“全局指针”。它是由可执行文件静态分配的数据的基地址,安腾架构有一个专门用于它的寄存器。
例如,如果你的程序中有这些全局变量和这个函数:
int foo;
int bar;
int baz;
int func()
{
foo++;
bar += foo;
baz *= bar / foo;
return foo + bar + baz;
}
Run Code Online (Sandbox Code Playgroud)
gp/函数对在概念上是&foo, &func. 生成的代码func将引用gp查找全局变量所在的位置。编译器知道foo可以在 处找到gp,bar可以在 处找到gp + 4并且baz可以在 处找到gp + 8。
假设func 在外部库中定义,如果从程序中调用它,编译器将使用如下指令序列:
func到某个寄存器中;这使得可执行文件完全与位置无关,因为它们从不存储数据符号的绝对地址,因此可以在内存中仅维护任何可执行文件的一个实例,无论有多少进程使用它(您甚至可以加载在单个进程中多次执行相同的可执行文件,并且在系统范围内仍然只有一份可执行代码的副本),代价是使函数指针有点奇怪。对于 Itanium ABI,函数指针不是代码地址(就像“常规”x86 ABI 一样):它是 gp 值和代码地址的地址,因为如果可以的话,该代码地址可能不值多少钱' t 访问它的全局变量,就像一个没有this指针的方法可能无法做很多事情一样。
我所知道的唯一使用此概念的其他 ABI 是 Mac OS Classic PowerPC ABI。他们称这些对为“过渡向量”。
由于 x86_64 支持 RIP 相对寻址(x86 没有等效的 EIP 相对寻址),现在创建与位置无关的代码非常容易,而无需使用额外的寄存器或使用“增强型”函数指针。代码和数据必须保持恒定的偏移量。因此,这部分 Itanium ABI 可能在 Intel 平台上一去不复返了。
从安腾注册公约:
8.2 gp 寄存器
每个引用静态分配数据或调用另一个过程的过程都需要一个指向 gp 寄存器中其数据段的指针,以便它可以访问其静态数据及其链接表。每个加载模块都有自己的数据段,并且在调用该加载模块内的任何入口点之前必须正确设置 gp 寄存器。
链接约定要求每个加载模块准确定义一个 gp 值来引用其短数据段内的位置。预计选择这个位置是为了最大限度地提高短位移立即指令对标量和链接表条目的寻址的有用性。DLL 加载器将在将其数据段加载到内存中后,为每个加载模块确定 gp 寄存器的绝对值。
对于加载模块内的调用,gp 寄存器将保持不变,因此可以相应地优化已知为本地的调用。
对于加载模块之间的调用,必须使用新加载模块的正确 gp 值初始化 gp 寄存器,并且调用函数必须确保保存和恢复其自身的 gp 值。
| 归档时间: |
|
| 查看次数: |
644 次 |
| 最近记录: |