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 *
- Memory
Info - Wrapper structure for a
qemu_plugin_meminfo_t
- Register
Descriptor - 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 aT
should include a check for whether it is initialized. - Translation
Block - Wrapper structure for a
qemu_plugin_tb *
- Translation
Block Iterator - 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§
- Callback
Flags - Flags for callbacks
- Flush
Callback - A callback called on flush.
- MemRW
- Memory read/write flags
- Plugin
Id - A plugin ID
- Plugin
Op - Plugin operations for inline operations
- Plugin
U64 - 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.
- Syscall
Callback - A callback called on Syscall entry
- Syscall
Return Callback - A callback called on Syscall return
- VCPU
Exit Callback - A callback that can be called many times, each time a vCPU exits
- VCPU
Idle Callback - A callback that can be called many times, each time a vCPU idles
- VCPU
Index - The index of a vCPU
- VCPU
Init Callback - A callback that can be called many times, each time a vCPU is initialized
- VCPU
Resume Callback - A callback that can be called many times, each time a vCPU is resumed
- VCPU
Translation Block Translation Callback - 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.