qemu_plugin/translation_block/
mod.rs1use crate::{
4 CallbackFlags, Error, Instruction, Result, VCPUIndex,
5 handle_qemu_plugin_register_vcpu_tb_exec_cb, sys::qemu_plugin_tb,
6};
7#[cfg(not(any(
8 feature = "plugin-api-v0",
9 feature = "plugin-api-v1",
10 feature = "plugin-api-v2"
11)))]
12use crate::{PluginCondition, PluginU64};
13use std::{ffi::c_void, marker::PhantomData};
14
15#[derive(Debug, Clone)]
16pub struct TranslationBlock<'a> {
44 pub(crate) translation_block: usize,
45 marker: PhantomData<&'a ()>,
46}
47
48impl<'a> From<*mut qemu_plugin_tb> for TranslationBlock<'a> {
49 fn from(tb: *mut qemu_plugin_tb) -> Self {
50 Self {
51 translation_block: tb as usize,
52 marker: PhantomData,
53 }
54 }
55}
56
57impl<'a> TranslationBlock<'a> {
58 pub fn size(&self) -> usize {
60 unsafe { crate::sys::qemu_plugin_tb_n_insns(self.translation_block as *mut qemu_plugin_tb) }
61 }
62
63 pub fn vaddr(&self) -> u64 {
65 unsafe { crate::sys::qemu_plugin_tb_vaddr(self.translation_block as *mut qemu_plugin_tb) }
66 }
67
68 pub fn instruction(&'a self, index: usize) -> Result<Instruction<'a>> {
75 let size = self.size();
76
77 if index >= size {
78 Err(Error::InvalidInstructionIndex { index, size })
79 } else {
80 Ok(Instruction::new(self, unsafe {
81 crate::sys::qemu_plugin_tb_get_insn(
82 self.translation_block as *mut qemu_plugin_tb,
83 index,
84 )
85 }))
86 }
87 }
88
89 pub fn instructions(&'a self) -> TranslationBlockIterator<'a> {
91 TranslationBlockIterator { tb: self, index: 0 }
92 }
93
94 pub fn register_execute_callback<F>(&self, cb: F)
100 where
101 F: FnMut(VCPUIndex) + Send + Sync + 'static,
102 {
103 self.register_execute_callback_flags(cb, CallbackFlags::QEMU_PLUGIN_CB_NO_REGS);
104 }
105
106 pub fn register_execute_callback_flags<F>(&self, cb: F, flags: CallbackFlags)
112 where
113 F: FnMut(VCPUIndex) + Send + Sync + 'static,
114 {
115 let callback = Box::new(cb);
116 let callback_box = Box::new(callback);
117 let userdata = Box::into_raw(callback_box) as *mut c_void;
118
119 unsafe {
120 crate::sys::qemu_plugin_register_vcpu_tb_exec_cb(
121 self.translation_block as *mut qemu_plugin_tb,
122 Some(handle_qemu_plugin_register_vcpu_tb_exec_cb::<F>),
123 flags,
124 userdata,
125 )
126 };
127 }
128
129 #[cfg(not(any(
130 feature = "plugin-api-v0",
131 feature = "plugin-api-v1",
132 feature = "plugin-api-v2"
133 )))]
134 pub fn register_conditional_execute_callback<F>(
144 &self,
145 cb: F,
146 cond: PluginCondition,
147 entry: PluginU64,
148 immediate: u64,
149 ) where
150 F: FnMut(VCPUIndex) + Send + Sync + 'static,
151 {
152 self.register_conditional_execute_callback_flags(
153 cb,
154 CallbackFlags::QEMU_PLUGIN_CB_NO_REGS,
155 cond,
156 entry,
157 immediate,
158 )
159 }
160
161 #[cfg(not(any(
162 feature = "plugin-api-v0",
163 feature = "plugin-api-v1",
164 feature = "plugin-api-v2"
165 )))]
166 pub fn register_conditional_execute_callback_flags<F>(
177 &self,
178 cb: F,
179 flags: CallbackFlags,
180 cond: PluginCondition,
181 entry: PluginU64,
182 immediate: u64,
183 ) where
184 F: FnMut(VCPUIndex) + Send + Sync + 'static,
185 {
186 let callback = Box::new(cb);
187 let callback_box = Box::new(callback);
188 let userdata = Box::into_raw(callback_box) as *mut c_void;
189
190 unsafe {
191 crate::sys::qemu_plugin_register_vcpu_tb_exec_cond_cb(
192 self.translation_block as *mut qemu_plugin_tb,
193 Some(handle_qemu_plugin_register_vcpu_tb_exec_cb::<F>),
194 flags,
195 cond,
196 entry,
197 immediate,
198 userdata,
199 )
200 };
201 }
202}
203
204pub struct TranslationBlockIterator<'a> {
206 tb: &'a TranslationBlock<'a>,
207 index: usize,
208}
209
210impl<'a> Iterator for TranslationBlockIterator<'a> {
211 type Item = Instruction<'a>;
212
213 fn next(&mut self) -> Option<Self::Item> {
214 let size = self.tb.size();
215
216 if self.index >= size {
217 None
218 } else {
219 let insn = self.tb.instruction(self.index).ok();
220 self.index += 1;
221 insn
222 }
223 }
224}