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 a T 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§

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.