Expand description
Frust’s native-only hot-patch runtime: the in-app half of hot patching.
Wrap a patch point in HotFn (or the free call). In a debug build every call does one
lookup in the installed JumpTable, keyed on the address of the function’s
HotFunction::call_it monomorphisation (or, for HotFn::from_fn_ptr, the pointer’s own
value), and jumps to the patched version when one is mapped, else runs the original. There is
no stale-call detection and no retry. A patch builder (today dx 0.7.10, whose wire format
JumpTable matches, but whose tables are anchored on main, which apply_patch refuses
with PatchError::AnchorMismatch: a table must be anchored on ANCHOR_SYMBOL) compiles the changed code into a library and sends the table;
apply_patch loads that library, rebases the table onto this process, publishes it, and runs
every register_handler handler. Patches are serialised, and a patch is refused before
anything is loaded in a release build, while no anchor is set (set_anchor; the app defines
the ANCHOR_SYMBOL function), and, in every apply entry (apply_patch and
apply_from_devtools), while a layout-mismatch record is unreported
(report_layout_mismatch; checked under the apply lock, PatchError::LayoutMismatchPending).
The layout precondition: every type whose values cross images (a mapped function’s arguments, return and closure captures, a component’s state) must keep its layout between the running image and a patch. Symbol names do not encode layout, so nothing here can check it; the patch builder’s L3 gate does, and the runtime reports a disagreement it meets anyway.
The patch boundary: nothing rewrites process memory, so the table only redirects calls that
enter through a HotFn. Patch code is also reached without one, though: a trait object, stored
closure or fn pointer created while patched code ran points straight into the patch library,
and calling it later runs that code with no HotFn in between (including after a newer patch).
Likewise such values created before a patch keep running the old code until they are rebuilt.
Lookups happen only under cfg!(debug_assertions). In a release build every HotFn call is a
direct call and the table is never read. See the crate README for scope and differences.
Structs§
- Address
Hasher - Identity hasher for integer keys;
AddressMaponly ever feeds it au64. - Apply
Report - What
apply_from_devtoolsdid: whether the patch was applied, and why not when it was not. - HotFn
- A hot-reloadable function:
HotFn::callruns the newest version the jump table maps. - HotFn
Ptr - The address a hot function currently resolves to.
- Jump
Table - One patch: the library holding the new code and the old -> new address map into it.
- Layout
Mismatch - A layout disagreement found at run time: a value built by one image was reached by another
whose own layout for
type_namediffers. - Missed
Key - A jump-table key that missed, located in the image the calling code belongs to.
Enums§
- Patch
Error - Why a patch could not be applied. On every error nothing is installed and no handler runs.
Constants§
- ANCHOR_
SYMBOL - The symbol every patch library exports and the app defines:
#[unsafe(no_mangle)] pub extern "C" fn __frust_hotpatch_anchor() {}. - UNKNOWN_
IMAGE - The image index reported for an address that lies in no image this crate knows.
Traits§
- FnPointer
- A plain, non-higher-ranked function-pointer type
fn(A, ..) -> Rof up to nine arguments: the only typesHotFn::from_fn_ptraccepts. Sealed; implemented by this crate only. - HotFunction
- A function that can be detoured through the jump table: implemented for every
FnMutof up to nine arguments (taken as a tuple).FnOnceis excluded because a patch may re-run the function.
Functions§
- apply_
from_ devtools - The safe devtools entry: apply the patch library at
bytes_pathwithtable. - apply_
patch ⚠ - Apply a patch: load
table.lib, rebasetable’s addresses onto this process and the loaded library, install it, then run everyregister_handlerhandler. - call
- Call
fonce through the jump table. - fall_
through_ count - How many
HotFncalls, on any thread, missed the jump table since the last patch was applied (seelast_call_fell_through). Reset to zero by every successfulapply_patch. - get_
jump_ ⚠table - The installed jump table, or
Nonebefore the first patch. - last_
call_ fell_ through - Whether this thread’s most recent
HotFncall found a jump table installed but no mapping for its own key, and so ran the function compiled into the calling image. - load_
patch_ ⚠library - Load
pathwith the platform loaderapply_patchuses:dlopen/LoadLibrarythroughlibloadingon desktop, the memfd +android_dlopen_extpath on Android (which lets a library outside the app’s native-library directory load on a non-rooted device). - mark_
layout_ mismatches_ reported - Mark
reportedas carried by aPatchOutcomeorhotpatch_infoanswer. Only the records given are removed, so one reported after the caller read the list stays pending. - missed_
keys - Every distinct key that missed the jump table since the last patch was applied, each once, ordered by image then link address. Reset by every patch.
- pending_
layout_ mismatches - The layout-mismatch records not yet reported, oldest first (for
hotpatch_info). - register_
handler - Register
handlerto run right after each patch library is loaded and its jump table installed. - report_
layout_ mismatch - Record that
type_namehas layoutstoredin the image that created a value andownin the image now handling it. The record is kept until it is reported to the host: it is returned bypending_layout_mismatchesand cleared bymark_layout_mismatches_reported. Identical records collapse into one. While any record is unreported, every apply entry (apply_patch,apply_from_devtools) refuses. - seam_
hits - How many
HotFncalls, on any thread, found their key in the installed jump table (and so ran the patched version) since the last patch was applied. Reset to zero by every patch. - set_
anchor - Register the running executable’s anchor: the address of its
__frust_hotpatch_anchorfunction, taken as a function pointer (__frust_hotpatch_anchor as usize).
Type Aliases§
- Address
Map - An address -> address map that does not hash its keys: addresses are already unique.
- Build
Address Hasher - The
AddressMaphasher builder.