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

Proposal: Add new relocation type R_WASM_MEMORY_ADDR_SELFREL_I32 #162

Open
kateinoigakukun opened this issue Feb 5, 2021 · 8 comments
Open

Comments

@kateinoigakukun
Copy link
Contributor

kateinoigakukun commented Feb 5, 2021

Summary

This R_WASM_MEMORY_ADDR_SELFREL_I32 relocation represents an offset between its relocating address and the symbol address. It's very similar to R_X86_64_PC32 but restricted to be used for only data segments.

S + A - P

A: Represents the addend used to compute the value of the relocatable field.
P: Represents the place of the storage unit being relocated.
S: Represents the value of the symbol whose index resides in the relocation entry.

Motivation

Currently, Swift uses R_X86_64_PC32 relocation in data sections on ELF. The relocation is used to express relative pointer which is used in Swift’s metadata. The relative pointer is a pointer that has a 32 bit offset from its own address to the referent’s address. This technique reduces the pointer size 64 bit to 32 bit on a 64bit addressing mode, and also reduces the load-time relocation on general environments.

Wasm doesn’t have a relocation type like R_X86_64_PC32 and doesn’t have any benefit of using the relative pointer on wasm32 because it doesn’t reduce pointer size and also Wasm doesn’t have load-time relocations. So we, SwiftWasm project, use 32-bit absolute pointers instead of relative pointers now.

However, using absolute pointers instead of relative pointers breaks the metadata layout on wasm64 due to the pointer size. If we can use relative pointers as same as other architectures, we can support wasm64 without changing the data structure. The same data structure will make it simple to debug and implement the compiler pipeline.
So we propose a new relocation type for data segments to use relative pointers.

What do you think about this feature? @sunfishcode @sbc100

@kateinoigakukun kateinoigakukun changed the title Proposal: Add new relocation type MEMORY_ADDR_SELFREL_I32 Proposal: Add new relocation type R_WASM_MEMORY_ADDR_SELFREL_I32 Feb 5, 2021
@sbc100
Copy link
Member

sbc100 commented Feb 5, 2021

Interesting. Sounds like there are some real benefits for your use case. I have a couple of questions:

  1. I the primary advantage here only present on wasm64? In which case we should loop in @aardappel.
  2. Would the relocation type still exist on wasm32? for convenience only? It seems like it would be strictly less performant on wasm32 because you would need to do a runtime addition, and an absolute relocation would work find here?
  3. I suppose the relocation would fail if the if the relocation location and the symbol are more then 4Gb apart?

@aardappel
Copy link

I am generally a fan of pointer-relative addressing, so this seems like a nice option to have, especially for wasm64.

There may be an advantage for wasm32 in that data using these relocs can be placed/moved anywhere in wasm memory, as opposed to be baked by wasm-ld for a certain destination.

On the downside, there is no way to express these relative pointers in C/C++ or (currently) in .wat/.s, so its application is limited to compilers who do their own object file emitting?

Also, most systems that would emit relative pointer data would do so locally, meaning they don't need relocs at all. These relocs are thus limited to pointer relative data that is using external linker symbols, which makes it more niche.

Fantasizing beyond your use case, what would be fun is a SLEB version of this, the idea being that it can make data really small (with offsets possibly fitting in a single byte). But that is even more niche :)

@sbc100
Copy link
Member

sbc100 commented Feb 5, 2021

Fantasizing beyond your use case, what would be fun is a SLEB version of this, the idea being that it can make data really small (with offsets possibly fitting in a single byte). But that is even more niche :)

Because we are only talking about the data section here.. so wouldn't using LEB require user-space LEB decoding to resolve such an address at runtime? Or perhaps you are saying we could embed relative data addresses in i32.const instructions maybe?

@aardappel
Copy link

@sbc100 yes, that would require the user to adopt SLEB for their data as well, hence the "fantasizing" part. Ignore that :)

@kateinoigakukun
Copy link
Contributor Author

kateinoigakukun commented Feb 6, 2021

@sbc100 @aardappel Thank you for taking a look!

  1. I the primary advantage here only present on wasm64? In which case we should loop in @aardappel.

Yes, I'm planning to use this for wasm64 mainly.

  1. Would the relocation type still exist on wasm32? for convenience only? It seems like it would be strictly less performant on wasm32 because you would need to do a runtime addition, and an absolute relocation would work find here?

In the aspect of runtime performance, the relative pointer is less performant on wasm32, but it's a little worth using consistent addressing mode with other architectures for simplicity. So I'll implement this on wasm32 also.

  1. I suppose the relocation would fail if the if the relocation location and the symbol are more then 4Gb apart?

