What does "a GP/function address pair" mean in Itanium C++ ABI? What does GP stand for?
相关问题
- Uncaught Error: Returned values aren't valid,
- What does the 'm' in a Python ABI tag mean
- Architectures and ABI Compatiblity
- ABI-Compatibility of visual studio c-libraries
- Difference in ABI between x86_64 Linux functions a
相关文章
- Difference in ABI between x86_64 Linux functions a
- Difference between arm-none-eabi and arm-linux-gnu
- STL Containers and Binary Interface Compatibility
- Is the Java Native Interface (JNI) affected by C++
- How to expose STL list over DLL boundary?
- X86-64 NASM calling extern c functions
- APK completely shadowed with multiple ABI APKs
- Which registers are safe to use in a function (x86
Short explanation:
gp
is, for all practical means, a hidden parameter to all functions that comply with the Itanium ABI. It's a kind ofthis
pointer to the global variables the function uses. As far as I know, no mainstream OS does it anymore.GP stands for "globals pointer". It's a base address for data statically allocated by executables, and the Itanium architecture has a register just for it.
For instance, if you had these global variables and this function in your program:
The gp/function pair would conceptually be
&foo, &func
. The code generated forfunc
would refer togp
to find where the globals are located. The compiler knowsfoo
can be found atgp
,bar
can be found atgp + 4
andbaz
can be found atgp + 8
.Assuming
func
is defined in an external library, if you call it from your program, the compiler will use a sequence of instructions like this one:func
into some register;This makes executables fully position-independent since they don't ever store absolute addresses to data symbols, and therefore makes it possible to maintain only one instance of any executable file in memory, no matter how many processes use it (you could even load the same executable multiple times within a single process and still only have one copy of the executable code systemwide), at the cost of making function pointers a little weird. With the Itanium ABI, a function pointer is not a code address (like it is with "regular" x86 ABIs): it's an address to a gp value and a code address, since that code address might not be worth much if it can't access its global variables, just like a method might not be able to do much if it doesn't have a
this
pointer.The only other ABI I know that uses this concept was the Mac OS Classic PowerPC ABI. They called those pairs "transition vectors".
Since x86_64 supports RIP-relative addressing (x86 did not have an equivalent EIP-relative addressing), it's now pretty easy to create position-independent code without having to use an additional register or having to use "enhanced" function pointers. Code and data just have to be kept at constant offsets. Therefore, this part of the Itanium ABI is probably gone for good on Intel platforms.
From the Itanium Register Conventions:
Just a comment about this quote from the other answer:
What this is talking about: Itanium has three different ways to put a value into a register (where 'immediate' here means 'offset from the base'). You can support a full 64 bit offset from anywhere, but it takes two instructions:
Not only does that take 2 separate clocks, it takes 3 instruction slots across 2 bundles to make that happen.
There are two shorter versions:
add14
(alsoadds
) andadd22
(alsoaddl
). The difference was in the immediate size each could handle. Each took a single 'A' slot iirc, and completed in a single clock.add14
could use any register as the source & target, but could only handle up to 14 bit immediates.add22
could use any register as the target, but for source, only two bits were allocated. So you could only user0
,r1
,r2
,r3
as the source regs.r0
is not a real register - it's hardwired to 0. But using one of the other 3 as a local stack registers, means you can address 256 times the memory using simple offsets, compared to using the local stack registers. Therefore, if you put your global base address intor1
(the convention), you could access that much more local offsets before having to do a separate movl and/or modifying gp for the next section of code.