QEMU TCG 插件
编写插件
API 版本
插件是 QEMU 的新功能,允许开发树外插件并动态链接到运行中的 QEMU。 但项目保留按需修改或破坏 API 的权利。 避免兼容问题的最好方式是将插件提交上游,以便 API 改变时一起更新。
所有插件必须导出声明构建时 API 版本的符号,例如:
QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION;
未导出 qemu_plugin_version,或版本超出 QEMU 支持范围时,核心拒绝加载。
传给 qemu_plugin_install 的 qemu_info_t 还会给出最低和当前支持版本。 添加 API 时递增当前版本,修改或移除已有 API 时递增最低版本。
查询句柄生命周期
每个回调提供不透明信息句柄,通常可继续查询翻译、指令或操作的信息。 句柄只在回调期间有效,因此需要的信息必须在回调中提取并由插件保存。
插件生命周期
首先加载插件并调用公开的 qemu_plugin_install,再由插件注册各类事件回调。 希望程序或系统结束时输出统计摘要的插件,通常注册 atexit 处理器。
事件发生时调用回调,可能提供额外信息。 翻译事件允许枚举块内指令,并为部分或全部指令注册执行回调。
也可以添加执行加法、存储立即数等操作的内联指令, 或根据内联计算的条件决定是否执行回调。 这些操作关联 scoreboard,它是随核心或线程创建自动扩容的线程本地存储, 无需加锁即可安全访问和修改。 内联操作与条件回调结合,比传统回调更高效地插桩二进制程序。
QEMU 退出时调用全部已注册 atexit 回调。
QEMU 内部细节的暴露
插件架构刻意避免暴露翻译实现细节。 虽然存在翻译时刻、翻译块等概念,其内部对插件仍不透明。 只能通过导出的 qemu_plugin 函数查询指定指令细节和系统配置。
不过可以依赖以下假设。
翻译块
全部代码都经过翻译,但翻译结果不一定执行。 要知道实际发生什么,必须对执行本身插桩。
同一地址被多次翻译很正常。 跟踪系统模式代码时,应查看 qemu_plugin_insn_haddr 提供的底层物理地址, 考虑虚拟内存影响;若系统发生换页,物理地址也可能变化。
块内不一定执行所有指令,要准确跟踪单条指令必须直接插桩。 不过异步中断不会在块中途改变控制流。
指令
指令插桩在执行前运行,能确定指令即将分派,却不能确定一定完成。 通常是因为执行触发 SIGILL 等同步异常。 若需确认完成,还应插桩下一指令。 execlog.c 展示如何跟踪并在执行后补齐信息。
内存访问
内存回调在加载或存储成功后调用。 失败访问对内存插桩不可见,但可观察其执行副作用,例如进入异常处理器。
系统空闲和恢复状态
qemu_plugin_register_vcpu_idle_cb 和 qemu_plugin_register_vcpu_resume_cb 可跟踪 CPU 等待外部 I/O 时进入和退出睡眠。 模拟效率较低,使 CPU 空闲机会更少,因此事件频率可能低于真实硬件。
内部实现
加锁
必须避免死锁,尤其在 MTTCG 下。 从插件代码调用时会加锁,回调列表同时受 RCU 保护, 因此执行回调无需持锁。 这也有利于性能,因为内存访问等回调可能非常频繁。
因此维护自己的 CPU 列表,避免与 cpu_list_lock 的加锁顺序问题。
使用递归锁,因为回调中可能再次注册。
注册和注销因加锁而较慢,但很少发生。 重点是调用或跳过回调时的性能,而非注册性能,RCU 很适合这一需求。
插件可随时请求卸载,包括在回调中,适合不再需要插桩时自行移除。 卸载是异步的,请求后仍可能触发回调。 只有全部 vCPU 静止时的安全工作执行完成,才算完全卸载。
插件 API
以下 API 从 include/plugins/qemu-plugin.h 的内联文档生成。 更新 API 时,请同时提供完整 kernel-doc 注释。
-
type qemu_plugin_id_t
Unique plugin ID
-
struct qemu_info_t
system information for plugins
Definition:
struct qemu_info_t {
const char *target_name;
struct {
int min;
int cur;
} version;
bool system_emulation;
union {
struct {
int smp_vcpus;
int max_vcpus;
} system;
};
};
Members
target_namestring describing architecture
versionminimum and current plugin API level
system_emulationis this a full system emulation?
{unnamed_union}anonymous
systeminformation relevant to system emulation
Description
This structure provides for some limited information about the system to allow the plugin to make decisions on how to proceed. For example it might only be suitable for running on some guest architectures or when under full system emulation.
-
int qemu_plugin_install(qemu_plugin_id_t id, const qemu_info_t *info, int argc, char **argv)
Install a plugin
Parameters
qemu_plugin_id_t idthis plugin's opaque ID
const qemu_info_t *infoa block describing some details about the guest
int argcnumber of arguments
char **argvarray of arguments (argc elements)
Description
All plugins must export this symbol which is called when the plugin is first loaded. Calling qemu_plugin_uninstall() from this function is a bug.
Note
info is only live during the call. Copy any information we want to keep. argv remains valid throughout the lifetime of the loaded plugin.
Return
0 on successful loading, !0 for an error.
-
qemu_plugin_udata_cb_t
Typedef: callback with user data
Syntax
void qemu_plugin_udata_cb_t (void *userdata)
Parameters
void *userdatauser data for callback
-
qemu_plugin_vcpu_udata_cb_t
Typedef: vcpu callback
Syntax
void qemu_plugin_vcpu_udata_cb_t (unsigned int vcpu_index, void *userdata)
Parameters
unsigned int vcpu_indexthe current vcpu context
void *userdatauser data for callback
-
enum qemu_plugin_discon_type
type of a (potential) PC discontinuity
Constants
QEMU_PLUGIN_DISCON_INTERRUPTan interrupt, defined across all architectures as an asynchronous event, usually originating from outside the CPU
QEMU_PLUGIN_DISCON_EXCEPTIONan exception, defined across all architectures as a synchronous event in response to a specific instruction being executed
QEMU_PLUGIN_DISCON_HOSTCALLa host call, functionally a special kind of exception that is not handled by code run by the vCPU but machinery outside the vCPU
QEMU_PLUGIN_DISCON_ALLall types of disconinuity events currently covered
-
qemu_plugin_vcpu_discon_cb_t
Typedef: vcpu discontinuity callback
Syntax
void qemu_plugin_vcpu_discon_cb_t (unsigned int vcpu_index, enum qemu_plugin_discon_type type, uint64_t from_pc, uint64_t to_pc, void *userdata)
Parameters
unsigned int vcpu_indexthe current vcpu context
enum qemu_plugin_discon_type typethe type of discontinuity
uint64_t from_pcthe source of the discontinuity, e.g. the PC before the transition
uint64_t to_pcthe PC pointing to the next instruction to be executed
void *userdatauser data for callback
Description
The exact semantics of from_pc depends on the type of discontinuity. For interrupts, from_pc will point to the next instruction which would have been executed. For exceptions and host calls, from_pc will point to the instruction that caused the exception or issued the host call. Note that in the case of exceptions, the instruction may not be retired and thus not observable via general instruction exec callbacks. The same may be the case for some host calls such as hypervisor call "exceptions".
-
void qemu_plugin_uninstall(qemu_plugin_id_t id, qemu_plugin_udata_cb_t cb, void *userdata)
Uninstall a plugin
Parameters
qemu_plugin_id_t idthis plugin's opaque ID
qemu_plugin_udata_cb_t cbcallback to be called once the plugin has been removed
void *userdatauser data for callback
Description
Do NOT assume that the plugin has been uninstalled once this function returns. Plugins are uninstalled asynchronously, and therefore the given plugin receives callbacks until cb is called.
Note
Calling this function from qemu_plugin_install() is a bug.
-
void qemu_plugin_reset(qemu_plugin_id_t id, qemu_plugin_udata_cb_t cb, void *userdata)
Reset a plugin
Parameters
qemu_plugin_id_t idthis plugin's opaque ID
qemu_plugin_udata_cb_t cbcallback to be called once the plugin has been reset
void *userdatauser data for callback
Description
Unregisters all callbacks for the plugin given by id.
Do NOT assume that the plugin has been reset once this function returns. Plugins are reset asynchronously, and therefore the given plugin receives callbacks until cb is called.
-
void qemu_plugin_register_vcpu_init_cb(qemu_plugin_id_t id, qemu_plugin_vcpu_udata_cb_t cb, void *userdata)
register a vCPU initialization callback
Parameters
qemu_plugin_id_t idplugin ID
qemu_plugin_vcpu_udata_cb_t cbcallback function
void *userdatauser data for callback
Description
The cb function is called every time a vCPU is initialized.
See also: qemu_plugin_register_vcpu_exit_cb()
-
void qemu_plugin_register_vcpu_exit_cb(qemu_plugin_id_t id, qemu_plugin_vcpu_udata_cb_t cb, void *userdata)
register a vCPU exit callback
Parameters
qemu_plugin_id_t idplugin ID
qemu_plugin_vcpu_udata_cb_t cbcallback function
void *userdatauser data for callback
Description
The cb function is called every time a vCPU exits.
See also: qemu_plugin_register_vcpu_init_cb()
-
void qemu_plugin_register_vcpu_idle_cb(qemu_plugin_id_t id, qemu_plugin_vcpu_udata_cb_t cb, void *userdata)
register a vCPU idle callback
Parameters
qemu_plugin_id_t idplugin ID
qemu_plugin_vcpu_udata_cb_t cbcallback function
void *userdatauser data for callback
Description
The cb function is called every time a vCPU idles.
-
void qemu_plugin_register_vcpu_resume_cb(qemu_plugin_id_t id, qemu_plugin_vcpu_udata_cb_t cb, void *userdata)
register a vCPU resume callback
Parameters
qemu_plugin_id_t idplugin ID
qemu_plugin_vcpu_udata_cb_t cbcallback function
void *userdatauser data for callback
Description
The cb function is called every time a vCPU resumes execution.
-
void qemu_plugin_register_vcpu_discon_cb(qemu_plugin_id_t id, enum qemu_plugin_discon_type type, qemu_plugin_vcpu_discon_cb_t cb, void *userdata)
register a discontinuity callback
Parameters
qemu_plugin_id_t idplugin ID
enum qemu_plugin_discon_type typetypes of discontinuities for which to call the callback
qemu_plugin_vcpu_discon_cb_t cbcallback function
void *userdatauser data for callback
Description
The cb function is called every time a vCPU receives a discontinuity event of the specified type(s), after the vCPU was prepared to handle the event. Preparation entails updating the PC, usually to some interrupt handler or trap vector entry.
-
type qemu_plugin_u64
uint64_t member of an entry in a scoreboard
Description
This field allows to access a specific uint64_t member in one given entry, located at a specified offset. Inline operations expect this as entry.
-
enum qemu_plugin_cb_flags
type of callback
Constants
QEMU_PLUGIN_CB_NO_REGScallback does not access the CPU's regs
QEMU_PLUGIN_CB_R_REGScallback reads the CPU's regs
QEMU_PLUGIN_CB_RW_REGScallback reads and writes the CPU's regs
QEMU_PLUGIN_CB_RW_REGS_PCcallback reads and writes the CPU's regs and updates the PC
-
enum qemu_plugin_mem_rw
type of memory access
Constants
QEMU_PLUGIN_MEM_Rmemory read access only
QEMU_PLUGIN_MEM_Wmemory write access only
QEMU_PLUGIN_MEM_RWmemory read and write access
-
enum qemu_plugin_mem_value_type
size of memory value
Constants
QEMU_PLUGIN_MEM_VALUE_U8unsigned 8-bit value
QEMU_PLUGIN_MEM_VALUE_U16unsigned 16-bit value
QEMU_PLUGIN_MEM_VALUE_U32unsigned 32-bit value
QEMU_PLUGIN_MEM_VALUE_U64unsigned 64-bit value
QEMU_PLUGIN_MEM_VALUE_U128unsigned 128-bit value
-
type qemu_plugin_mem_value
value accessed during a load/store
-
enum qemu_plugin_cond
condition to enable callback
Constants
QEMU_PLUGIN_COND_NEVERfalse
QEMU_PLUGIN_COND_ALWAYStrue
QEMU_PLUGIN_COND_EQis equal?
QEMU_PLUGIN_COND_NEis not equal?
QEMU_PLUGIN_COND_LTis less than?
QEMU_PLUGIN_COND_LEis less than or equal?
QEMU_PLUGIN_COND_GTis greater than?
QEMU_PLUGIN_COND_GEis greater than or equal?
-
qemu_plugin_vcpu_tb_trans_cb_t
Typedef: translation callback
Syntax
void qemu_plugin_vcpu_tb_trans_cb_t (struct qemu_plugin_tb *tb, void *userdata)
Parameters
struct qemu_plugin_tb *tbopaque handle used for querying and instrumenting a block.
void *userdataany plugin data to pass to the cb
-
void qemu_plugin_register_vcpu_tb_trans_cb(qemu_plugin_id_t id, qemu_plugin_vcpu_tb_trans_cb_t cb, void *userdata)
register a translate cb
Parameters
qemu_plugin_id_t idplugin ID
qemu_plugin_vcpu_tb_trans_cb_t cbcallback function
void *userdatauser data for callback
Description
The cb function is called every time a translation occurs. The cb function is passed an opaque qemu_plugin_type which it can query for additional information including the list of translated instructions. At this point the plugin can register further callbacks to be triggered when the block or individual instruction executes.
-
void qemu_plugin_register_vcpu_tb_exec_cb(struct qemu_plugin_tb *tb, qemu_plugin_vcpu_udata_cb_t cb, enum qemu_plugin_cb_flags flags, void *userdata)
register execution callback
Parameters
struct qemu_plugin_tb *tbthe opaque qemu_plugin_tb handle for the translation
qemu_plugin_vcpu_udata_cb_t cbcallback function
enum qemu_plugin_cb_flags flagsdoes the plugin read or write the CPU's registers?
void *userdatauser data for callback
Description
The cb function is called every time a translated unit executes.
-
void qemu_plugin_register_vcpu_tb_exec_cond_cb(struct qemu_plugin_tb *tb, qemu_plugin_vcpu_udata_cb_t cb, enum qemu_plugin_cb_flags flags, enum qemu_plugin_cond cond, qemu_plugin_u64 entry, uint64_t imm, void *userdata)
register conditional callback
Parameters
struct qemu_plugin_tb *tbthe opaque qemu_plugin_tb handle for the translation
qemu_plugin_vcpu_udata_cb_t cbcallback function
enum qemu_plugin_cb_flags flagsdoes the plugin read or write the CPU's registers?
enum qemu_plugin_cond condcondition to enable callback
qemu_plugin_u64 entryfirst operand for condition
uint64_t immsecond operand for condition
void *userdatauser data for callback
Description
The cb function is called when a translated unit executes if entry cond imm is true. If condition is QEMU_PLUGIN_COND_ALWAYS, condition is never interpreted and this function is equivalent to qemu_plugin_register_vcpu_tb_exec_cb. If condition QEMU_PLUGIN_COND_NEVER, condition is never interpreted and callback is never installed.
-
enum qemu_plugin_op
describes an inline op
Constants
QEMU_PLUGIN_INLINE_ADD_U64add an immediate value uint64_t
QEMU_PLUGIN_INLINE_STORE_U64store an immediate value uint64_t
-
void qemu_plugin_register_vcpu_tb_exec_inline_per_vcpu(struct qemu_plugin_tb *tb, enum qemu_plugin_op op, qemu_plugin_u64 entry, uint64_t imm)
execution inline op
Parameters
struct qemu_plugin_tb *tbthe opaque qemu_plugin_tb handle for the translation
enum qemu_plugin_op opthe type of qemu_plugin_op (e.g. ADD_U64)
qemu_plugin_u64 entryentry to run op
uint64_t immthe op data (e.g. 1)
Description
Insert an inline op on a given scoreboard entry.
-
void qemu_plugin_register_vcpu_insn_exec_cb(struct qemu_plugin_insn *insn, qemu_plugin_vcpu_udata_cb_t cb, enum qemu_plugin_cb_flags flags, void *userdata)
register insn execution cb
Parameters
struct qemu_plugin_insn *insnthe opaque qemu_plugin_insn handle for an instruction
qemu_plugin_vcpu_udata_cb_t cbcallback function
enum qemu_plugin_cb_flags flagsdoes the plugin read or write the CPU's registers?
void *userdatauser data for callback
Description
The cb function is called every time an instruction is executed
-
void qemu_plugin_register_vcpu_insn_exec_cond_cb(struct qemu_plugin_insn *insn, qemu_plugin_vcpu_udata_cb_t cb, enum qemu_plugin_cb_flags flags, enum qemu_plugin_cond cond, qemu_plugin_u64 entry, uint64_t imm, void *userdata)
conditional insn execution cb
Parameters
struct qemu_plugin_insn *insnthe opaque qemu_plugin_insn handle for an instruction
qemu_plugin_vcpu_udata_cb_t cbcallback function
enum qemu_plugin_cb_flags flagsdoes the plugin read or write the CPU's registers?
enum qemu_plugin_cond condcondition to enable callback
qemu_plugin_u64 entryfirst operand for condition
uint64_t immsecond operand for condition
void *userdatauser data for callback
Description
The cb function is called when an instruction executes if entry cond imm is true. If condition is QEMU_PLUGIN_COND_ALWAYS, condition is never interpreted and this function is equivalent to qemu_plugin_register_vcpu_insn_exec_cb. If condition QEMU_PLUGIN_COND_NEVER, condition is never interpreted and callback is never installed.
-
void qemu_plugin_register_vcpu_insn_exec_inline_per_vcpu(struct qemu_plugin_insn *insn, enum qemu_plugin_op op, qemu_plugin_u64 entry, uint64_t imm)
insn exec inline op
Parameters
struct qemu_plugin_insn *insnthe opaque qemu_plugin_insn handle for an instruction
enum qemu_plugin_op opthe type of qemu_plugin_op (e.g. ADD_U64)
qemu_plugin_u64 entryentry to run op
uint64_t immthe op data (e.g. 1)
Description
Insert an inline op to every time an instruction executes.
-
size_t qemu_plugin_tb_n_insns(const struct qemu_plugin_tb *tb)
query helper for number of insns in TB
Parameters
const struct qemu_plugin_tb *tbopaque handle to TB passed to callback
Return
number of instructions in this block
-
uint64_t qemu_plugin_tb_vaddr(const struct qemu_plugin_tb *tb)
query helper for vaddr of TB start
Parameters
const struct qemu_plugin_tb *tbopaque handle to TB passed to callback
Return
virtual address of block start
-
struct qemu_plugin_insn *qemu_plugin_tb_get_insn(const struct qemu_plugin_tb *tb, size_t idx)
retrieve handle for instruction
Parameters
const struct qemu_plugin_tb *tbopaque handle to TB passed to callback
size_t idxinstruction number, 0 indexed
Description
The returned handle can be used in follow up helper queries as well as when instrumenting an instruction. It is only valid for the lifetime of the callback.
Return
opaque handle to instruction
-
size_t qemu_plugin_insn_data(const struct qemu_plugin_insn *insn, void *dest, size_t len)
copy instruction data
Parameters
const struct qemu_plugin_insn *insnopaque instruction handle from qemu_plugin_tb_get_insn()
void *destdestination into which data is copied
size_t lenlength of dest
Description
Returns the number of bytes copied, minimum of len and insn size.
-
size_t qemu_plugin_insn_size(const struct qemu_plugin_insn *insn)
return size of instruction
Parameters
const struct qemu_plugin_insn *insnopaque instruction handle from qemu_plugin_tb_get_insn()
Return
size of instruction in bytes
-
uint64_t qemu_plugin_insn_vaddr(const struct qemu_plugin_insn *insn)
return vaddr of instruction
Parameters
const struct qemu_plugin_insn *insnopaque instruction handle from qemu_plugin_tb_get_insn()
Return
virtual address of instruction
-
void *qemu_plugin_insn_haddr(const struct qemu_plugin_insn *insn)
return hardware addr of instruction
Parameters
const struct qemu_plugin_insn *insnopaque instruction handle from qemu_plugin_tb_get_insn()
Return
hardware (physical) target address of instruction
-
type qemu_plugin_meminfo_t
opaque memory transaction handle
Description
This can be further queried using the qemu_plugin_mem_* query functions.
-
unsigned int qemu_plugin_mem_size_shift(qemu_plugin_meminfo_t info)
get size of access
Parameters
qemu_plugin_meminfo_t infoopaque memory transaction handle
Return
size of access in ^2 (0=byte, 1=16bit, 2=32bit etc...)
-
bool qemu_plugin_mem_is_sign_extended(qemu_plugin_meminfo_t info)
was the access sign extended
Parameters
qemu_plugin_meminfo_t infoopaque memory transaction handle
Return
true if it was, otherwise false
-
bool qemu_plugin_mem_is_big_endian(qemu_plugin_meminfo_t info)
was the access big endian
Parameters
qemu_plugin_meminfo_t infoopaque memory transaction handle
Return
true if it was, otherwise false
-
bool qemu_plugin_mem_is_store(qemu_plugin_meminfo_t info)
was the access a store
Parameters
qemu_plugin_meminfo_t infoopaque memory transaction handle
Return
true if it was, otherwise false
-
qemu_plugin_mem_value qemu_plugin_mem_get_value(qemu_plugin_meminfo_t info)
return last value loaded/stored
Parameters
qemu_plugin_meminfo_t infoopaque memory transaction handle
Return
memory value in host-endian order (no further swap is necessary).
-
struct qemu_plugin_hwaddr *qemu_plugin_get_hwaddr(qemu_plugin_meminfo_t info, uint64_t vaddr)
return handle for memory operation
Parameters
qemu_plugin_meminfo_t infoopaque memory info structure
uint64_t vaddrthe virtual address of the memory operation
Description
For system emulation returns a qemu_plugin_hwaddr handle to query details about the actual physical address backing the virtual address. For linux-user guests it just returns NULL.
This handle is only valid for the duration of the callback. Any information about the handle should be recovered before the callback returns.
-
bool qemu_plugin_hwaddr_is_io(const struct qemu_plugin_hwaddr *haddr)
query whether memory operation is IO
Parameters
const struct qemu_plugin_hwaddr *haddraddress handle from qemu_plugin_get_hwaddr()
Description
Returns true if the handle's memory operation is to memory-mapped IO, or false if it is to RAM
-
uint64_t qemu_plugin_hwaddr_phys_addr(const struct qemu_plugin_hwaddr *haddr)
query physical address for memory operation
Parameters
const struct qemu_plugin_hwaddr *haddraddress handle from qemu_plugin_get_hwaddr()
Description
Returns the physical address associated with the memory operation
Note that the returned physical address may not be unique if you are dealing with multiple address spaces.
-
qemu_plugin_vcpu_mem_cb_t
Typedef: memory callback function type
Syntax
void qemu_plugin_vcpu_mem_cb_t (unsigned int vcpu_index, qemu_plugin_meminfo_t info, uint64_t vaddr, void *userdata)
Parameters
unsigned int vcpu_indexthe executing vCPU
qemu_plugin_meminfo_t infoan opaque handle for further queries about the memory
uint64_t vaddrthe virtual address of the transaction
void *userdatauser data for callback
-
void qemu_plugin_register_vcpu_mem_cb(struct qemu_plugin_insn *insn, qemu_plugin_vcpu_mem_cb_t cb, enum qemu_plugin_cb_flags flags, enum qemu_plugin_mem_rw rw, void *userdata)
register memory access callback
Parameters
struct qemu_plugin_insn *insnhandle for instruction to instrument
qemu_plugin_vcpu_mem_cb_t cbcallback of type qemu_plugin_vcpu_mem_cb_t
enum qemu_plugin_cb_flags flags(currently unused) callback flags
enum qemu_plugin_mem_rw rwmonitor reads, writes or both
void *userdatauser data for callback
Description
This registers a full callback for every memory access generated by an instruction. If the instruction doesn't access memory no callback will be made.
The callback reports the vCPU the access took place on, the virtual address of the access and a handle for further queries. The user can attach some userdata to the callback for additional purposes.
Other execution threads will continue to execute during the callback so the plugin is responsible for ensuring it doesn't get confused by making appropriate use of locking if required.
-
void qemu_plugin_register_vcpu_mem_inline_per_vcpu(struct qemu_plugin_insn *insn, enum qemu_plugin_mem_rw rw, enum qemu_plugin_op op, qemu_plugin_u64 entry, uint64_t imm)
inline op for mem access
Parameters
struct qemu_plugin_insn *insnhandle for instruction to instrument
enum qemu_plugin_mem_rw rwapply to reads, writes or both
enum qemu_plugin_op opthe op, of type qemu_plugin_op
qemu_plugin_u64 entryentry to run op
uint64_t immimmediate data for op
Description
This registers a inline op every memory access generated by the instruction.
-
const void *qemu_plugin_request_time_control(void)
request the ability to control time
Parameters
voidno arguments
Description
This grants the plugin the ability to control system time. Only one plugin can control time so if multiple plugins request the ability all but the first will fail.
Returns an opaque handle or NULL if fails
-
void qemu_plugin_update_ns(const void *handle, int64_t time)
update system emulation time
Parameters
const void *handleopaque handle returned by qemu_plugin_request_time_control()
int64_t timetime in nanoseconds
Description
This allows an appropriately authorised plugin (i.e. holding the time control handle) to move system time forward to time. For user-mode emulation the time is not changed by this as all reported time comes from the host kernel.
Start time is 0.
-
qemu_plugin_vcpu_syscall_cb_t
Typedef: vCPU syscall callback function type
Syntax
void qemu_plugin_vcpu_syscall_cb_t (unsigned int vcpu_index, int64_t num, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5, uint64_t a6, uint64_t a7, uint64_t a8, void *userdata)
Parameters
unsigned int vcpu_indexthe executing vCPU
int64_t numthe syscall number
uint64_t a1the 1st syscall argument
uint64_t a2the 2nd syscall argument
uint64_t a3the 3rd syscall argument
uint64_t a4the 4th syscall argument
uint64_t a5the 5th syscall argument
uint64_t a6the 6th syscall argument
uint64_t a7the 7th syscall argument
uint64_t a8the 8th syscall argument
void *userdatauser data for callback
-
qemu_plugin_vcpu_syscall_filter_cb_t
Typedef: vCPU syscall filter callback function type
Syntax
bool qemu_plugin_vcpu_syscall_filter_cb_t (unsigned int vcpu_index, int64_t num, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5, uint64_t a6, uint64_t a7, uint64_t a8, int64_t *sysret, void *userdata)
Parameters
unsigned int vcpu_indexthe executing vCPU
int64_t numthe syscall number
uint64_t a1the 1st syscall argument
uint64_t a2the 2nd syscall argument
uint64_t a3the 3rd syscall argument
uint64_t a4the 4th syscall argument
uint64_t a5the 5th syscall argument
uint64_t a6the 6th syscall argument
uint64_t a7the 7th syscall argument
uint64_t a8the 8th syscall argument
int64_t *sysretreference of the syscall return value, must set this if filtered
void *userdatauser data for callback
Description
Returns true if you want to filter this syscall (i.e. stop it being handled further), otherwise returns false.
-
qemu_plugin_vcpu_syscall_ret_cb_t
Typedef: vCPU syscall return callback function type
Syntax
void qemu_plugin_vcpu_syscall_ret_cb_t (unsigned int vcpu_index, int64_t num, int64_t ret, void *userdata)
Parameters
unsigned int vcpu_indexthe executing vCPU
int64_t numthe syscall number
int64_t retthe syscall return value
void *userdatauser data for callback
-
void qemu_plugin_register_vcpu_syscall_cb(qemu_plugin_id_t id, qemu_plugin_vcpu_syscall_cb_t cb, void *userdata)
register a syscall entry callback
Parameters
qemu_plugin_id_t idplugin id
qemu_plugin_vcpu_syscall_cb_t cbcallback of type qemu_plugin_vcpu_syscall_cb_t
void *userdatauser data for callback
Description
This registers a callback for every syscall executed by the guest. The cb function is executed before a syscall is handled by the host.
-
void qemu_plugin_register_vcpu_syscall_filter_cb(qemu_plugin_id_t id, qemu_plugin_vcpu_syscall_filter_cb_t cb, void *userdata)
register a syscall filter callback
Parameters
qemu_plugin_id_t idplugin id
qemu_plugin_vcpu_syscall_filter_cb_t cbcallback of type qemu_plugin_vcpu_syscall_filter_cb_t
void *userdatauser data for callback
Description
This registers a callback for every syscall executed by the guest. The cb function is executed before a syscall is handled by the host. If the callback returns true, the syscall is filtered and will not be executed by the host. The callback must then set the syscall return value via the corresponding pointer passed to it.
-
void qemu_plugin_register_vcpu_syscall_ret_cb(qemu_plugin_id_t id, qemu_plugin_vcpu_syscall_ret_cb_t cb, void *userdata)
register a syscall entry callback
Parameters
qemu_plugin_id_t idplugin id
qemu_plugin_vcpu_syscall_ret_cb_t cbcallback of type qemu_plugin_vcpu_syscall_ret_cb_t
void *userdatauser data for callback
Description
This registers a callback for every syscall executed by the guest. The cb function is executed upon return from the host syscall before execution is handed back to the guest.
-
char *qemu_plugin_insn_disas(const struct qemu_plugin_insn *insn)
return disassembly string for instruction
Parameters
const struct qemu_plugin_insn *insninstruction reference
Description
Returns an allocated string containing the disassembly
-
const char *qemu_plugin_insn_symbol(const struct qemu_plugin_insn *insn)
best effort symbol lookup
Parameters
const struct qemu_plugin_insn *insninstruction reference
Description
Return a static string referring to the symbol. This is dependent on the binary QEMU is running having provided a symbol table.
-
void qemu_plugin_vcpu_for_each(qemu_plugin_id_t id, qemu_plugin_vcpu_udata_cb_t cb, void *userdata)
iterate over the existing vCPU
Parameters
qemu_plugin_id_t idplugin ID
qemu_plugin_vcpu_udata_cb_t cbcallback function
void *userdatauser data for callback
Description
The cb function is called once for each existing vCPU.
See also: qemu_plugin_register_vcpu_init_cb()
-
void qemu_plugin_register_flush_cb(qemu_plugin_id_t id, qemu_plugin_udata_cb_t cb, void *userdata)
register code cache flush callback
Parameters
qemu_plugin_id_t idplugin ID
qemu_plugin_udata_cb_t cbcallback
void *userdatauser data for callback
Description
The cb function is called every time the code cache is flushed. The callback can be used to free resources associated with existing translated blocks in a plugin. cb is guaranteed to run with all cpus being stopped, thus no lock is required within it.
-
void qemu_plugin_register_atexit_cb(qemu_plugin_id_t id, qemu_plugin_udata_cb_t cb, void *userdata)
register exit callback
Parameters
qemu_plugin_id_t idplugin ID
qemu_plugin_udata_cb_t cbcallback
void *userdatauser data for callback
Description
The cb function is called once execution has finished. Plugins should be able to free all their resources at this point much like after a reset/uninstall callback is called.
In user-mode it is possible a few un-instrumented instructions from child threads may run before the host kernel reaps the threads.
-
void qemu_plugin_outs(const char *string)
output string via QEMU's logging system
Parameters
const char *stringa string
-
bool qemu_plugin_bool_parse(const char *name, const char *val, bool *ret)
parses a boolean argument in the form of "<argname>=[on|yes|true|off|no|false]"
Parameters
const char *nameargument name, the part before the equals sign
const char *valargument value, what's after the equals sign
bool *retoutput return value
Description
returns true if the combination name**=**val parses correctly to a boolean argument, and false otherwise
-
const char *qemu_plugin_path_to_binary(void)
path to binary file being executed
Parameters
voidno arguments
Description
Return a string representing the path to the binary. For user-mode this is the main executable. For system emulation we currently return NULL. The user should g_free() the string once no longer needed.
-
uint64_t qemu_plugin_start_code(void)
returns start of text segment
Parameters
voidno arguments
Description
Returns the nominal start address of the main text segment in user-mode. Currently returns 0 for system emulation.
-
uint64_t qemu_plugin_end_code(void)
returns end of text segment
Parameters
voidno arguments
Description
Returns the nominal end address of the main text segment in user-mode. Currently returns 0 for system emulation.
-
uint64_t qemu_plugin_entry_code(void)
returns start address for module
Parameters
voidno arguments
Description
Returns the nominal entry address of the main text segment in user-mode. Currently returns 0 for system emulation.
-
type qemu_plugin_reg_descriptor
register descriptions
-
GArray *qemu_plugin_get_registers(void)
return register list for current vCPU
Parameters
voidno arguments
Description
Returns a potentially empty GArray of qemu_plugin_reg_descriptor. Caller frees the array (but not the const strings).
Should be used from a qemu_plugin_register_vcpu_init_cb() callback after the vCPU is initialised, i.e. in the vCPU context.
-
bool qemu_plugin_read_register(struct qemu_plugin_register *handle, GByteArray *buf)
read register for current vCPU
Parameters
struct qemu_plugin_register *handlea qemu_plugin_reg_handle handle
GByteArray *bufA GByteArray for the data owned by the plugin
Description
This function is only available in a context that register read access is explicitly requested via the QEMU_PLUGIN_CB_R_REGS flag, if called inside a callback that can be registered with a qemu_plugin_cb_flags argument. This function can also be used in any callback context that does not use a flags argument, such as in a callback registered with qemu_plugin_register_vcpu_init_cb(), except for callbacks registered with qemu_plugin_register_atexit_cb() and qemu_plugin_register_flush_cb().
Returns true on success, false on failure. The content of buf is in target byte order.
-
bool qemu_plugin_write_register(struct qemu_plugin_register *handle, GByteArray *buf)
write register for current vCPU
Parameters
struct qemu_plugin_register *handlea qemu_plugin_reg_handle handle
GByteArray *bufA GByteArray for the data owned by the plugin
Description
This function is only available in a context that register read access is explicitly requested via the QEMU_PLUGIN_CB_RW_REGS flag, if called inside a callback that can be registered with a qemu_plugin_cb_flags argument. This function can also be used in any callback context that does not use a flags argument, such as in a callback registered with qemu_plugin_register_vcpu_init_cb(), except for callbacks registered with qemu_plugin_register_atexit_cb() and qemu_plugin_register_flush_cb().
The size of buf must be at least the size of the requested register. Attempting to write a register with buf smaller than the register size will result in a crash or other undesired behavior.
Returns true on success, false on failure.
-
void qemu_plugin_set_pc(uint64_t vaddr)
set the program counter for the current vCPU
Parameters
uint64_t vaddrthe new virtual (guest) address for the program counter
Description
This function sets the program counter for the current vCPU to vaddr and resumes execution at that address. This function does not return.
-
bool qemu_plugin_read_memory_vaddr(uint64_t addr, GByteArray *data, size_t len)
read from memory using a virtual address
Parameters
uint64_t addrA virtual address to read from
GByteArray *dataA byte array to store data into
size_t lenThe number of bytes to read, starting from addr
Description
len bytes of data is read starting at addr and stored into data. If data is not large enough to hold len bytes, it will be expanded to the necessary size, reallocating if necessary. len must be greater than 0.
This function does not ensure writes are flushed prior to reading, so callers should take care when calling this function in plugin callbacks to avoid attempting to read data which may not yet be written and should use the memory callback API instead.
Returns true on success and false on failure.
-
bool qemu_plugin_write_memory_vaddr(uint64_t addr, GByteArray *data)
write to memory using a virtual address
Parameters
uint64_t addrA virtual address to write to
GByteArray *dataA byte array containing the data to write
Description
The contents of data will be written to memory starting at the virtual address addr.
This function does not guarantee consistency of writes, nor does it ensure that pending writes are flushed either before or after the write takes place, so callers should take care to only call this function in vCPU context (i.e. in callbacks) and avoid depending on the existence of data written using this function which may be overwritten afterward.
Returns true on success and false on failure.
-
enum qemu_plugin_hwaddr_operation_result
result of a memory operation
Constants
QEMU_PLUGIN_HWADDR_OPERATION_OKhwaddr operation succeeded
QEMU_PLUGIN_HWADDR_OPERATION_ERRORunexpected error occurred
QEMU_PLUGIN_HWADDR_OPERATION_DEVICE_ERRORerror in memory device
QEMU_PLUGIN_HWADDR_OPERATION_ACCESS_DENIEDpermission error
QEMU_PLUGIN_HWADDR_OPERATION_INVALID_ADDRESSaddress was invalid
QEMU_PLUGIN_HWADDR_OPERATION_INVALID_ADDRESS_SPACEinvalid address space
-
enum qemu_plugin_hwaddr_operation_result qemu_plugin_read_memory_hwaddr(uint64_t addr, GByteArray *data, size_t len)
read from memory using a hardware address
Parameters
uint64_t addrThe physical address to read from
GByteArray *dataA byte array to store data into
size_t lenThe number of bytes to read, starting from addr
Description
len bytes of data is read from the current memory space for the current vCPU starting at addr and stored into data. If data is not large enough to hold len bytes, it will be expanded to the necessary size, reallocating if necessary. len must be greater than 0.
This function does not ensure writes are flushed prior to reading, so callers should take care when calling this function in plugin callbacks to avoid attempting to read data which may not yet be written and should use the memory callback API instead.
This function is only valid for softmmu targets.
Returns a qemu_plugin_hwaddr_operation_result indicating the result of the operation.
-
enum qemu_plugin_hwaddr_operation_result qemu_plugin_write_memory_hwaddr(uint64_t addr, GByteArray *data)
write to memory using a hardware address
Parameters
uint64_t addrA physical address to write to
GByteArray *dataA byte array containing the data to write
Description
The contents of data will be written to memory starting at the hardware address addr in the current address space for the current vCPU.
This function does not guarantee consistency of writes, nor does it ensure that pending writes are flushed either before or after the write takes place, so callers should take care when calling this function in plugin callbacks to avoid depending on the existence of data written using this function which may be overwritten afterward. In addition, this function requires that the pages containing the address are not locked. Practically, this means that you should not write instruction memory in a current translation block inside a callback registered with qemu_plugin_register_vcpu_tb_trans_cb.
You can, for example, write instruction memory in a current translation block in a callback registered with qemu_plugin_register_vcpu_tb_exec_cb, although be aware that the write will not be flushed until after the translation block has finished executing. In general, this function should be used to write data memory or to patch code at a known address, not in a current translation block.
This function is only valid for softmmu targets.
Returns a qemu_plugin_hwaddr_operation_result indicating the result of the operation.
-
bool qemu_plugin_translate_vaddr(uint64_t vaddr, uint64_t *hwaddr)
translate virtual address for current vCPU
Parameters
uint64_t vaddrvirtual address to translate
uint64_t *hwaddrpointer to store the physical address
Description
This function is only valid in vCPU context (i.e. in callbacks) and is only valid for softmmu targets.
Returns true on success and false on failure.
-
struct qemu_plugin_scoreboard *qemu_plugin_scoreboard_new(size_t element_size)
alloc a new scoreboard
Parameters
size_t element_sizesize (in bytes) for one entry
Description
Returns a pointer to a new scoreboard. It must be freed using qemu_plugin_scoreboard_free.
-
void qemu_plugin_scoreboard_free(struct qemu_plugin_scoreboard *score)
free a scoreboard
Parameters
struct qemu_plugin_scoreboard *scorescoreboard to free
-
void *qemu_plugin_scoreboard_find(struct qemu_plugin_scoreboard *score, unsigned int vcpu_index)
get pointer to an entry of a scoreboard
Parameters
struct qemu_plugin_scoreboard *scorescoreboard to query
unsigned int vcpu_indexentry index
Description
Returns address of entry of a scoreboard matching a given vcpu_index. This address can be modified later if scoreboard is resized.
-
void qemu_plugin_u64_add(qemu_plugin_u64 entry, unsigned int vcpu_index, uint64_t added)
add a value to a qemu_plugin_u64 for a given vcpu
Parameters
qemu_plugin_u64 entryentry to query
unsigned int vcpu_indexentry index
uint64_t addedvalue to add
-
uint64_t qemu_plugin_u64_get(qemu_plugin_u64 entry, unsigned int vcpu_index)
get value of a qemu_plugin_u64 for a given vcpu
Parameters
qemu_plugin_u64 entryentry to query
unsigned int vcpu_indexentry index
-
void qemu_plugin_u64_set(qemu_plugin_u64 entry, unsigned int vcpu_index, uint64_t val)
set value of a qemu_plugin_u64 for a given vcpu
Parameters
qemu_plugin_u64 entryentry to query
unsigned int vcpu_indexentry index
uint64_t valnew value
-
uint64_t qemu_plugin_u64_sum(qemu_plugin_u64 entry)
return sum of all vcpu entries in a scoreboard
Parameters
qemu_plugin_u64 entryentry to sum