On 16/12/2025 10:27, Florian Hofhammer wrote:
>>> diff --git a/plugins/api.c b/plugins/api.c
>>> index eac04cc1f6..fc19bdb40b 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"
>>> @@ -450,13 +451,27 @@ int qemu_plugin_write_register(struct 
>>> qemu_plugin_register *reg,
>>>  {
>>>      g_assert(current_cpu);
>>>  
>>> -    if (buf->len == 0 || qemu_plugin_get_cb_flags() != 
>>> QEMU_PLUGIN_CB_RW_REGS) {
>>> +    if (buf->len == 0 || (
>>> +                qemu_plugin_get_cb_flags() != QEMU_PLUGIN_CB_RW_REGS
>>> +                && qemu_plugin_get_cb_flags() != 
>>> QEMU_PLUGIN_CB_RW_REGS_PC)) {
>>>          return -1;
>>>      }
>>
>> If we are exposing a specific qemu_plugin_set_pc we should probably
>> forbid setting it via write_register. Can we filter out the PC from the
>> register list?
> 
> The qemu_plugin_write_register API silently swallows writes to the PC
> even though such a write doesn't actually have an effect, so excluding
> the PC here might make sense and I'm happy to update the patch
> accordingly.
> Are there other registers that should be excluded as well?
> General-purpose register writes are visible to the guest immediately,
> but what about special registers? Do writes to those actually always
> have the intended effect or should they also be excluded here?

Actually, after looking into this for a bit, I don't think it's easily
feasible without a big revamp (but please correct me if I'm wrong or
simply missing something).

The problem is that the opaque handle passed to the plugin API only
encodes a register offset, not its name or type. So to exclude the PC,
we'd need to expose the register name to the API (which would
likely require either duplication of the name in both `struct
qemu_plugin_reg_descriptor` and `struct qemu_plugin_register` or
changing the API) and then filter in the API based on the register name
("pc", "rip", "eip", ...). This seems rather hacky and fragile to me.

Alternatively, we could encode whether a register is to be filtered out
or not in the opaque handle itself (e.g., by setting the topmost bit).
This still requires getting this information from somewhere, though.
Currently, registers are created by parsing the target XML in `gdb-xml/`
at compile time. The PC is generally marked as `type="code_ptr"` in the
XML, so we could expose this type information to the code and adjust the
register handle if it's a code pointer. The problem here is that it's
not just the PC that is marked as `code_ptr` in the XML; there may be
other registers as well (e.g., `lr` or `ra` for Arm and RISC-V).

I'm not sure whether the above explanation is clear enough, so please
let me know if you'd like me to clarify anything or point you to the
exact spots in the code.

Thanks,
Florian

Reply via email to