Hi, if want to to provide other function-calls to TCG plugin, such as reading guest memory, follow these steps:
- in include/qemu/qemu-plugin.h, add function header, such as
/**
* qemu_plugin_read_guest_virt_mem() - Read a buffer of guest memory
* @gva: Guest virtual address
* @buf: Buffer to copy guest memory into
* @length: Size of buf
*
* Returns: True if the memory was successfully copied into buf
*/
bool qemu_plugin_read_guest_virt_mem(uint64_t gva, char* buf, size_t length);
- in plugins/api.c, add function body, such as
bool qemu_plugin_read_guest_virt_mem(uint64_t gva, char* buf, size_t length) {
#ifdef CONFIG_USER_ONLY
return false;
#else
// Convert virtual address to physical, then read it
CPUState *cpu = current_cpu;
uint64_t page = gva & TARGET_PAGE_MASK;
hwaddr gpa = cpu_get_phys_page_debug(cpu, page);
if (gpa == (hwaddr)-1) {
return false;
}
gpa += (gva & ~TARGET_PAGE_MASK);
// cpu_physical_memory_read(gpa, buf, length);
cpu_memory_rw_debug(cpu, gva, buf, length, false);
return true;
#endif
}
- in plugins/qemu-plugins.symbols, add
qemu_plugin_read_guest_virt_mem;
- in your tcg plugin tests/plugin/mem.c, just call to it, such as
struct qemu_plugin_hwaddr *hwaddr2 = qemu_plugin_get_hwaddr(meminfo, vaddr);
const char *name = qemu_plugin_hwaddr_device_name(hwaddr2);
uint64_t addr = qemu_plugin_hwaddr_phys_addr(hwaddr2);
g_autoptr(GString) out = g_string_new("");
uint64_t temp=0;
unsigned int size=8;
// unsigned int size=qemu_plugin_mem_size_shift(meminfo); // get the accessed memory size
// if (size==2){
// size=1;
// }else if (size==4){
// size=2;
// }else{
// size=8;
// }
qemu_plugin_read_guest_virt_mem(vaddr, (char *)&temp, size);
if (qemu_plugin_mem_is_store(meminfo)) {
g_string_printf(out, "> mem store (%s), 0x%lx, 0x%lx, 0x%lx, %d\n", name, (long unsigned int)vaddr, (long unsigned int)addr, (long unsigned int)temp, size);
} else {
g_string_printf(out, "> mem load(%s), 0x%lx, 0x%lx, 0x%lx, %d\n", name, (long unsigned int)vaddr, (long unsigned int)addr, (long unsigned int)temp, size);
}
qemu_plugin_outs(out->str);
5. Run in qemu
./configure --target-list=riscv64-softmmu --enable-plugins
6. Edit xv6-riscv Makefile:
qemu2: $K/kernel fs.img
$(QEMU) $(QEMUOPTS) -singlestep -d exec,cpu,nochain,in_asm,int,plugin -plugin ~/workspace/qemu/build/tests/plugin/libmem.so,callback=true -D qemu.log
References:
- https://gitlab.com/qemu-project/qemu/-/issues/2152#note_1767322945
- https://github.com/qemu/qemu/commit/72c661a7f141ab41fbce5e95eb3593b69f40e246?diff=split&w=0#diff-d508cf0c073440a0ef62534395ec2ccff4378932f755f0d093cdc1795d9f871f
- https://airbus-seclab.github.io/qemu_blog/tcg_p3.html
- https://airbus-seclab.github.io/qemu_blog/regions.html