1use probe_rs::MemoryInterface;
2
3use crate::{
4 Bitfield, DebugError, Variable, VariableCache, VariableLocation, VariableName, VariableType,
5 VariableValue,
6 language::{
7 ProgrammingLanguage,
8 value::{Value, format_float},
9 },
10};
11use std::fmt::{Display, Write};
12
13#[derive(Debug, Clone)]
14pub struct C;
15
16impl ProgrammingLanguage for C {
17 fn read_variable_value(
18 &self,
19 variable: &Variable,
20 memory: &mut dyn MemoryInterface,
21 variable_cache: &VariableCache,
22 ) -> VariableValue {
23 match variable.type_name.inner() {
24 _ if variable.memory_location == VariableLocation::Unknown => VariableValue::Empty,
25
26 VariableType::Base(name) => match name.as_str() {
27 "_Bool" => UnsignedInt::get_value(variable, None, memory, variable_cache).into(),
28 "char" => CChar::get_value(variable, memory, variable_cache).into(),
29
30 "unsigned char"
31 | "unsigned int"
32 | "short unsigned int"
33 | "long unsigned int"
34 | "long long unsigned int" => {
35 UnsignedInt::get_value(variable, None, memory, variable_cache).into()
36 }
37 "signed char"
38 | "int"
39 | "short int"
40 | "long int"
41 | "long long int"
42 | "signed int"
43 | "short signed int"
44 | "long signed int"
45 | "long long signed int" => {
46 SignedInt::get_value(variable, None, memory, variable_cache).into()
47 }
48
49 "float" => match variable.byte_size {
50 Some(4) | None => f32::get_value(variable, memory, variable_cache)
51 .map(|f| format_float(f as f64))
52 .into(),
53 Some(size) => {
54 VariableValue::Error(format!("Invalid byte size for float: {size}"))
55 }
56 },
57 "double" => match variable.byte_size {
58 Some(8) | None => f64::get_value(variable, memory, variable_cache)
59 .map(format_float)
60 .into(),
61 Some(size) => {
62 VariableValue::Error(format!("Invalid byte size for double: {size}"))
63 }
64 },
65 _undetermined_value => VariableValue::Empty,
66 },
67
68 VariableType::Bitfield(bitfield, name) => match name.inner() {
69 VariableType::Base(name) => {
70 if name.as_str().contains("unsigned") {
71 UnsignedInt::get_value(variable, Some(*bitfield), memory, variable_cache)
72 .into()
73 } else {
74 SignedInt::get_value(variable, Some(*bitfield), memory, variable_cache)
75 .into()
76 }
77 }
78
79 _undetermined_value => VariableValue::Empty,
80 },
81
82 _other => VariableValue::Empty,
83 }
84 }
85
86 fn update_variable(
87 &self,
88 variable: &Variable,
89 memory: &mut dyn MemoryInterface,
90 new_value: &str,
91 ) -> Result<(), DebugError> {
92 match variable.type_name.inner() {
93 VariableType::Base(name) => match name.as_str() {
94 "_Bool" => UnsignedInt::update_value(variable, None, memory, new_value),
95 "char" => CChar::update_value(variable, memory, new_value),
96 "unsigned char" | "unsigned int" | "short unsigned int" | "long unsigned int" => {
97 UnsignedInt::update_value(variable, None, memory, new_value)
98 }
99 "signed char" | "int" | "short int" | "long int" | "signed int"
100 | "short signed int" | "long signed int" => {
101 SignedInt::update_value(variable, None, memory, new_value)
102 }
103 "float" => f32::update_value(variable, memory, new_value),
104 other => Err(DebugError::WarnAndContinue {
106 message: format!("Updating {other} variables is not yet supported."),
107 }),
108 },
109
110 VariableType::Bitfield(bitfield, name) => match name.inner() {
111 VariableType::Base(name) => {
112 if name.as_str().contains("unsigned") {
113 UnsignedInt::update_value(variable, Some(*bitfield), memory, new_value)
114 } else {
115 SignedInt::update_value(variable, Some(*bitfield), memory, new_value)
116 }
117 }
118
119 other => Err(DebugError::WarnAndContinue {
120 message: format!(
121 "Updating {} bitfield variables is not yet supported.",
122 other.kind()
123 ),
124 }),
125 },
126
127 other => Err(DebugError::WarnAndContinue {
128 message: format!("Updating {} variables is not yet supported.", other.kind()),
129 }),
130 }
131 }
132
133 fn format_array_type(&self, item_type: &str, length: usize) -> String {
134 format!("{item_type}[{length}]")
135 }
136
137 fn format_enum_value(&self, _type_name: &VariableType, value: &VariableName) -> VariableValue {
138 VariableValue::Valid(value.to_string())
139 }
140
141 fn format_pointer_type(&self, pointee: Option<&str>) -> String {
142 format!("{}*", pointee.unwrap_or("void"))
143 }
144
145 fn process_tag_with_no_type(&self, variable: &Variable, tag: gimli::DwTag) -> VariableValue {
146 match tag {
147 gimli::DW_TAG_const_type => VariableValue::Valid("const void".to_string()),
148 gimli::DW_TAG_pointer_type => {
149 let name = if let VariableLocation::Address(addr) = variable.memory_location {
150 format!("void* @ {addr:X}")
151 } else {
152 "void*".to_string()
153 };
154
155 VariableValue::Valid(name)
156 }
157 _ => VariableValue::Error(format!("Error: Failed to decode {tag} type reference")),
158 }
159 }
160}
161
162struct CChar(u8);
163
164impl Display for CChar {
165 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
166 let c = self.0;
167 if c.is_ascii() {
168 f.write_char(c as char)
169 } else {
170 f.write_fmt(format_args!("\\x{c:02x}"))
171 }
172 }
173}
174
175impl Value for CChar {
176 fn get_value(
177 variable: &Variable,
178 memory: &mut dyn MemoryInterface,
179 _variable_cache: &VariableCache,
180 ) -> Result<Self, DebugError>
181 where
182 Self: Sized,
183 {
184 let buff = u8::get_value(variable, memory, _variable_cache)?;
185
186 Ok(Self(buff))
187 }
188
189 fn update_value(
190 variable: &Variable,
191 memory: &mut dyn MemoryInterface,
192 new_value: &str,
193 ) -> Result<(), DebugError> {
194 fn input_error(value: &str) -> DebugError {
195 DebugError::WarnAndContinue {
196 message: format!(
197 "Invalid value for char: {value}. Please provide a single character."
198 ),
199 }
200 }
201
202 let new_value = if new_value.len() == 1 && new_value.is_ascii() {
205 new_value.as_bytes()[0]
206 } else if new_value.starts_with("\\x") && [3, 4].contains(&new_value.len()) {
207 u8::from_str_radix(&new_value[2..], 16).map_err(|_| input_error(new_value))?
208 } else {
209 return Err(input_error(new_value));
210 };
211
212 memory.write_word_8(variable.memory_location.memory_address()?, new_value)?;
213
214 Ok(())
215 }
216}
217
218struct UnsignedInt(u128);
219
220impl Display for UnsignedInt {
221 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
222 f.write_fmt(format_args!("{}", self.0))
223 }
224}
225
226impl UnsignedInt {
227 fn get_value(
228 variable: &Variable,
229 bitfield: Option<Bitfield>,
230 memory: &mut dyn MemoryInterface,
231 _variable_cache: &VariableCache,
232 ) -> Result<Self, DebugError>
233 where
234 Self: Sized,
235 {
236 let mut buff = [0u8; 16];
238 let bytes = variable.byte_size.unwrap_or(1).min(16) as usize;
239 if let VariableLocation::RegisterValue(value) = variable.memory_location {
240 let reg_bytes = TryInto::<u128>::try_into(value)?.to_le_bytes();
242
243 buff[..bytes].copy_from_slice(®_bytes[..bytes]);
244 } else {
245 memory.read(
247 variable.memory_location.memory_address()?,
248 &mut buff[..bytes],
249 )?;
250 }
251
252 let value = u128::from_le_bytes(buff);
253
254 let value = match bitfield {
256 Some(bitfield) => bitfield.extract(value),
257 None => value,
258 };
259
260 Ok(Self(value))
261 }
262
263 fn update_value(
264 variable: &Variable,
265 bitfield: Option<Bitfield>,
266 memory: &mut dyn MemoryInterface,
267 new_value: &str,
268 ) -> Result<(), DebugError> {
269 match parse_int::parse::<u128>(new_value) {
270 Ok(value) => write_unsigned_bytes(variable, bitfield, memory, value),
271 Err(e) => Err(DebugError::WarnAndContinue {
272 message: format!("Invalid data conversion from value: {new_value:?}. {e:?}"),
273 }),
274 }
275 }
276}
277
278fn write_unsigned_bytes(
279 variable: &Variable,
280 bitfield: Option<Bitfield>,
281 memory: &mut dyn MemoryInterface,
282 unsigned: u128,
283) -> Result<(), DebugError> {
284 let bytes = variable.byte_size.unwrap_or(1) as usize;
286
287 let Some(bitfield) = bitfield else {
289 let buff = unsigned.to_le_bytes();
290 memory.write_8(variable.memory_location.memory_address()?, &buff[..bytes])?;
291 return Ok(());
292 };
293
294 let mut buff = [0u8; 16];
298 memory.read(
299 variable.memory_location.memory_address()?,
300 &mut buff[..bytes],
301 )?;
302 let read_value = u128::from_le_bytes(buff);
303
304 let new_value = bitfield.insert(read_value, unsigned);
305
306 let buff = new_value.to_le_bytes();
308 memory.write_8(variable.memory_location.memory_address()?, &buff[..bytes])?;
309
310 Ok(())
311}
312
313struct SignedInt(i128);
314
315impl Display for SignedInt {
316 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
317 f.write_fmt(format_args!("{}", self.0))
318 }
319}
320
321impl SignedInt {
322 fn get_value(
323 variable: &Variable,
324 bitfield: Option<Bitfield>,
325 memory: &mut dyn MemoryInterface,
326 variable_cache: &VariableCache,
327 ) -> Result<Self, DebugError>
328 where
329 Self: Sized,
330 {
331 let unsigned = UnsignedInt::get_value(variable, bitfield, memory, variable_cache)?.0;
333 let bytes = variable.byte_size.unwrap_or(1).min(16) as usize;
334
335 let sign_bit_shift = match bitfield {
337 Some(bitfield) => bitfield.length() as usize - 1,
338 None => (bytes * 8) - 1,
339 };
340
341 let negative = unsigned & (1 << sign_bit_shift) != 0;
342 let value = if negative {
343 (unsigned | (!0 << sign_bit_shift)) as i128
344 } else {
345 unsigned as i128
346 };
347
348 Ok(Self(value))
349 }
350
351 fn update_value(
352 variable: &Variable,
353 bitfield: Option<Bitfield>,
354 memory: &mut dyn MemoryInterface,
355 new_value: &str,
356 ) -> Result<(), DebugError> {
357 match parse_int::parse::<i128>(new_value) {
358 Ok(value) => write_unsigned_bytes(variable, bitfield, memory, value as u128),
359 Err(e) => Err(DebugError::WarnAndContinue {
360 message: format!("Invalid data conversion from value: {new_value:?}. {e:?}"),
361 }),
362 }
363 }
364}
365
366impl From<Result<UnsignedInt, DebugError>> for VariableValue {
367 fn from(val: Result<UnsignedInt, DebugError>) -> Self {
368 val.map_or_else(
369 |err| VariableValue::Error(format!("{err:?}")),
370 |value| VariableValue::Valid(value.to_string()),
371 )
372 }
373}
374
375impl From<Result<SignedInt, DebugError>> for VariableValue {
376 fn from(val: Result<SignedInt, DebugError>) -> Self {
377 val.map_or_else(
378 |err| VariableValue::Error(format!("{err:?}")),
379 |value| VariableValue::Valid(value.to_string()),
380 )
381 }
382}