/
single_register_access.rs
85 lines (79 loc) · 3.2 KB
/
single_register_access.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
use super::prelude::*;
use crate::protocol::commands::ext::SingleRegisterAccess;
use crate::arch::{Arch, RegId};
use crate::target::ext::base::BaseOps;
impl<T: Target, C: Connection> GdbStubImpl<T, C> {
fn inner<Tid>(
res: &mut ResponseWriter<'_, C>,
ops: crate::target::ext::base::single_register_access::SingleRegisterAccessOps<'_, Tid, T>,
command: SingleRegisterAccess<'_>,
id: Tid,
) -> Result<HandlerStatus, Error<T::Error, C::Error>>
where
Tid: crate::is_valid_tid::IsValidTid,
{
let handler_status = match command {
SingleRegisterAccess::p(p) => {
let reg = <T::Arch as Arch>::RegId::from_raw_id(p.reg_id);
let (reg_id, reg_size) = match reg {
None => {
warn!("reg id {} does not map onto any known register", p.reg_id);
return Ok(HandlerStatus::Handled);
}
Some(v) => v,
};
let mut buf = p.buf;
if let Some(size) = reg_size {
buf = buf
.get_mut(..size.get())
.ok_or(Error::PacketBufferOverflow)?;
}
let len = ops.read_register(id, reg_id, buf).handle_error()?;
if len == 0 {
if let Some(size) = reg_size {
res.write_x(size.get())?;
} else {
return Err(Error::TargetMismatch);
}
} else {
if let Some(size) = reg_size {
if size.get() != len {
return Err(Error::TargetMismatch);
}
} else {
buf = buf.get_mut(..len).ok_or(Error::PacketBufferOverflow)?;
}
res.write_hex_buf(buf)?;
}
HandlerStatus::Handled
}
SingleRegisterAccess::P(p) => {
let reg = <T::Arch as Arch>::RegId::from_raw_id(p.reg_id);
match reg {
// empty packet indicates unrecognized query
None => return Ok(HandlerStatus::Handled),
Some((reg_id, _)) => ops.write_register(id, reg_id, p.val).handle_error()?,
}
HandlerStatus::NeedsOk
}
};
Ok(handler_status)
}
pub(crate) fn handle_single_register_access<'a>(
&mut self,
res: &mut ResponseWriter<'_, C>,
target: &mut T,
command: SingleRegisterAccess<'a>,
) -> Result<HandlerStatus, Error<T::Error, C::Error>> {
match target.base_ops() {
BaseOps::SingleThread(ops) => match ops.support_single_register_access() {
None => Ok(HandlerStatus::Handled),
Some(ops) => Self::inner(res, ops, command, ()),
},
BaseOps::MultiThread(ops) => match ops.support_single_register_access() {
None => Ok(HandlerStatus::Handled),
Some(ops) => Self::inner(res, ops, command, self.current_mem_tid),
},
}
}
}