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