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§
- Errors that can occur in the qemu-plugin crate
- Installation for the QEMU plugin
- Traits and helpers enabling idiomatic QEMU plugin implementation
- Re-exported sys API bindings. These bindings should not be used directly in most cases.
- Tools for checking whether the plugin version and the QEMU version are compatible
Structs§
- Wrapper structure for a
qemu_plugin_hwaddr *
- Wrapper structure for a
qemu_plugin_insn *
- Wrapper structure for a
qemu_plugin_meminfo_t
- Wrapper structure for a
qemu_plugin_register_descriptor
- 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 aT
should include a check for whether it is initialized. - Wrapper structure for a
qemu_plugin_tb *
- An iterator over the instructions of a translation block
Functions§
- 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. - 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. - 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. - 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.
- Return the number of vCPUs, if running in system mode
- Output a string via the QEMU logging mechanism
- 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.
- Register a callback to run once execution is finished. Plugins should be able to free all their resources at this point.
- Register a callback to run on flush.
- 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.
- 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.
- 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.
- Register a callback to be called when an instruction is executed.
- Register an inline callback to be called when an instruction is executed.
- 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.
- Register an inline callback for every memory transaction of a particular instruction.
- 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.
- Register a callback to run on Syscall
- Register a callback to run on Syscall return
- Register a callback to be called when a translation block is executed.
- Register an inline callback to be called when a translation block is executed.
- 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. - Reset a plugin
- Get the sum of all VCPU entries in a scoreboard
- 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. - Add a value to a
PluginU64
for a given VCPU - Get the value of a
PluginU64
for a given VCPU - Set the value of a
PluginU64
for a given VCPU - Uninstall a plugin.
Type Aliases§
- Flags for callbacks
- A callback called on flush.
- Memory read/write flags
- A plugin ID
- Plugin operations for inline operations
- 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.
- A callback called on Syscall entry
- A callback called on Syscall return
- A callback that can be called many times, each time a vCPU exits
- A callback that can be called many times, each time a vCPU idles
- The index of a vCPU
- A callback that can be called many times, each time a vCPU is initialized
- A callback that can be called many times, each time a vCPU is resumed
- 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.