Bochs - Playable-Quotes/QuoteKit GitHub Wiki

Launching the emulator

$ bochs -q -f bochsrc.txt # where .txt is some config file

Attach Frida to the emulator

$ frida -l script.js bochs

Hook the main loop

const handleAsyncEvent = Module.getExportByName("bochs","_ZN8BX_CPU_C16handleAsyncEventEv");

How fast does it run? ~1266 Hz (on Adam's 4GHz M3 MBP)

Get main memory range

const bx_mem = Module.getExportByName("bochs", "bx_mem");
const mem_size = bx_mem.add(8*9).readU64();
const mem_base = bx_mem.add(8*11).readPointer();

Get a save state

const SIM = Module.getExportByName("bochs", "SIM").readPointer();
const save_state = new NativeFunction(
        DebugSymbol.fromName("bx_real_sim_c::save_state(char const*)").address,
        'bool', ['pointer'/* bx_real_sim_c* this */, 'pointer'/* const char *checkpoint_path */ ]);
// save_state(SIM, Memory.allocUtf8String("tmp-sr"))

Component sizes/times

If attach minimal logging to save_sr_param, it goes to 3350ms.

  • "hard_drive" takes 2860ms, 4.0GB
  • "memory" takes 425ms, 128 MB
  • "cpu0" takes 27ms (lots of small page table stuff), 408KB
  • "vga" takes 25ms (big buffer), 16MB
  • everything else is <1 ms, a bit over 256KB, mostly in IDE buffers

If I skip hard_drive and memory, it goes to 60ms.

How much time/space does saving savestates cost? Saving my alpine box takes about 3300ms baseline. 4.1GB (from Adam's 2023 notes on 2.5GHz Intel Core i7 MBP in 2023)

Snoop player inputs

const bx_devices = Module.getExportByName("bochs", "bx_devices");
const get_scancode = DebugSymbol.fromName("bx_devices_c::gen_scancode(unsigned int)").address
const gen_scancode_wrapper = new NativeFunction(get_scancode, 'void', ['pointer', 'uint']);

Disk access tracking

flat_image_t::lseek(long, int);
flat_image_t::read(void*, unsigned long);
flat_image_t::write(void const*, unsigned long);

Memory access tracking

const bx_mem = Module.getExportByName("bochs", "bx_mem");
const mem_size = bx_mem.add(8*9).readU64();
const mem_base = bx_mem.add(8*11).readPointer();

MemoryAccessMonitor.enable([{base:mem_base, size:mem_size}], ...