debug_worker/gdb/targets/
mod.rs1use super::VmProxy;
5use gdbstub::target::Target;
6use gdbstub::target::TargetError;
7use gdbstub::target::ext::target_description_xml_override::TargetDescriptionXmlOverrideOps;
8use std::marker::PhantomData;
9use std::ops::Deref;
10use std::ops::DerefMut;
11use vmm_core_defs::debug_rpc::DebuggerVpState;
12
13mod base;
14mod breakpoints;
15mod target_aarch64;
16mod target_i8086;
17mod target_x86_64_qemu;
18
19pub trait ToTargetResult<T, E> {
20 fn fatal(self) -> Result<T, TargetError<E>>;
21 fn nonfatal(self) -> Result<T, TargetError<E>>;
22}
23
24impl<T, E> ToTargetResult<T, anyhow::Error> for Result<T, E>
25where
26 E: Into<anyhow::Error>,
27{
28 fn fatal(self) -> Result<T, TargetError<anyhow::Error>> {
29 self.map_err(|err| {
30 let err: anyhow::Error = err.into();
31 tracing::error!(
32 error = err.as_ref() as &dyn std::error::Error,
33 "gdb fatal error"
34 );
35 TargetError::Fatal(err)
36 })
37 }
38
39 fn nonfatal(self) -> Result<T, TargetError<anyhow::Error>> {
40 self.map_err(|err| {
41 let err = err.into();
42 tracing::warn!(
43 error = err.as_ref() as &dyn std::error::Error,
44 "gdb nonfatal error"
45 );
46 TargetError::Io(std::io::Error::other(err))
47 })
48 }
49}
50
51pub struct ArchError;
52
53impl<E> From<ArchError> for TargetError<E> {
54 fn from(_: ArchError) -> Self {
55 TargetError::NonFatal
56 }
57}
58
59pub trait TargetArch:
61 gdbstub::arch::Arch<Usize = Self::Address, BreakpointKind = usize> + Sized
62{
63 type Address: Copy + Into<u64> + TryFrom<u64>;
64
65 fn register(
67 state: &DebuggerVpState,
68 reg_id: Self::RegId,
69 buf: &mut [u8],
70 ) -> Result<usize, ArchError>;
71
72 fn registers(state: &DebuggerVpState, regs: &mut Self::Registers) -> Result<(), ArchError>;
74
75 fn update_registers(
79 state: &mut DebuggerVpState,
80 regs: &Self::Registers,
81 ) -> Result<(), ArchError>;
82
83 fn update_register(
85 state: &mut DebuggerVpState,
86 reg_id: Self::RegId,
87 val: &[u8],
88 ) -> Result<(), ArchError>;
89
90 fn support_target_description_xml_override<'a, 'b>(
92 target: &'a mut VmTarget<'b, Self>,
93 ) -> Option<TargetDescriptionXmlOverrideOps<'a, VmTarget<'b, Self>>> {
94 let _ = target;
95 None
96 }
97}
98
99pub struct VmTarget<'a, T>(&'a mut VmProxy, PhantomData<T>);
101
102impl<'a, T: TargetArch> VmTarget<'a, T> {
103 pub fn new(vm_proxy: &'a mut VmProxy) -> Self {
104 Self(vm_proxy, PhantomData)
105 }
106}
107
108impl<T> Deref for VmTarget<'_, T> {
109 type Target = VmProxy;
110
111 fn deref(&self) -> &Self::Target {
112 self.0
113 }
114}
115
116impl<T> DerefMut for VmTarget<'_, T> {
117 fn deref_mut(&mut self) -> &mut Self::Target {
118 self.0
119 }
120}
121
122impl<T: TargetArch> Target for VmTarget<'_, T> {
123 type Arch = T;
124 type Error = anyhow::Error;
125
126 fn use_rle(&self) -> bool {
128 false
129 }
130
131 #[inline(always)]
132 fn base_ops(&mut self) -> gdbstub::target::ext::base::BaseOps<'_, Self::Arch, Self::Error> {
133 gdbstub::target::ext::base::BaseOps::MultiThread(self)
134 }
135
136 #[inline(always)]
137 fn support_target_description_xml_override(
138 &mut self,
139 ) -> Option<TargetDescriptionXmlOverrideOps<'_, Self>> {
140 T::support_target_description_xml_override(self)
141 }
142
143 #[inline(always)]
144 fn support_breakpoints(
145 &mut self,
146 ) -> Option<gdbstub::target::ext::breakpoints::BreakpointsOps<'_, Self>> {
147 Some(self)
148 }
149
150 fn guard_rail_implicit_sw_breakpoints(&self) -> bool {
155 true
156 }
157}