Expand description
Cached snapshot of the original binary’s symbol table.
Why a cache: the binary an app boots with is “hundreds of MB” on
a real-world build (subsecond’s own comment). We pay that I/O +
parse cost once at the start of a whisker run session and re-use
it for every subsequent hot patch. Each save then only has to
parse the small patch dylib and diff it against the cached
original — closer to the sub-second budget.
Apart from the symbols, we also capture the static virtual
address of whisker_aslr_anchor (emitted by #[whisker::main])
in the host binary. That becomes JumpTable::aslr_reference,
and our vendored subsecond’s apply_patch uses it as
ⓘ
old_offset = aslr_reference() // dlsym(RTLD_DEFAULT,
// "whisker_aslr_anchor")
- table.aslr_reference // static anchor addr (us)
= runtime image base.so the JumpTable’s static keys can be adjusted to live runtime addresses. Two earlier bugs led us here:
- Setting this to
file.relative_address_base()(always 0 for ELF PIE) shifted the keys byruntime_main_addrrather than the image base;call_as_ptr’s map lookup always missed. - Anchoring on
maininstead ofwhisker_aslr_anchor— on Android,dlsym(RTLD_DEFAULT, "main")resolves toapp_process64’smain, not the user’s.so, so the slide math computed garbage. The unique anchor name fixes that.
Structs§
- Hotpatch
Module Cache - Pre-parsed snapshot of the original (== “fat”) binary. Built once per dev-server run; subsequent JumpTable construction reads from here without touching the disk again.