As well as R_X86_64_PC32, the relocation would fail when the difference between symbols are out of i32.

On the downside, there is no way to express these relative pointers in C/C++ or (currently) in .wat/.s, so its application is limited to compilers who do their own object file emitting?
Also, most systems that would emit relative pointer data would do so locally, meaning they don't need relocs at all. These relocs are thus limited to pointer relative data that is using external linker symbols, which makes it more niche.

That's right. The only way to express relative pointers is LLVM IR or machine code directly now. And the relocation is used only for reference of foreign segment symbols.
Perhaps, the reloc may be used for PIC addressing without __memory_base (of course, the relative pointer's absolute pointer must be known.) But I'm not sure there are such use cases 🤷‍♂️

@kateinoigakukun
Copy link
Contributor Author

kateinoigakukun commented Feb 14, 2021

@sbc100 @aardappel I created a patch for this reloc type. Could you take a look when you have time? https://reviews.llvm.org/D96659

kateinoigakukun added a commit to kateinoigakukun/llvm-project that referenced this issue Feb 14, 2021
This `R_WASM_MEMORY_ADDR_SELFREL_I32` relocation represents an offset
between its relocating address and the symbol address. It's very similar
to `R_X86_64_PC32` but restricted to be used for only data segments.

```
S + A - P
```

A: Represents the addend used to compute the value of the relocatable
field.
P: Represents the place of the storage unit being relocated.
S: Represents the value of the symbol whose index resides in the
relocation entry.

Proposal: WebAssembly/tool-conventions#162

Differential Revision: https://reviews.llvm.org/D96659
kateinoigakukun added a commit to kateinoigakukun/llvm-project that referenced this issue Feb 24, 2021
This `R_WASM_MEMORY_ADDR_LOCREL_I32` relocation represents an offset
between its relocating address and the symbol address. It's very similar
to `R_X86_64_PC32` but restricted to be used for only data segments.

```
S + A - P
```

A: Represents the addend used to compute the value of the relocatable
field.
P: Represents the place of the storage unit being relocated.
S: Represents the value of the symbol whose index resides in the
relocation entry.

Proposal: WebAssembly/tool-conventions#162

Differential Revision: https://reviews.llvm.org/D96659
sbc100 pushed a commit to llvm/llvm-project that referenced this issue Mar 8, 2021
This `R_WASM_MEMORY_ADDR_SELFREL_I32` relocation represents an offset
between its relocating address and the symbol address. It's very similar
to `R_X86_64_PC32` but restricted to be used for only data segments.

```
S + A - P
```

A: Represents the addend used to compute the value of the relocatable
field.
P: Represents the place of the storage unit being relocated.
S: Represents the value of the symbol whose index resides in the
relocation entry.

Proposal: WebAssembly/tool-conventions#162

Differential Revision: https://reviews.llvm.org/D96659
arichardson pushed a commit to CTSRD-CHERI/llvm-project that referenced this issue Mar 31, 2021
This `R_WASM_MEMORY_ADDR_SELFREL_I32` relocation represents an offset
between its relocating address and the symbol address. It's very similar
to `R_X86_64_PC32` but restricted to be used for only data segments.

```
S + A - P
```

A: Represents the addend used to compute the value of the relocatable
field.
P: Represents the place of the storage unit being relocated.
S: Represents the value of the symbol whose index resides in the
relocation entry.

Proposal: WebAssembly/tool-conventions#162

Differential Revision: https://reviews.llvm.org/D96659
@MaxDesiatov
Copy link
Contributor

This has been merged to LLVM as R_WASM_MEMORY_ADDR_LOCREL_I32. Does this mean that the functionality is fully implemented now? Do we need to submit a PR here clarifying how it works, and then close this issue?

@dschuff
Copy link
Member

dschuff commented Feb 7, 2022

Yes, I believe that's correct. I think we just need to add to the existing list of relocation types

mem-frob pushed a commit to draperlaboratory/hope-llvm-project that referenced this issue Oct 7, 2022
This `R_WASM_MEMORY_ADDR_SELFREL_I32` relocation represents an offset
between its relocating address and the symbol address. It's very similar
to `R_X86_64_PC32` but restricted to be used for only data segments.

```
S + A - P
```

A: Represents the addend used to compute the value of the relocatable
field.
P: Represents the place of the storage unit being relocated.
S: Represents the value of the symbol whose index resides in the
relocation entry.

Proposal: WebAssembly/tool-conventions#162

Differential Revision: https://reviews.llvm.org/D96659
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

5 participants