| 2498 | } |
| 2499 | |
| 2500 | static void emit_native_handler(X64Emitter& e, const VMConfig& vm, bool is_jmp) { |
| 2501 | const auto& r = vm.dispatcher_regs(); |
| 2502 | { |
| 2503 | // deferred data-island decrypt |
| 2504 | const auto& st_local = vm.state_layout(); |
| 2505 | auto lbl_dec_done = e.new_label(); |
| 2506 | |
| 2507 | // lea rax, [rip + data_island_init_flag]; cmp byte [rax], 0; jnz done |
| 2508 | auto flag_lea = e.lea_reg_rip(rx::rax, 0); |
| 2509 | e.add_fixup( |
| 2510 | flag_lea, |
| 2511 | static_cast<std::uint32_t>(FixupKind::DataIslandInitFlag), |
| 2512 | 0, |
| 2513 | 0 |
| 2514 | ); |
| 2515 | e.u8(0x80); |
| 2516 | e.emit_modrm_mem( |
| 2517 | 7, |
| 2518 | rx::rax, |
| 2519 | rx::none, |
| 2520 | 0, |
| 2521 | 0 |
| 2522 | ); |
| 2523 | e.u8(0); |
| 2524 | e.jcc_label(cc::nz, lbl_dec_done); |
| 2525 | |
| 2526 | // save cipher_state + ip so the rest of the handler's fetch |
| 2527 | // invariant survives the loop. |
| 2528 | e.mov_mem_reg( |
| 2529 | r.state_ptr, |
| 2530 | static_cast<std::int32_t>(st_local.cipher_extra) + kPreDecryptCsOff, |
| 2531 | r.cipher_state, |
| 2532 | true |
| 2533 | ); |
| 2534 | |
| 2535 | e.mov_mem_reg( |
| 2536 | r.state_ptr, |
| 2537 | static_cast<std::int32_t>(st_local.cipher_extra) + kPreDecryptIpOff, |
| 2538 | r.ip, |
| 2539 | true |
| 2540 | ); |
| 2541 | |
| 2542 | // reset cipher_state to cipher_init and walk the island tom hanks |
| 2543 | e.mov_reg_imm64(rx::rax, vm.cipher_init_state()); |
| 2544 | e.mov_reg_reg(r.cipher_state, rx::rax); |
| 2545 | auto src_slot = e.lea_reg_rip(r.ip, 0); |
| 2546 | e.add_fixup( |
| 2547 | src_slot, |
| 2548 | static_cast<std::uint32_t>(FixupKind::DataIsland), |
| 2549 | 0, |
| 2550 | 0 |
| 2551 | ); |
| 2552 | auto dst_slot = e.lea_reg_rip(r.scratch_b, 0); |
| 2553 | e.add_fixup( |
| 2554 | dst_slot, |
| 2555 | static_cast<std::uint32_t>(FixupKind::DataIsland), |
| 2556 | 0, |
| 2557 | 0 |
no test coverage detected