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 Hotpatch flag #745

Open
1 of 3 tasks
nebulark opened this issue May 10, 2024 · 1 comment
Open
1 of 3 tasks

Add Hotpatch flag #745

nebulark opened this issue May 10, 2024 · 1 comment
Labels
major-change A proposal to make a major change to rustc T-compiler Add this label so rfcbot knows to poll the compiler team

Comments

@nebulark
Copy link

nebulark commented May 10, 2024

Proposal

Add a compiler flag that forces the compiler to emit functions can always be hotpatched. It would be a less bloated alternative to patchable-function-entries (rust-lang/rfcs#3543). Currently it would only work on Windows as it also requires some linker support.

A function can be reliably hotpatched when the following conditions are true:

  1. The first instruction is at least two bytes long
  2. There is no jump to the first instruction
  3. There are enough unused bytes before the function

This allows writing instructions for an absolute jump just before the function and replacing the first instruction with a relative jump to that absolute jump.

The patchable-function-entries flag inserts a fixed amount of nop instructions at the beginning and in front of the function, which reliably fulfils all conditions.

The hotpatch flag by itself only fullfils 1) by making use of of the LLVM function attribute 'patchable-function", "prologue-short-redirect"' (see LLVM Docs ). However, functions are only modified only if they do not already fulfil the condition. In the wild >99% of functions already do so. On x86 a function containing just a single return statement would be an exception. Many architectures fulfil this by default, as they don't have single byte instructions.

While the LLVM function attribute does not support 2) this very rarely matters in practice. Almost no functions break this condition. So far I have only seen this in parameterless functions which perform a tail call to themselves. In addition the hotpatch would need to occur while the hotpatched function is currently executed. This can be completely avoided by the hotpatching facility by hotpatching only when at a known safe instruction, e.g. the beginning of an update loop.

A special flag "functionpadmin" can be passed to some linkers (link.exe, link-lld) to ensure 3). Similar to hotpatch it only adds extra padding if needed. When functions are aligned by the linker they may already contain enough padding, so nothing more needs to be done. In addition, as patchable-function-entries is linker agnostic it needs to create extra symbols and relocations to make the function prefix padding work, creating additional bloat. However, this may require hotpatch flag in the Codeview S_COMPILE3 record, which would also be done with the proposed compiler flag. See: https://github.com/llvm/llvm-project/blob/d703b922961e0d02a5effdd4bfbb23ad50a3cc9f/lld/COFF/Writer.cpp#L1298

Inlining is not a concern for this feature. If a function is inlined, the function in which it is inlined in can be hotpatched instead.

When a patchable-function-entries attribute is present it takes precedence over this flag. This is also how LLVM currently implements this (see: https://github.com/llvm/llvm-project/blob/bb937e276da11c6d85318b32006f6510877c1a2c/llvm/lib/CodeGen/PatchableFunction.cpp#L43-L49)

Zulip discussion that led to this MCP: https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler/topic/Adding.20hotpatch.20flag.20to.20the.20compiler

Implementation

Add the '"patchable-function", "prologue-short-redirect"' attribute to each function, so LLVM can do its magic for x86. For architectures which 1 byte instructions, nothing needs to be done.

Set TargetOptions::Hotpatch to true, so LLVM emits hotpatch flag in the Codeview S_COMPILE3 record. Some linkers require this for their function padding.

As a first step I would only implement this on x86/x64. I already have a candidate implementation: rust-lang/rust#124966  

I used the Clang implementation as a template: llvm/llvm-project@5af2433

The implementation would cover x86 and aarch64, but only for windows due to required linker support.

I could see this as special option for patchable-function-entries, e.g. "patchable-function-entries=prologue-short-redirect" or "patchable-function-entries=hotpatch"

I'd prefer to have a seperate flag distinc from patchable-function-entries. But if there is good reason I could see to have hotpatch as a special option of patchable-function-entries.

Mentors or Reviewers

None yet.

Process

The main points of the Major Change Process are as follows:

  • File an issue describing the proposal.
  • A compiler team member or contributor who is knowledgeable in the area can second by writing @rustbot second.
    • Finding a "second" suffices for internal changes. If however, you are proposing a new public-facing feature, such as a -C flag, then full team check-off is required.
    • Compiler team members can initiate a check-off via @rfcbot fcp merge on either the MCP or the PR.
  • Once an MCP is seconded, the Final Comment Period begins. If no objections are raised after 10 days, the MCP is considered approved.

You can read more about Major Change Proposals on forge.

Comments

This issue is not meant to be used for technical discussion. There is a Zulip stream for that. Use this issue to leave procedural comments, such as volunteering to review, indicating that you second the proposal (or third, etc), or raising a concern that you would like to be addressed.

@nebulark nebulark added major-change A proposal to make a major change to rustc T-compiler Add this label so rfcbot knows to poll the compiler team labels May 10, 2024
@rustbot
Copy link
Collaborator

rustbot commented May 10, 2024

This issue is not meant to be used for technical discussion. There is a Zulip stream for that. Use this issue to leave procedural comments, such as volunteering to review, indicating that you second the proposal (or third, etc), or raising a concern that you would like to be addressed.

Concerns or objections to the proposal should be discussed on Zulip and formally registered here by adding a comment with the following syntax:

@rustbot concern reason-for-concern 
<description of the concern> 

Concerns can be lifted with:

@rustbot resolve reason-for-concern 

See documentation at https://forge.rust-lang.org

cc @rust-lang/compiler @rust-lang/compiler-contributors

@rustbot rustbot added the to-announce Announce this issue on triage meeting label May 10, 2024
@apiraino apiraino removed the to-announce Announce this issue on triage meeting label May 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
major-change A proposal to make a major change to rustc T-compiler Add this label so rfcbot knows to poll the compiler team
Projects
None yet
Development

No branches or pull requests

3 participants