Crate qemu_plugin

Source
Expand description

High level idiomatic Rust bindings to the QEMU plugin API

qemu-plugin makes it easy to write QEMU plugins in Rust.

§Example

Below is a minimal plugin example for a plugin which prints the execution trace of the program running in QEMU. Notice that all we do is register a struct which implements Plugin, and the library takes care of the rest.

use anyhow::Result;
use ctor::ctor;
use qemu_plugin::{
    plugin::{HasCallbacks, Plugin, Register, PLUGIN},
    PluginId, TranslationBlock,
};
use std::sync::Mutex;

struct TinyTrace {}

impl Register for TinyTrace {}

impl HasCallbacks for TinyTrace {
    fn on_translation_block_translate(
        &mut self,
        _id: PluginId,
        tb: TranslationBlock,
    ) -> Result<()> {
        tb.instructions().enumerate().try_for_each(|(idx, insn)| {
            if idx == 0 {
                println!("====TB: {:08x}", insn.vaddr());
            }

            println!("{:08x}: {}", insn.vaddr(), insn.disas()?);
            Ok::<(), anyhow::Error>(())
        })?;

        Ok(())
    }
}

impl Plugin for TinyTrace {}

#[ctor]
fn init() {
    PLUGIN
        .set(Mutex::new(Box::new(TinyTrace {})))
        .map_err(|_| anyhow::anyhow!("Failed to set plugin"))
        .expect("Failed to set plugin");
}

The above src/lib.rs in a Cargo project with the following Cargo.toml will compile to libtiny.so, which can be loaded in QEMU by running qemu-system-ARCH -plugin ./libtiny.so.

[package]
name = "tiny"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = ["cdylib"]

[dependencies]
qemu-plugin = "9.0.0-v0"
anyhow = "1.0.75"
ffi = "0.1.0"
ctor = "0.2.6"

Modules§

error
Errors that can occur in the qemu-plugin crate
install
Installation for the QEMU plugin
plugin
Traits and helpers enabling idiomatic QEMU plugin implementation
sys
Re-exported sys API bindings. These bindings should not be used directly in most cases.
version
Tools for checking whether the plugin version and the QEMU version are compatible

Structs§

HwAddr
Wrapper structure for a qemu_plugin_hwaddr *
Instruction
Wrapper structure for a qemu_plugin_insn *
MemoryInfo
Wrapper structure for a qemu_plugin_meminfo_t
RegisterDescriptor
Wrapper structure for a qemu_plugin_register_descriptor
Scoreboard
A wrapper structure for a qemu_plugin_scoreboard *. This is a way of having one entry per VCPU, the count of which is managed automatically by QEMU. Keep in mind that additional entries and existing entries will be allocated and reallocated by qemu, not by the plugin, so every use of a T should include a check for whether it is initialized.
TranslationBlock
Wrapper structure for a qemu_plugin_tb *
TranslationBlockIterator
An iterator over the instructions of a translation block

Functions§

