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 = "8.2.2-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.

Structs§

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.
  • Return the maximum number of vCPUs, if running in system mode
  • 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 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 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 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
  • 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.
  • Uninstall a plugin.

Type Aliases§

  • Flags for callbacks
  • A callback called on flush.
  • Memory read/write flags
  • A plugin ID
  • 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.