Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Define GOT-Relative data relocation #221

Closed
PiJoules opened this issue Sep 26, 2023 · 3 comments
Closed

Define GOT-Relative data relocation #221

PiJoules opened this issue Sep 26, 2023 · 3 comments

Comments

@PiJoules
Copy link
Contributor

We would like to introduce a new relocation type that works similarly to x86’s R_X86_64_GOTPCREL relocation.

In the “GOT-relative data relocations” section of aaelf64.rst, we would add a new type “R_<CLS>_GOTPCREL32” that follows the existing wording to “R_<CLS>_GOTREL32”, but instead evaluates to the 32-bit offset between a GOT entry for a given symbol and the current location where the relocation is applied, so its equation would be “G + GOT - P + A”.

The purpose of this relocation is to remove what we call “rtti_proxies” in the relative vtables C++ ABI. This ABI saves memory by moving vtables into .rodata by replacing each of the relocations that would constitute the vtable (R_RISCV_64, R_AARCH64_ABS64, R_X86_64_64) with PC-relative offsets, requiring no dynamic relocations. Instead of placing a pointer to each virtual method into the vtable, we would instead take the offset between the vtable and the virtual function which can be statically computed if the compiler knows both symbols are DSO-local. The same is done with the pointer to the RTTI object, but an issue here is the RTTI is not guaranteed to be DSO-local, so we must emit a DSO-local “proxy” symbol which points to the actual RTTI object, and take the offset to the proxy instead. This proxy is equivalent to a GOT entry, but in order to use the GOT entry, we’d need a relocation that points to the entry itself rather than just the start of the GOT.

The proxies work in the meantime, but this new relocation would allow us to effectively “move” those proxies to the GOT which will provide these benefits:

  1. It will reuse the same GOT slot across translation units without COMDAT machinery for each proxy, which reduces clutter and bloat in object files and streamlines linking by using simpler features with less bulk in the input files.
  2. It will reuse the same GOT slot as a non-vtable reference to the same symbol would.
  3. The GOT is tightly packed in the RELRO segment, whereas the proxy symbols will be placed in arbitrary parts of the .data.rel.ro section.

This could also be used for other PIC-friendly optimizations we’d like to implement that aren’t specific to vtables.

We have a WIP patch that implements this for x86_64, but does not yet work for AArch64. What steps can we take to add this relocation?

@smithp35
Copy link
Contributor

Thanks for the suggestion and the motivating details. If I've understood this correctly this is a data relocation, that generates a GOT entry, and resolves to the 32-bit pc-relative offset to that GOT entry. The GOT entry may point to an entity that isn't DSO local so this may require a dynamic relocation.

I think the expression we use for that for the equivalent instruction relocations is G(GDAT(S+A))- P
GDAT(S+A) generates the GOT entry and the dynamic relocation R__GLOB_DAT(S+A).
G(GDAT(S+A)) is the address of that GOT entry
G(GDAT(S+A)) - P is the offset to the GOT entry.

I note that no linker currently implements the GDAT(S+A) correctly, I think LLD would implement as G(GDAT(S)) - P + A and GNU ld would ignore the addend A (#217) that is probably best handled by issue 217 so I suggest we keep the expression consistent.

I think this would result in:

GOT-relative data relocation
...
315 | - | R_<CLS>_GOTREL32 | G(GDAT(S+A))- P | Write bits [31:0] of X at byte-aligned place P. This represents a 32-bit offset relative to GOT, treated as signed; Check that -2^31 <= X < 2^31 |

I think the fastest way to progress this would be to submit a pull request with the suggested changes. Otherwise it is waiting for someone to write it up.

To me (as an individual) the proposal looks reasonable. I'm wondering if it is worth defining a 64-bit R__GOTREL64 while we are here. My instinct is that we wait till something needs it.

@PiJoules
Copy link
Contributor Author

Thanks for the suggestion and the motivating details. If I've understood this correctly this is a data relocation, that generates a GOT entry, and resolves to the 32-bit pc-relative offset to that GOT entry. The GOT entry may point to an entity that isn't DSO local so this may require a dynamic relocation.

Correct

I think the expression we use for that for the equivalent instruction relocations is G(GDAT(S+A))- P GDAT(S+A) generates the GOT entry and the dynamic relocation R__GLOB_DAT(S+A). G(GDAT(S+A)) is the address of that GOT entry G(GDAT(S+A)) - P is the offset to the GOT entry.

Oh ok that makes sense. I actually didn't notice GDAT(S+A) before but that equation works also.

I note that no linker currently implements the GDAT(S+A) correctly, I think LLD would implement as G(GDAT(S)) - P + A and GNU ld would ignore the addend A (#217) that is probably best handled by issue 217 so I suggest we keep the expression consistent.

I think this would result in:

GOT-relative data relocation
...
315 | - | R_<CLS>_GOTREL32 | G(GDAT(S+A))- P | Write bits [31:0] of X at byte-aligned place P. This represents a 32-bit offset relative to GOT, treated as signed; Check that -2^31 <= X < 2^31 |

I think the fastest way to progress this would be to submit a pull request with the suggested changes. Otherwise it is waiting for someone to write it up.

Can do. Wanted some early feedback to see if there would be any hard no's.

To me (as an individual) the proposal looks reasonable. I'm wondering if it is worth defining a 64-bit R__GOTREL64 while we are here. My instinct is that we wait till something needs it.

I'm also in the boat of reserving it until it's needed.

@PiJoules
Copy link
Contributor Author

Submitted #223

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants