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

Add ePIC relocations and rewrite rules #405

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

luismarques
Copy link
Collaborator

Continuing to follow up on the request to decompose the ePIC PR into multiple PRs, this PR adds the ePIC relocations and rewrite rules.

** Rewrites the addition instruction into a canonical `nop` (`addi x0, x0, 0`) or `c.nop` instruction (if the relocation is being applied to an `add` or `c.add` instruction, respectively), or
** Deletes the `add` or `c.add` instruction.
* For GP-relative addressing:
** Nothing needs to be done.
Copy link
Collaborator Author

@luismarques luismarques Nov 12, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the future, I'm hoping we'll have a R_RISCV_GPREL_ADD relocation, for relaxation purposes. If that happens, we can replace this "Nothing needs to be done" with "Optionally adds a R_RISCV_GPREL_ADD relaxation relocation with the same symbol and addend, at the same offset."

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Put this as forward-looking non-normative next?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please see if the added note properly addresses your suggestion.

riscv-elf.adoc Outdated Show resolved Hide resolved
Copy link
Collaborator

@kito-cheng kito-cheng left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM :)

@kito-cheng
Copy link
Collaborator

@rui314 @MaskRay any comments? generally I would like get at least one more LGTM from someone other than GNU folk, but I know it's kinda embedded stuffs which you may not interested on that, so it's fine if no comment, but I would like to make sure it's at least not looks insane to linker expert.

@Nelson1225 You and me has spend times on discussion this before, and we both like this, so I assume you are OK with this, but I guess it would be great to get your explicitly LGTM here again :)

riscv-elf.adoc Outdated
* If the symbol resides in a writable output section, then GP-relative addressing is used;
* If the symbol does not reside in an output section or the section is not writable, then PC-relative addressing is used instead.

NOTE: Implementations are permitted to apply alternative rules for choosing between GP-relative or PC-relative addressing.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Notes are non-normative, so can't override what's outside a note. If it's not required then the spec above needs to not dictate the rules.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've put the old description as part of the non-normative note. Please check if that addresses your concern.

** Rewrites the addition instruction into a canonical `nop` (`addi x0, x0, 0`) or `c.nop` instruction (if the relocation is being applied to an `add` or `c.add` instruction, respectively), or
** Deletes the `add` or `c.add` instruction.
* For GP-relative addressing:
** Nothing needs to be done.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Put this as forward-looking non-normative next?

@MaskRay
Copy link
Collaborator

MaskRay commented Feb 5, 2024

I am happy with the GP-relative relocation part (also used by the FDPIC ABI proposal), but I am afraid I am concerned of R_RISCV_EPIC_* relocations. Commented here #343 (comment)

Also CC @sorear

Copy link
Collaborator

@sorear sorear left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have a good understanding of the use cases for embedded systems that need PIC but not shared libraries. Is there any freely source available example of something that would use this? If it's needed for a commercial RTOS, is there at least a public manual or datasheet?

@MaskRay Was your comment questioning the existence of the use case for ePIC without shared libraries, suggesting that ePIC should be a special case of FDPIC, or something else?

Assuming that the use case is valid, the general approach looks good. Relocation behavior needs to be described in the language of externally observable linker behavior, not implementation details like synthesized non-dynamic relocations. I think we also need an absolute option, at least for weak symbols but it may be useful more generally.

* If the symbol resides in a writable output section, then GP-relative addressing is used;
* If the symbol does not reside in an output section or the section is not writable, then PC-relative addressing is used instead.

The ePIC relocations are applied to a sequence of instructions that initially address a symbol relative to the GP. When PC-relative addressing should be used instead, the ePIC relocations rewrite the instructions to perform PC-relative addressing and add the appropriate PC-relative relocations. When GP-relative addressing should be used, the instruction rewrites do not occur and GP-relative relocations are added. For correctness, the rewrites must occur even when linker relaxations are disabled. Paired `R_RISCV_RELAX` relocations are preserved during the rewrite process, and will pair with relocations added as part of that rewrite.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The ePIC relocations are applied to a sequence of instructions that initially address a symbol relative to the GP. When PC-relative addressing should be used instead, the ePIC relocations rewrite the instructions to perform PC-relative addressing and add the appropriate PC-relative relocations. When GP-relative addressing should be used, the instruction rewrites do not occur and GP-relative relocations are added. For correctness, the rewrites must occur even when linker relaxations are disabled. Paired `R_RISCV_RELAX` relocations are preserved during the rewrite process, and will pair with relocations added as part of that rewrite.
The ePIC relocations are applied to a sequence of instructions that initially address a symbol relative to the GP. When PC-relative addressing should be used instead, the ePIC relocations rewrite the instructions to perform PC-relative addressing. When GP-relative addressing should be used, the instruction rewrites do not occur. For correctness, the rewrites must occur even when linker relaxations are disabled. Relaxation may occur if paired `R_RISCV_RELAX` relocations are present.

The behavior of relocations needs to be specified in terms of observable linker behavior. The output will not contain non-dynamic relocations (and ePIC does not support dynamic linking), so describe it purely in terms of instruction rewrites.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 for this change

@@ -849,6 +859,48 @@ def align(addend):
return ALIGN
----

==== Embedded PIC rewrite rules

The Embedded PIC (ePIC) relocations allow addressing a symbol relative to either the PC or the GP, as appropriate for that symbol.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to allow absolute addressing as a third option (for weak symbols, and also usable for symbols not in an output section).

Comment on lines +877 to +881
* For PC-relative addressing:
** Rewrites the `lui` instruction into an `auipc` instruction with the same operands, by overwriting the opcode field.
** Adds a `R_RISCV_PCREL_HI20` relocation with the same symbol and addend, at the same offset.
* For GP-relative addressing:
** Adds a `R_RISCV_GPREL_HI20` relocation with the same symbol and addend, at the same offset.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use observable behavior.

Relaxation may delete the HI20 entirely, unless that is documented elsewhere.

* For GP-relative addressing:
** Nothing needs to be done.

NOTE: If a `R_RISCV_GPREL_ADD` relaxation relocation is defined in the future, the GP-relative addressing rule could be updated to read: "Optionally adds a `R_RISCV_GPREL_ADD` relaxation relocation with the same symbol and addend, at the same offset."
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Delete, not observable.

Comment on lines +887 to +891
* For PC-relative addressing, it either:
** Rewrites the addition instruction into a canonical `nop` (`addi x0, x0, 0`) or `c.nop` instruction (if the relocation is being applied to an `add` or `c.add` instruction, respectively), or
** Deletes the `add` or `c.add` instruction.
* For GP-relative addressing:
** Nothing needs to be done.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only allow the instruction to be deleted if there is a paired R_RISCV_RELAX.

Allow deletion if there is a paired R_RISCV_RELAX and the HI20 was deleted by relaxation.

<| Rewrite
.2+| 68 .2+| EPIC_LO12_S .2+| Static | _S-Type_ .2+| <<Embedded PIC rewrite rules,Embedded PIC rewrite>> for the low 12 bits of a 32-bit PC- or GP-relative offset, `epic_low(address of %epic_high)`
<| Rewrite
.2+| 69 .2+| EPIC_BASE_ADD .2+| Static | _I-type_ .2+| <<Embedded PIC rewrite rules,Embedded PIC rewrite>> of `gp` addition, `%epic_base_add(symbol)`
Copy link
Collaborator

@sorear sorear Feb 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer to have EPIC_BASE_ADD point at the %epic_high for consistency, and rename it EPIC_ADD.

We can get rid of EPIC_LO12_I/EPIC_LO12_S and use the overloaded PCREL_LO12_I/PCREL_LO12_S (which are also used for GOT references, so they're already somewhat of misnomers).

It might be worth getting rid of the GPREL* relocations and using EPIC* exclusively, unless GPREL* already made it into a ratified version.

Comment on lines +899 to +902
* For PC-relative addressing, it either:
** Adds a `R_RISCV_PCREL_LO12_I` or `R_RISCV_PCREL_LO12_S` relocation, as appropriate, with the same symbol and addend, at the same offset.
* For GP-relative addressing:
** Adds a `R_RISCV_GPREL_LO12_I` or `R_RISCV_GPREL_LO12_S` relocation, as appropriate, at the same offset. The symbol and addend of the new relocation are those of the corresponding `R_RISCV_EPIC_HI20` relocation.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Describe observable behavior - it relocates and relaxes as if there were an XXX relocation, it does not create an XXX relocation.

@MaskRay
Copy link
Collaborator

MaskRay commented Feb 20, 2024

I don't have a good understanding of the use cases for embedded systems that need PIC but not shared libraries. Is there any freely source available example of something that would use this? If it's needed for a commercial RTOS, is there at least a public manual or datasheet?

@MaskRay Was your comment questioning the existence of the use case for ePIC without shared libraries, suggesting that ePIC should be a special case of FDPIC, or something else?

Assuming that the use case is valid, the general approach looks good. Relocation behavior needs to be described in the language of externally observable linker behavior, not implementation details like synthesized non-dynamic relocations. I think we also need an absolute option, at least for weak symbols but it may be useful more generally.

My comment is questioning the existence of the use case for ePIC without shared libraries. I think we should consider FDPIC, which works with MMU-less and MMU systems, supports dynamic libraries. After FDPIC support, we can figure out whether there is still ePIC need. (I kinda suspect no.)

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

Successfully merging this pull request may close these issues.

5 participants