Position-Independent code on Mips

Position-Independent code on Mips

Robbert Haarman


Posted by inglorion
at 2014-10-28 12:51:23

As on other architectures, position-independent code for MIPS on GNU/Linux is accomplished with the help of a global offset table. This table contains the addresses of symbols used by the code. Instead of using the address of a symbol directly, as one would in non-position-independent code, a reference to a symbol is resolved by looking up the symbol's entry in the global offset table and then using the address stored there. Of course, we still need to find the address of the global offset table (abbreviated GOT).

On Mips on GNU/Linux, functions are passed the address of their entry point in register $25. The global offset table is at a fixed offset to this. By convention, $28 is used to hold the address of the GOT. The correct value can be computed as follows:

lui $28, %hi(_gp_disp)
addiu $28, %lo(_gp_disp)
addu $28, $28, $25

This is what the GNU assembler's .cpload $25 pseudo-op expands to.

Once you have the address of the global offset table in $28, you can get the address of a symbol that your object imports or exports by doing something like

lw $2, %got(foo)($28)

where foo is the name of your symbol. This would store the address foo is at in register $2, assuming $28 holds the address of the GOT.

However, for symbols that are defined in your object but not exported, the situation is slightly different. For such symbols, you need to also add the %lo of your symbol's address to the address you get from the GOT. So, for symbols that aren't imported or exported, but defined in the same object as your code, the position-independent way to get the address of the symbol is

lw $2, %got(foo)($28)
addiu $2, %lo(foo)