On 2/24/26 9:46 AM, Alex Bennée wrote:
Florian Hofhammer <[email protected]> writes:
This patch adds a plugin API function that allows diverting the program
counter during execution. A potential use case for this functionality is
to skip over parts of the code, e.g., by hooking into a specific
instruction and setting the PC to the next instruction in the callback.
Link: https://lists.nongnu.org/archive/html/qemu-devel/2025-08/msg00656.html
Signed-off-by: Florian Hofhammer <[email protected]>
---
include/plugins/qemu-plugin.h | 13 +++++++++++++
plugins/api.c | 13 +++++++++++++
2 files changed, 26 insertions(+)
diff --git a/include/plugins/qemu-plugin.h b/include/plugins/qemu-plugin.h
index a6ec8e275d..04c884e82b 100644
--- a/include/plugins/qemu-plugin.h
+++ b/include/plugins/qemu-plugin.h
@@ -76,6 +76,7 @@ typedef uint64_t qemu_plugin_id_t;
*
* version 6:
* - changed return value of qemu_plugin_{read,write}_register from int to
bool
+ * - added qemu_plugin_set_pc
*/
extern QEMU_PLUGIN_EXPORT int qemu_plugin_version;
@@ -1042,6 +1043,18 @@ QEMU_PLUGIN_API
bool qemu_plugin_write_register(struct qemu_plugin_register *handle,
GByteArray *buf);
+/**
+ * qemu_plugin_set_pc() - set the program counter for the current vCPU
+ *
+ * @vaddr: the new virtual (guest) address for the program counter
+ *
+ * This function sets the program counter for the current vCPU to @vaddr and
+ * resumes execution at that address. This function only returns in case of
+ * errors.
+ */
+QEMU_PLUGIN_API
+void qemu_plugin_set_pc(uint64_t vaddr);
+
/**
* qemu_plugin_read_memory_vaddr() - read from memory using a virtual address
*
diff --git a/plugins/api.c b/plugins/api.c
index e754b7c69c..ca3e93a194 100644
--- a/plugins/api.c
+++ b/plugins/api.c
@@ -41,6 +41,7 @@
#include "qemu/log.h"
#include "system/memory.h"
#include "tcg/tcg.h"
+#include "exec/cpu-common.h"
#include "exec/gdbstub.h"
#include "exec/target_page.h"
#include "exec/translation-block.h"
@@ -466,6 +467,18 @@ bool qemu_plugin_write_register(struct
qemu_plugin_register *reg,
return (gdb_write_register(current_cpu, buf->data, GPOINTER_TO_INT(reg) - 1)
> 0);
}
+void qemu_plugin_set_pc(uint64_t vaddr)
+{
+ g_assert(current_cpu);
+
+ if (qemu_plugin_get_cb_flags() != QEMU_PLUGIN_CB_RW_REGS_PC) {
+ return;
+ }
I think its fine to assert() here - we do it elsewhere in the api, if
the user is holding it wrong we should exit now rather than leave the
plugin more confused in the future.
Agree.
With the assert instead of return,
Reviewed-by: Pierrick Bouvier <[email protected]>