Skip to content

Commit

Permalink
Fix some typos and add conditional API for V3
Browse files Browse the repository at this point in the history
  • Loading branch information
novafacing committed Jun 3, 2024
1 parent a2496bc commit ae16a6d
Show file tree
Hide file tree
Showing 6 changed files with 261 additions and 45 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ jobs:
container: ubuntu:24.04
env:
# Hash of v3
QEMU_COMMIT_HASH: 4abc892362f8282450f18c4e45c5b0534461d01e
QEMU_COMMIT_HASH: 7de77d37880d7267a491cb32a1b2232017d1e545
steps:
- name: Set up Sources List
run: |
Expand Down
39 changes: 27 additions & 12 deletions plugins/tracer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,19 +149,17 @@ impl Tracer {
}

impl HasCallbacks for Tracer {
#[cfg(any(feature = "plugin-api-v2", feature = "plugin-api-v3"))]
fn on_vcpu_init(
&mut self,
_id: PluginId,
_vcpu_id: VCPUIndex,
) -> std::prelude::v1::Result<(), anyhow::Error> {
#[cfg(any(feature = "plugin-api-v2", feature = "plugin-api-v3"))]
{
*self
.registers
.lock()
.map_err(|e| anyhow!("Failed to lock registers: {}", e))? =
qemu_plugin_get_registers()?;
}
*self
.registers
.lock()
.map_err(|e| anyhow!("Failed to lock registers: {}", e))? =
qemu_plugin_get_registers()?;
Ok(())
}

Expand All @@ -173,6 +171,27 @@ impl HasCallbacks for Tracer {
tb.instructions().try_for_each(|insn| {
let event = InstructionEvent::try_from(&insn)?;

#[cfg(feature = "plugin-api-v1")]
if self.log_insns {
let tx = self.tx.clone();

insn.register_execute_callback(move |_| {
tx.lock()
.map_err(|e| anyhow!("Failed to lock tx: {}", e))
.and_then(|tx| {
to_writer(
tx.as_ref().ok_or_else(|| anyhow!("No tx"))?,
&Event::Instruction {
event: event.clone(),
},
)
.map_err(|e| anyhow!(e))
})
.expect("Failed to send instruction event");
});
}

#[cfg(any(feature = "plugin-api-v2", feature = "plugin-api-v3"))]
if self.log_insns {
let tx = self.tx.clone();
let registers = self
Expand All @@ -189,10 +208,6 @@ impl HasCallbacks for Tracer {
tx.as_ref().ok_or_else(|| anyhow!("No tx"))?,
&Event::Instruction {
event: event.clone(),
#[cfg(any(
feature = "plugin-api-v2",
feature = "plugin-api-v3"
))]
registers: Registers(
registers
.iter()
Expand Down
9 changes: 4 additions & 5 deletions qemu-plugin-sys/generate-bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ const QEMU_SRC_URL_BASE: &str = "https://download.qemu.org/";
const QEMU_VERSION_V1: &str = "8.2.4";
// Plugin V2 is from 9.0.0
const QEMU_VERSION_V2: &str = "9.0.0";
/// Plugin V3 is from 4abc892362f8282450f18c4e45c5b0534461d01e
const QEMU_VERSION_V3: &str = "4abc892362f8282450f18c4e45c5b0534461d01e";
/// Plugin V3 is from 7de77d37880d7267a491cb32a1b2232017d1e545
const QEMU_VERSION_V3: &str = "7de77d37880d7267a491cb32a1b2232017d1e545";

fn qemu_src_url_v1() -> String {
format!("{}qemu-{}.tar.xz", QEMU_SRC_URL_BASE, QEMU_VERSION_V1)
Expand All @@ -48,7 +48,7 @@ fn qemu_src_url_v2() -> String {
}

fn qemu_src_url_v3() -> String {
format!("{}/archive/4abc892362f8282450f18c4e45c5b0534461d01e.zip", QEMU_GITHUB_URL_BASE)
format!("{}/archive/{}.zip", QEMU_GITHUB_URL_BASE, QEMU_VERSION_V3)
}

/// Download a URL to a destination, using a blocking request
Expand Down Expand Up @@ -91,7 +91,7 @@ fn extract_txz(archive: &Path, destination: &Path) -> Result<()> {
Ok(())
}

/// Extract a zip frile at a path to a destination
/// Extract a zip file at a path to a destination
fn extract_zip(archive: &Path, destination: &Path) -> Result<()> {
let archive = File::open(archive)?;
let mut archive = ZipArchive::new(archive)?;
Expand All @@ -108,7 +108,6 @@ fn generate_windows_delaylink_library(qemu_plugin_symbols: &Path, destination: &
}

fn generate_bindings(qemu_plugin_header: &Path, destination: &Path) -> Result<()> {
// let glib_20 = probe_library("glib-2.0").map_err(|e| anyhow!(e))?;
let header_contents = read_to_string(qemu_plugin_header)?;
let header_file_name = qemu_plugin_header.file_name().ok_or_else(|| anyhow!("Failed to get file name"))?.to_str().ok_or_else(|| anyhow!("Failed to convert file name to string"))?;
let header_contents = header_contents.replace("#include <glib.h>", "");
Expand Down
40 changes: 39 additions & 1 deletion qemu-plugin-sys/src/bindings_v3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,19 @@ pub enum qemu_plugin_mem_rw {
QEMU_PLUGIN_MEM_W = 2,
QEMU_PLUGIN_MEM_RW = 3,
}
#[repr(u32)]
#[doc = " enum qemu_plugin_cond - condition to enable callback\n\n @QEMU_PLUGIN_COND_NEVER: false\n @QEMU_PLUGIN_COND_ALWAYS: true\n @QEMU_PLUGIN_COND_EQ: is equal?\n @QEMU_PLUGIN_COND_NE: is not equal?\n @QEMU_PLUGIN_COND_LT: is less than?\n @QEMU_PLUGIN_COND_LE: is less than or equal?\n @QEMU_PLUGIN_COND_GT: is greater than?\n @QEMU_PLUGIN_COND_GE: is greater than or equal?"]
#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]
pub enum qemu_plugin_cond {
QEMU_PLUGIN_COND_NEVER = 0,
QEMU_PLUGIN_COND_ALWAYS = 1,
QEMU_PLUGIN_COND_EQ = 2,
QEMU_PLUGIN_COND_NE = 3,
QEMU_PLUGIN_COND_LT = 4,
QEMU_PLUGIN_COND_LE = 5,
QEMU_PLUGIN_COND_GT = 6,
QEMU_PLUGIN_COND_GE = 7,
}
#[doc = " typedef qemu_plugin_vcpu_tb_trans_cb_t - translation callback\n @id: unique plugin id\n @tb: opaque handle used for querying and instrumenting a block."]
pub type qemu_plugin_vcpu_tb_trans_cb_t =
::std::option::Option<unsafe extern "C" fn(id: qemu_plugin_id_t, tb: *mut qemu_plugin_tb)>;
Expand All @@ -204,11 +217,24 @@ extern "C" {
userdata: *mut ::std::os::raw::c_void,
);
}
extern "C" {
#[doc = " qemu_plugin_register_vcpu_tb_exec_cond_cb() - register conditional callback\n @tb: the opaque qemu_plugin_tb handle for the translation\n @cb: callback function\n @cond: condition to enable callback\n @entry: first operand for condition\n @imm: second operand for condition\n @flags: does the plugin read or write the CPU's registers?\n @userdata: any plugin data to pass to the @cb?\n\n The @cb function is called when a translated unit executes if\n entry @cond imm is true.\n If condition is QEMU_PLUGIN_COND_ALWAYS, condition is never interpreted and\n this function is equivalent to qemu_plugin_register_vcpu_tb_exec_cb.\n If condition QEMU_PLUGIN_COND_NEVER, condition is never interpreted and\n callback is never installed."]
pub fn qemu_plugin_register_vcpu_tb_exec_cond_cb(
tb: *mut qemu_plugin_tb,
cb: qemu_plugin_vcpu_udata_cb_t,
flags: qemu_plugin_cb_flags,
cond: qemu_plugin_cond,
entry: qemu_plugin_u64,
imm: u64,
userdata: *mut ::std::os::raw::c_void,
);
}
#[repr(u32)]
#[doc = " enum qemu_plugin_op - describes an inline op\n\n @QEMU_PLUGIN_INLINE_ADD_U64: add an immediate value uint64_t\n\n Note: currently only a single inline op is supported."]
#[doc = " enum qemu_plugin_op - describes an inline op\n\n @QEMU_PLUGIN_INLINE_ADD_U64: add an immediate value uint64_t\n @QEMU_PLUGIN_INLINE_STORE_U64: store an immediate value uint64_t"]
#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]
pub enum qemu_plugin_op {
QEMU_PLUGIN_INLINE_ADD_U64 = 0,
QEMU_PLUGIN_INLINE_STORE_U64 = 1,
}
extern "C" {
#[doc = " qemu_plugin_register_vcpu_tb_exec_inline_per_vcpu() - execution inline op\n @tb: the opaque qemu_plugin_tb handle for the translation\n @op: the type of qemu_plugin_op (e.g. ADD_U64)\n @entry: entry to run op\n @imm: the op data (e.g. 1)\n\n Insert an inline op on a given scoreboard entry."]
Expand All @@ -228,6 +254,18 @@ extern "C" {
userdata: *mut ::std::os::raw::c_void,
);
}
extern "C" {
#[doc = " qemu_plugin_register_vcpu_insn_exec_cond_cb() - conditional insn execution cb\n @insn: the opaque qemu_plugin_insn handle for an instruction\n @cb: callback function\n @flags: does the plugin read or write the CPU's registers?\n @cond: condition to enable callback\n @entry: first operand for condition\n @imm: second operand for condition\n @userdata: any plugin data to pass to the @cb?\n\n The @cb function is called when an instruction executes if\n entry @cond imm is true.\n If condition is QEMU_PLUGIN_COND_ALWAYS, condition is never interpreted and\n this function is equivalent to qemu_plugin_register_vcpu_insn_exec_cb.\n If condition QEMU_PLUGIN_COND_NEVER, condition is never interpreted and\n callback is never installed."]
pub fn qemu_plugin_register_vcpu_insn_exec_cond_cb(
insn: *mut qemu_plugin_insn,
cb: qemu_plugin_vcpu_udata_cb_t,
flags: qemu_plugin_cb_flags,
cond: qemu_plugin_cond,
entry: qemu_plugin_u64,
imm: u64,
userdata: *mut ::std::os::raw::c_void,
);
}
extern "C" {
#[doc = " qemu_plugin_register_vcpu_insn_exec_inline_per_vcpu() - insn exec inline op\n @insn: the opaque qemu_plugin_insn handle for an instruction\n @op: the type of qemu_plugin_op (e.g. ADD_U64)\n @entry: entry to run op\n @imm: the op data (e.g. 1)\n\n Insert an inline op to every time an instruction executes."]
pub fn qemu_plugin_register_vcpu_insn_exec_inline_per_vcpu(
Expand Down
2 changes: 2 additions & 0 deletions qemu-plugin-sys/src/qemu_plugin_api_v3.def
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,15 @@ EXPORTS
qemu_plugin_register_vcpu_idle_cb
qemu_plugin_register_vcpu_init_cb
qemu_plugin_register_vcpu_insn_exec_cb
qemu_plugin_register_vcpu_insn_exec_cond_cb
qemu_plugin_register_vcpu_insn_exec_inline_per_vcpu
qemu_plugin_register_vcpu_mem_cb
qemu_plugin_register_vcpu_mem_inline_per_vcpu
qemu_plugin_register_vcpu_resume_cb
qemu_plugin_register_vcpu_syscall_cb
qemu_plugin_register_vcpu_syscall_ret_cb
qemu_plugin_register_vcpu_tb_exec_cb
qemu_plugin_register_vcpu_tb_exec_cond_cb
qemu_plugin_register_vcpu_tb_exec_inline_per_vcpu
qemu_plugin_register_vcpu_tb_trans_cb
qemu_plugin_reset
Expand Down
Loading

0 comments on commit ae16a6d

Please sign in to comment.