qemu_plugin_bool_parse
Parse a boolean argument in the form of =[on|yes|true|off|no|false]. returns true if the combination @name=@val parses correctly to a boolean argument, and false otherwise.
qemu_plugin_end_code
Return the end of the text segment of the binary file being executed if running in user mode, or None if running in System mode. If not running in system mode, None may be interpreted as zero by callers, but the caller must take care to ensure the plugin is not running in a system mode context.
qemu_plugin_entry_code
Return the start address for the module of the binary file being executed if running in user mode, or None if running in System mode. If not running in system mode, None may be interpreted as zero by callers, but the caller must take care to ensure the plugin is not running in a system mode context.
qemu_plugin_get_registers
Returns a potentially empty list of registers. This should be used from a qemu_plugin_register_vcpu_init_cb callback after the vcpu has been initialized.
qemu_plugin_num_vcpus
Return the number of vCPUs, if running in system mode
qemu_plugin_outs
Output a string via the QEMU logging mechanism
qemu_plugin_path_to_binary
Return the path to the binary file being executed if running in user mode, or None if running in System mode. Return an error if the path cannot be converted to a string.
qemu_plugin_register_atexit_cb
Register a callback to run once execution is finished. Plugins should be able to free all their resources at this point.
qemu_plugin_register_flush_cb
Register a callback to run on flush.
qemu_plugin_register_vcpu_exit_cb
Register a callback to be called when a vCPU exits. The callback does not receive user data, so it is not possible to register it via closure.
qemu_plugin_register_vcpu_idle_cb
Register a callback to be called when a vCPU idles. The callback does not receive user data, so it is not possible to register it via closure.
qemu_plugin_register_vcpu_init_cb
Register a callback to be called when a vCPU is initialized. The callback does not receive user data, so it is not possible to register it via closure.
qemu_plugin_register_vcpu_insn_exec_cb
Register a callback to be called when an instruction is executed.
qemu_plugin_register_vcpu_insn_exec_inline_per_vcpu
Register an inline callback to be called when an instruction is executed.
qemu_plugin_register_vcpu_mem_cb
Register a callback for every memory transaction of a particular instruction. If the instruction is executed multiple times, the callback will be called multiple times.
qemu_plugin_register_vcpu_mem_inline_per_vcpu
Register an inline callback for every memory transaction of a particular instruction.
qemu_plugin_register_vcpu_resume_cb
Register a callback to be called when a vCPU resumes. The callback does not receive user data, so it is not possible to register it via closure.
qemu_plugin_register_vcpu_syscall_cb
Register a callback to run on Syscall
qemu_plugin_register_vcpu_syscall_ret_cb
Register a callback to run on Syscall return
qemu_plugin_register_vcpu_tb_exec_cb
Register a callback to be called when a translation block is executed.
qemu_plugin_register_vcpu_tb_exec_inline_per_vcpu
Register an inline callback to be called when a translation block is executed.
qemu_plugin_register_vcpu_tb_trans_cb
Register a callback to be called when a translation block is translated. The callback receives a pointer to a qemu_plugin_tb structure, which can be queried for additional information including the list of translated instructions. The callback can register further callbacks to be triggered when the block or individual instructions execute.
qemu_plugin_reset
Reset a plugin
qemu_plugin_scoreboard_sum
Get the sum of all VCPU entries in a scoreboard
qemu_plugin_start_code
Return the start of the text segment of the binary file being executed if running in user mode, or None if running in System mode. If not running in system mode, None may be interpreted as zero by callers, but the caller must take care to ensure the plugin is not running in a system mode context.
qemu_plugin_u64_add
Add a value to a PluginU64 for a given VCPU
qemu_plugin_u64_get
Get the value of a PluginU64 for a given VCPU
qemu_plugin_u64_set
Set the value of a PluginU64 for a given VCPU
qemu_plugin_uninstall
Uninstall a plugin.

Type Aliases§

CallbackFlags
Flags for callbacks
FlushCallback
A callback called on flush.
MemRW
Memory read/write flags
PluginId
A plugin ID
PluginOp
Plugin operations for inline operations
PluginU64
u64 member of an entry in a scoreboard, allows access to a specific u64 member in one given entry, located at a specified offset. Inline operations expect this as an entry.
SyscallCallback
A callback called on Syscall entry
SyscallReturnCallback
A callback called on Syscall return
VCPUExitCallback
A callback that can be called many times, each time a vCPU exits
VCPUIdleCallback
A callback that can be called many times, each time a vCPU idles
VCPUIndex
The index of a vCPU
VCPUInitCallback
A callback that can be called many times, each time a vCPU is initialized
VCPUResumeCallback
A callback that can be called many times, each time a vCPU is resumed
VCPUTranslationBlockTranslationCallback
A callback that can be called many times, each time a translation occurs. The callback is passed an opaque qemu_plugin_tb pointer, which can be queried for additional information including the list of translated instructions. The callback can register further callbacks to be triggered when the block or individual instructions execute.