Change to combine restoration prologue with coverage register spill (#1029)
Co-authored-by: Your Name <you@example.com>
This commit is contained in:
parent
2a88a776bf
commit
d0b4c39acd
@ -85,33 +85,36 @@ impl CoverageRuntime {
|
|||||||
dynasm!(ops
|
dynasm!(ops
|
||||||
; .arch aarch64
|
; .arch aarch64
|
||||||
// Store the context
|
// Store the context
|
||||||
; stp x0, x1, [sp, #-0xa0]
|
; b >start
|
||||||
|
|
||||||
|
; stp x16, x17, [sp, -0x90]!
|
||||||
|
; start:
|
||||||
|
|
||||||
// Load the previous_pc
|
// Load the previous_pc
|
||||||
; ldr x1, >previous_loc
|
; ldr x17, >previous_loc
|
||||||
; ldr x1, [x1]
|
; ldr x17, [x17]
|
||||||
|
|
||||||
// Caltulate the edge id
|
// Caltulate the edge id
|
||||||
; ldr x0, >loc
|
; ldr x16, >loc
|
||||||
; eor x0, x1, x0
|
; eor x16, x17, x16
|
||||||
|
|
||||||
// Load the map byte address
|
// Load the map byte address
|
||||||
; ldr x1, >map_addr
|
; ldr x17, >map_addr
|
||||||
; add x0, x1, x0
|
; add x16, x17, x16
|
||||||
|
|
||||||
// Update the map byte
|
// Update the map byte
|
||||||
; ldrb w1, [x0]
|
; ldrb w17, [x16]
|
||||||
; add w1, w1, #1
|
; add w17, w17, #1
|
||||||
; add x1, x1, x1, lsr #8
|
; add x17, x17, x17, lsr #8
|
||||||
; strb w1, [x0]
|
; strb w17, [x16]
|
||||||
|
|
||||||
// Update the previous_pc value
|
// Update the previous_pc value
|
||||||
; ldr x0, >loc_shr
|
; ldr x16, >loc_shr
|
||||||
; ldr x1, >previous_loc
|
; ldr x17, >previous_loc
|
||||||
; str x0, [x1]
|
; str x16, [x17]
|
||||||
|
|
||||||
// Restore the context
|
// Restore the context
|
||||||
; ldp x0, x1, [sp, #-0xa0]
|
; ldp x16, x17, [sp], #0x90
|
||||||
|
|
||||||
// Skip the data
|
// Skip the data
|
||||||
; b >end
|
; b >end
|
||||||
@ -184,6 +187,24 @@ impl CoverageRuntime {
|
|||||||
pub fn emit_coverage_mapping(&mut self, address: u64, output: &StalkerOutput) {
|
pub fn emit_coverage_mapping(&mut self, address: u64, output: &StalkerOutput) {
|
||||||
let h64 = xxh3_rrmxmx_mixer(address);
|
let h64 = xxh3_rrmxmx_mixer(address);
|
||||||
let writer = output.writer();
|
let writer = output.writer();
|
||||||
|
|
||||||
|
// Since the AARCH64 instruction set requires that a register be used if
|
||||||
|
// performing a long branch, if the Stalker engine is unable to use a near
|
||||||
|
// branch to transition between branches, then it spills some registers
|
||||||
|
// into the stack beyond the red-zone so that it can use them to perform
|
||||||
|
// the branch. Accordingly each block is transparently prefixed with an
|
||||||
|
// instruction to restore these registers. If however a near branch can
|
||||||
|
// be used, then this instruction is simply skipped and Stalker simply
|
||||||
|
// branches to the second instruction in the block.
|
||||||
|
//
|
||||||
|
// Since we also need to spill some registers in order to update our
|
||||||
|
// coverage map, in the event of a long branch, we can simply re-use
|
||||||
|
// these spilt registers. This, however, means we need to retard the
|
||||||
|
// code writer so that we can overwrite the so-called "restoration
|
||||||
|
// prologue".
|
||||||
|
let pc = writer.pc();
|
||||||
|
writer.reset(pc - 4);
|
||||||
|
|
||||||
let code = self.generate_inline_code(h64 & (MAP_SIZE as u64 - 1));
|
let code = self.generate_inline_code(h64 & (MAP_SIZE as u64 - 1));
|
||||||
writer.put_bytes(&code);
|
writer.put_bytes(&code);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user