1use std::{
2 cell::RefCell,
3 fmt::{Display, LowerHex},
4 ops::{Add, AddAssign, Sub, SubAssign},
5 rc::{Rc, Weak},
6};
7
8use bytemuck::{Pod, Zeroable};
9use gimli::{
10 DW_AT_byte_size, DW_AT_data_bit_offset, DW_AT_data_member_location, DW_AT_defaulted,
11 DW_AT_encoding, DW_AT_type, DW_AT_upper_bound, DW_AT_virtuality, DW_ATE_UTF, DW_ATE_boolean,
12 DW_ATE_float, DW_ATE_signed, DW_ATE_signed_char, DW_ATE_unsigned, DW_ATE_unsigned_char,
13 DW_DEFAULTED_in_class, DW_TAG_array_type, DW_TAG_base_type, DW_TAG_class_type,
14 DW_TAG_const_type, DW_TAG_enumeration_type, DW_TAG_formal_parameter, DW_TAG_inheritance,
15 DW_TAG_member, DW_TAG_pointer_type, DW_TAG_ptr_to_member_type, DW_TAG_reference_type,
16 DW_TAG_rvalue_reference_type, DW_TAG_structure_type, DW_TAG_subprogram, DW_TAG_subrange_type,
17 DW_TAG_subroutine_type, DW_TAG_typedef, DW_TAG_union_type, DW_TAG_volatile_type,
18 DW_VIRTUALITY_none, DwAte, DwTag,
19};
20use typed_builder::TypedBuilder;
21
22use super::bit::to_byte_vec;
23
24use super::register_info::RegisterId;
25use super::{registers::Registers, target::Target};
26
27use super::{bit::from_bytes, registers::F80};
28
29use super::bit::memcpy_bits;
30
31use super::dwarf::BitfieldInformation;
32
33use super::process::Process;
34
35use super::sdb_error::SdbError;
36
37use super::dwarf::Die;
38
39use super::elf::ElfCollection;
40
41use super::elf::Elf;
42
43pub type Byte64 = [u8; 8];
44pub type Byte128 = [u8; 16];
45
46#[macro_export]
47macro_rules! strip {
48 ($value:expr, $( $tag:expr ),+ $(,)?) => {{
49 use gimli::DW_AT_type;
50 let mut ret = $value.clone();
51 let mut tag = ret.get_die()?.abbrev_entry().tag as u16;
52 while false $(|| tag == $tag.0)+ {
53 ret = SdbType::new(ret.get_die()?.index(DW_AT_type.0 as u64)?.as_type().get_die()?);
54 tag = ret.get_die()?.abbrev_entry().tag as u16;
55 }
56 Ok(ret)
57 }};
58}
59
60#[repr(transparent)]
61#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default)]
62pub struct VirtualAddress {
63 addr: u64,
64}
65
66unsafe impl Pod for VirtualAddress {}
67
68unsafe impl Zeroable for VirtualAddress {}
69
70#[derive(Default, Debug)]
71pub struct FileOffset {
72 addr: u64,
73 elf: Weak<Elf>,
74}
75
76impl FileOffset {
77 pub fn new(elf: &Rc<Elf>, addr: u64) -> Self {
78 Self {
79 addr,
80 elf: Rc::downgrade(elf),
81 }
82 }
83
84 pub fn off(&self) -> u64 {
85 self.addr
86 }
87
88 pub fn elf_file(&self) -> Rc<Elf> {
89 self.elf.upgrade().unwrap()
90 }
91}
92
93#[derive(Default, Debug, Clone)]
94pub struct FileAddress {
95 addr: u64,
96 elf: Weak<Elf>,
97}
98
99impl FileAddress {
100 pub fn new(elf: &Rc<Elf>, addr: u64) -> Self {
101 Self {
102 addr,
103 elf: Rc::downgrade(elf),
104 }
105 }
106
107 pub fn null() -> Self {
108 FileAddress::default()
109 }
110
111 pub fn addr(&self) -> u64 {
112 self.addr
113 }
114
115 pub fn rc_elf_file(&self) -> Rc<Elf> {
116 self.elf.upgrade().unwrap()
117 }
118
119 pub fn weak_elf_file(&self) -> Weak<Elf> {
120 self.elf.clone()
121 }
122
123 pub fn has_elf(&self) -> bool {
124 self.elf.upgrade().is_some()
125 }
126
127 pub fn to_virt_addr(&self) -> VirtualAddress {
128 let elf = self.elf.upgrade();
129 assert!(elf.is_some());
130 let elf = elf.unwrap();
131 let section = elf.get_section_containing_file_addr(self);
132
133 return match section {
134 Some(_) => VirtualAddress {
135 addr: self.addr + elf.load_bias().addr,
136 },
137 None => VirtualAddress::default(),
138 };
139 }
140}
141
142impl PartialEq for FileAddress {
143 fn eq(&self, other: &Self) -> bool {
144 self.addr == other.addr && self.elf.ptr_eq(&other.elf)
145 }
146}
147
148impl Eq for FileAddress {}
149
150impl PartialOrd for FileAddress {
151 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
152 Some(self.cmp(other))
153 }
154}
155
156impl Ord for FileAddress {
157 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
158 assert!(self.elf.ptr_eq(&other.elf));
159 self.addr.cmp(&other.addr)
160 }
161}
162
163impl Add<i64> for FileAddress {
164 type Output = FileAddress;
165
166 fn add(self, rhs: i64) -> Self::Output {
167 Self {
168 addr: (self.addr as i128 + rhs as i128) as u64,
169 elf: self.elf,
170 }
171 }
172}
173
174impl AddAssign<i64> for FileAddress {
175 fn add_assign(&mut self, rhs: i64) {
176 self.addr = (self.addr as i128 + rhs as i128) as u64;
177 }
178}
179
180impl Sub<i64> for FileAddress {
181 type Output = FileAddress;
182
183 fn sub(self, rhs: i64) -> Self::Output {
184 Self {
185 addr: (self.addr as i128 - rhs as i128) as u64,
186 elf: self.elf,
187 }
188 }
189}
190
191impl SubAssign<i64> for FileAddress {
192 fn sub_assign(&mut self, rhs: i64) {
193 self.addr = (self.addr as i128 - rhs as i128) as u64;
194 }
195}
196
197impl VirtualAddress {
198 pub fn new(addr: u64) -> Self {
199 Self { addr }
200 }
201
202 pub fn to_file_addr_elf(self, elf: &Rc<Elf>) -> FileAddress {
203 let obj = elf;
204 let section = obj.get_section_containing_virt_addr(self);
205 return match section {
206 Some(_) => FileAddress {
207 addr: self.addr - obj.load_bias().addr,
208 elf: Rc::downgrade(elf),
209 },
210 None => FileAddress::default(),
211 };
212 }
213
214 pub fn to_file_addr_elves(self, elves: &ElfCollection) -> FileAddress {
215 let obj = elves.get_elf_containing_address(self);
216 if obj.upgrade().is_none() {
217 return FileAddress::default();
218 }
219 return self.to_file_addr_elf(&obj.upgrade().unwrap());
220 }
221}
222
223impl LowerHex for VirtualAddress {
224 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
225 LowerHex::fmt(&self.addr, f)
226 }
227}
228
229impl From<u64> for VirtualAddress {
230 fn from(value: u64) -> Self {
231 Self { addr: value }
232 }
233}
234
235impl VirtualAddress {
236 pub fn addr(&self) -> u64 {
237 self.addr
238 }
239}
240
241impl Add<i64> for VirtualAddress {
242 type Output = VirtualAddress;
243
244 fn add(self, rhs: i64) -> Self::Output {
245 Self {
246 addr: (self.addr as i128 + rhs as i128) as u64,
247 }
248 }
249}
250
251impl AddAssign<i64> for VirtualAddress {
252 fn add_assign(&mut self, rhs: i64) {
253 self.addr = (self.addr as i128 + rhs as i128) as u64;
254 }
255}
256
257impl Sub<i64> for VirtualAddress {
258 type Output = VirtualAddress;
259
260 fn sub(self, rhs: i64) -> Self::Output {
261 Self {
262 addr: (self.addr as i128 - rhs as i128) as u64,
263 }
264 }
265}
266
267impl SubAssign<i64> for VirtualAddress {
268 fn sub_assign(&mut self, rhs: i64) {
269 self.addr = (self.addr as i128 - rhs as i128) as u64;
270 }
271}
272
273#[derive(Debug, Clone, Copy)]
274pub enum StoppointMode {
275 Write,
276 ReadWrite,
277 Execute,
278}
279
280impl Display for StoppointMode {
281 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
282 match &self {
283 StoppointMode::Write => write!(f, "write"),
284 StoppointMode::ReadWrite => write!(f, "read_write"),
285 StoppointMode::Execute => write!(f, "execute"),
286 }
287 }
288}
289
290#[derive(Debug, Clone)]
291pub struct SdbType {
292 byte_size: RefCell<Option<usize>>,
293 info: SdbTypeInfo,
294}
295
296#[derive(Debug, Clone)]
297pub enum SdbTypeInfo {
298 Die(Rc<Die>),
299 BuiltinType(BuiltinType),
300}
301
302impl PartialEq for SdbType {
303 fn eq(&self, other: &Self) -> bool {
304 self.try_eq(other).unwrap_or(false)
305 }
306}
307
308impl Eq for SdbType {}
309
310impl SdbType {
311 pub fn try_eq(&self, rhs: &Self) -> Result<bool, SdbError> {
312 if !self.is_from_dwarf() && !rhs.is_from_dwarf() {
313 return Ok(self.get_builtin_type()? == rhs.get_builtin_type()?);
314 }
315 let from_dwarf: Option<&SdbType>;
316 let builtin: Option<&SdbType>;
317 if !self.is_from_dwarf() {
318 from_dwarf = Some(rhs);
319 builtin = Some(self);
320 } else if !rhs.is_from_dwarf() {
321 from_dwarf = Some(self);
322 builtin = Some(rhs);
323 } else {
324 from_dwarf = None;
325 builtin = None;
326 }
327 if let (Some(from_dwarf), Some(builtin)) = (from_dwarf, builtin) {
328 let die = from_dwarf.strip_cvref_typedef()?.get_die()?;
329 let tag = die.abbrev_entry().tag as u16;
330 if tag == DW_TAG_base_type.0 {
331 let encoding = die.index(DW_AT_encoding.0 as u64)?.as_int()?;
332 #[allow(non_upper_case_globals)]
333 match DwAte(encoding as u8) {
334 DW_ATE_boolean => {
335 return Ok(builtin.get_builtin_type()? == BuiltinType::Boolean);
336 }
337 DW_ATE_float => {
338 return Ok(builtin.get_builtin_type()? == BuiltinType::FloatingPoint);
339 }
340 DW_ATE_signed | DW_ATE_unsigned => {
341 return Ok(builtin.get_builtin_type()? == BuiltinType::Integer);
342 }
343 DW_ATE_signed_char | DW_ATE_unsigned_char => {
344 return Ok(builtin.get_builtin_type()? == BuiltinType::Character);
345 }
346 _ => {
347 return Ok(false);
348 }
349 }
350 }
351 if tag == DW_TAG_pointer_type.0 {
352 let type_die = die.index(DW_AT_type.0 as u64)?.as_type();
353 return Ok(
354 type_die.is_char_type()? && builtin.get_builtin_type()? == BuiltinType::String
355 );
356 }
357 return Ok(false);
358 }
359 let lhs_stripped = self.strip_all()?;
360 let rhs_stripped = rhs.strip_all()?;
361
362 let lhs_name = lhs_stripped.get_die()?.name()?;
363 let rhs_name = rhs_stripped.get_die()?.name()?;
364 if let (Some(lhs_name), Some(rhs_name)) = (lhs_name, rhs_name)
365 && lhs_name == rhs_name
366 {
367 return Ok(true);
368 }
369 Ok(false)
370 }
371
372 pub fn is_class_type(&self) -> Result<bool, SdbError> {
373 if !self.is_from_dwarf() {
374 return Ok(false);
375 }
376 let stripped = self.strip_cv_typedef()?.get_die()?;
377 let tag = stripped.abbrev_entry().tag as u16;
378 return Ok(tag == DW_TAG_class_type.0
379 || tag == DW_TAG_structure_type.0
380 || tag == DW_TAG_union_type.0);
381 }
382
383 pub fn is_reference_type(&self) -> Result<bool, SdbError> {
384 if !self.is_from_dwarf() {
385 return Ok(false);
386 }
387 let stripped = self.strip_cv_typedef()?.get_die()?;
388 let tag = stripped.abbrev_entry().tag as u16;
389 return Ok(tag == DW_TAG_reference_type.0 || tag == DW_TAG_rvalue_reference_type.0);
390 }
391
392 pub fn alignment(&self) -> Result<usize, SdbError> {
393 if !self.is_from_dwarf() {
394 return self.byte_size();
395 }
396 if self.is_class_type()? {
397 let mut max_alignment = 0;
398 for child in self.get_die()?.children() {
399 if child.abbrev_entry().tag as u16 == DW_TAG_member.0
400 && child.contains(DW_AT_data_member_location.0 as u64)
401 || child.contains(DW_AT_data_bit_offset.0 as u64)
402 {
403 let member_type = child.index(DW_AT_type.0 as u64)?.as_type();
404 let member_alignment = member_type.alignment()?;
405 if member_alignment > max_alignment {
406 max_alignment = member_alignment;
407 }
408 }
409 }
410 return Ok(max_alignment);
411 }
412 if self.get_die()?.abbrev_entry().tag as u16 == DW_TAG_array_type.0 {
413 return self
414 .get_die()?
415 .index(DW_AT_type.0 as u64)?
416 .as_type()
417 .alignment();
418 }
419 self.byte_size()
420 }
421
422 pub fn has_unaligned_fields(&self) -> Result<bool, SdbError> {
423 if !self.is_from_dwarf() {
424 return Ok(false);
425 }
426 if self.is_class_type()? {
427 for child in self.get_die()?.children() {
428 if child.abbrev_entry().tag as u16 == DW_TAG_member.0
429 && child.contains(DW_AT_data_member_location.0 as u64)
430 {
431 let member_type = child.index(DW_AT_type.0 as u64)?.as_type();
432 let location =
433 child.index(DW_AT_data_member_location.0 as u64)?.as_int()? as usize;
434 if location % member_type.alignment()? != 0 {
435 return Ok(true);
436 }
437 if member_type.has_unaligned_fields()? {
438 return Ok(true);
439 }
440 }
441 }
442 }
443 Ok(false)
444 }
445
446 pub fn is_non_trivial_for_calls(&self) -> Result<bool, SdbError> {
447 let stripped = self.strip_cv_typedef()?.get_die()?;
448 let tag = stripped.abbrev_entry().tag as u16;
449
450 if tag == DW_TAG_class_type.0
451 || tag == DW_TAG_structure_type.0
452 || tag == DW_TAG_union_type.0
453 {
454 for child in stripped.children() {
455 if (child.abbrev_entry().tag as u16 == DW_TAG_member.0
456 && child.contains(DW_AT_data_member_location.0 as u64)
457 || child.contains(DW_AT_data_bit_offset.0 as u64))
458 && child
459 .index(DW_AT_type.0 as u64)?
460 .as_type()
461 .is_non_trivial_for_calls()?
462 {
463 return Ok(true);
464 }
465 if (child.abbrev_entry().tag as u16 == DW_TAG_inheritance.0)
466 && child
467 .index(DW_AT_type.0 as u64)?
468 .as_type()
469 .is_non_trivial_for_calls()?
470 {
471 return Ok(true);
472 }
473 if child.contains(DW_AT_virtuality.0 as u64)
474 && child.index(DW_AT_virtuality.0 as u64)?.as_int()?
475 != DW_VIRTUALITY_none.0 as u64
476 {
477 return Ok(true);
478 }
479 if child.abbrev_entry().tag as u16 == DW_TAG_subprogram.0 {
480 if is_copy_or_move_constructor(self, &child)? {
481 if !child.contains(DW_AT_defaulted.0 as u64)
482 || child.index(DW_AT_defaulted.0 as u64)?.as_int()?
483 != DW_DEFAULTED_in_class.0 as u64
484 {
485 return Ok(true);
486 }
487 } else if is_destructor(&child)?
488 && (!child.contains(DW_AT_defaulted.0 as u64)
489 || child.index(DW_AT_defaulted.0 as u64)?.as_int()?
490 != DW_DEFAULTED_in_class.0 as u64)
491 {
492 return Ok(true);
493 }
494 }
495 }
496 }
497 if tag == DW_TAG_array_type.0 {
498 return stripped
499 .index(DW_AT_type.0 as u64)?
500 .as_type()
501 .is_non_trivial_for_calls();
502 }
503 Ok(false)
504 }
505
506 pub fn get_parameter_classes(&self) -> Result<[ParameterClass; 2], SdbError> {
507 let mut classes = [ParameterClass::NoClass, ParameterClass::NoClass];
508
509 if !self.is_from_dwarf() {
510 match self.get_builtin_type()? {
511 BuiltinType::Boolean => classes[0] = ParameterClass::Integer,
512 BuiltinType::Character => classes[0] = ParameterClass::Integer,
513 BuiltinType::Integer => classes[0] = ParameterClass::Integer,
514 BuiltinType::FloatingPoint => classes[0] = ParameterClass::Sse,
515 BuiltinType::String => classes[0] = ParameterClass::Integer,
516 }
517 return Ok(classes);
518 }
519
520 let stripped = self.strip_cv_typedef()?;
521 let die = stripped.get_die()?;
522 let tag = die.abbrev_entry().tag as u16;
523
524 if tag == DW_TAG_base_type.0 && stripped.byte_size()? <= 8 {
525 let encoding = die.index(DW_AT_encoding.0 as u64)?.as_int()? as u8;
526 #[allow(non_upper_case_globals)]
527 match DwAte(encoding) {
528 DW_ATE_boolean => classes[0] = ParameterClass::Integer,
529 DW_ATE_float => classes[0] = ParameterClass::Sse,
530 DW_ATE_signed => classes[0] = ParameterClass::Integer,
531 DW_ATE_signed_char => classes[0] = ParameterClass::Integer,
532 DW_ATE_unsigned => classes[0] = ParameterClass::Integer,
533 DW_ATE_unsigned_char => classes[0] = ParameterClass::Integer,
534 _ => return SdbError::err("Unimplemented base type encoding"),
535 }
536 } else if tag == DW_TAG_pointer_type.0
537 || tag == DW_TAG_reference_type.0
538 || tag == DW_TAG_rvalue_reference_type.0
539 {
540 classes[0] = ParameterClass::Integer;
541 } else if tag == DW_TAG_base_type.0
542 && die.index(DW_AT_encoding.0 as u64)?.as_int()? as u8 == DW_ATE_float.0
543 && stripped.byte_size()? == 16
544 {
545 classes[0] = ParameterClass::X87;
546 classes[1] = ParameterClass::X87up;
547 } else if tag == DW_TAG_class_type.0
548 || tag == DW_TAG_structure_type.0
549 || tag == DW_TAG_union_type.0
550 || tag == DW_TAG_array_type.0
551 {
552 classes = classify_class_type(self)?;
553 }
554 Ok(classes)
555 }
556
557 pub fn new(die: Rc<Die>) -> Self {
558 Self {
559 byte_size: RefCell::new(None),
560 info: SdbTypeInfo::Die(die),
561 }
562 }
563
564 pub fn new_from_info(info: SdbTypeInfo) -> Self {
565 Self {
566 byte_size: RefCell::new(None),
567 info,
568 }
569 }
570
571 pub fn new_builtin(builtin_type: BuiltinType) -> Self {
572 Self {
573 byte_size: RefCell::new(None),
574 info: SdbTypeInfo::BuiltinType(builtin_type),
575 }
576 }
577
578 pub fn get_die(&self) -> Result<Rc<Die>, SdbError> {
579 match &self.info {
580 SdbTypeInfo::Die(die) => Ok(die.clone()),
581 _ => SdbError::err("Type is not from DWARF info"),
582 }
583 }
584
585 pub fn byte_size(&self) -> Result<usize, SdbError> {
586 if self.byte_size.borrow().is_none() {
587 self.byte_size
588 .borrow_mut()
589 .replace(self.compute_byte_size()?);
590 }
591 return Ok(self.byte_size.borrow().unwrap());
592 }
593
594 pub fn is_char_type(&self) -> Result<bool, SdbError> {
595 let stripped = self.strip_cv_typedef()?.get_die()?;
596 if !stripped.contains(DW_AT_encoding.0 as u64) {
597 return Ok(false);
598 }
599 let encoding = stripped.index(DW_AT_encoding.0 as u64)?.as_int()? as u8;
600 return Ok(stripped.abbrev_entry().tag as u16 == DW_TAG_base_type.0
601 && encoding == DW_ATE_signed_char.0
602 || encoding == DW_ATE_unsigned_char.0);
603 }
604
605 fn compute_byte_size(&self) -> Result<usize, SdbError> {
606 if !self.is_from_dwarf() {
607 return Ok(match self.get_builtin_type()? {
608 BuiltinType::Boolean => 1,
609 BuiltinType::Character => 1,
610 BuiltinType::Integer => 8,
611 BuiltinType::FloatingPoint => 8,
612 BuiltinType::String => 8,
613 });
614 }
615 let die = self.get_die()?;
616 let tag = die.abbrev_entry().tag;
617
618 if tag as u16 == DW_TAG_pointer_type.0 {
619 return Ok(8);
620 }
621 if tag as u16 == DW_TAG_ptr_to_member_type.0 {
622 let member_type = die.index(DW_AT_type.0 as u64)?.as_type();
623 if member_type.get_die()?.abbrev_entry().tag as u16 == DW_TAG_subroutine_type.0 {
624 return Ok(16);
625 }
626 return Ok(8);
627 }
628 if tag as u16 == DW_TAG_array_type.0 {
629 let mut value_size = die.index(DW_AT_type.0 as u64)?.as_type().byte_size()?;
630 for child in die.children() {
631 if child.abbrev_entry().tag as u16 == DW_TAG_subrange_type.0 {
632 value_size *= (child.index(DW_AT_upper_bound.0 as u64)?.as_int()? + 1) as usize;
633 }
634 }
635 return Ok(value_size);
636 }
637 if die.contains(DW_AT_byte_size.0 as u64) {
638 return Ok(die.index(DW_AT_byte_size.0 as u64)?.as_int()? as usize);
639 }
640 if die.contains(DW_AT_type.0 as u64) {
641 return die.index(DW_AT_type.0 as u64)?.as_type().byte_size();
642 }
643
644 return Ok(0);
645 }
646
647 pub fn strip_cv_typedef(&self) -> Result<Self, SdbError> {
648 strip!(
649 self,
650 DW_TAG_const_type,
651 DW_TAG_volatile_type,
652 DW_TAG_typedef
653 )
654 }
655
656 pub fn strip_cvref_typedef(&self) -> Result<Self, SdbError> {
657 strip!(
658 self,
659 DW_TAG_const_type,
660 DW_TAG_volatile_type,
661 DW_TAG_typedef,
662 DW_TAG_reference_type,
663 DW_TAG_rvalue_reference_type
664 )
665 }
666
667 pub fn strip_all(&self) -> Result<Self, SdbError> {
668 strip!(
669 self,
670 DW_TAG_const_type,
671 DW_TAG_volatile_type,
672 DW_TAG_typedef,
673 DW_TAG_reference_type,
674 DW_TAG_rvalue_reference_type,
675 DW_TAG_pointer_type
676 )
677 }
678
679 pub fn get_builtin_type(&self) -> Result<BuiltinType, SdbError> {
680 match &self.info {
681 SdbTypeInfo::BuiltinType(builtin_type) => Ok(*builtin_type),
682 _ => SdbError::err("Type is not a builtin type"),
683 }
684 }
685
686 pub fn is_from_dwarf(&self) -> bool {
687 matches!(&self.info, SdbTypeInfo::Die(_))
688 }
689}
690
691#[derive(Debug, Clone, TypedBuilder)]
692pub struct TypedData {
693 pub data: Vec<u8>,
694 pub type_: SdbType,
695 #[builder(default)]
696 pub address: Option<VirtualAddress>,
697}
698
699impl TypedData {
700 pub fn data(&self) -> &Vec<u8> {
701 &self.data
702 }
703
704 pub fn data_ptr(&self) -> &[u8] {
705 self.data.as_slice()
706 }
707
708 pub fn value_type(&self) -> &SdbType {
709 &self.type_
710 }
711
712 pub fn address(&self) -> Option<VirtualAddress> {
713 self.address
714 }
715
716 pub fn fixup_bitfield(&self, _proc: &Process, member_die: &Die) -> Result<Self, SdbError> {
717 let stripped = self.type_.strip_cv_typedef()?;
718 let bitfield_info = member_die.get_bitfield_information(stripped.byte_size()? as u64)?;
719 if let Some(bitfield_info) = bitfield_info {
720 let BitfieldInformation {
721 bit_size,
722 storage_byte_size,
723 bit_offset,
724 } = bitfield_info;
725 let mut fixed_data = vec![0u8; storage_byte_size as usize];
726 let dest = fixed_data.as_mut_slice();
727 let src = self.data().as_slice();
728 memcpy_bits(dest, 0, src, bit_offset as u32, bit_size as u32);
729 return Ok(TypedData::builder()
730 .data(fixed_data)
731 .type_(self.type_.clone())
732 .build());
733 }
734 Ok(self.clone())
735 }
736
737 pub fn deref_pointer(&self, proc: &Process) -> Result<TypedData, SdbError> {
738 let stripped_type_die = self.type_.strip_cv_typedef()?.get_die()?;
739 let tag = stripped_type_die.abbrev_entry().tag;
740 if tag as u16 != DW_TAG_pointer_type.0 {
741 return SdbError::err("Not a pointer type");
742 }
743 let address = VirtualAddress::new(from_bytes::<u64>(&self.data));
744 let value_type = stripped_type_die.index(DW_AT_type.0 as u64)?.as_type();
745 let data_vec = proc.read_memory(address, value_type.byte_size()?)?;
746 Ok(TypedData::builder()
747 .data(data_vec)
748 .type_(value_type)
749 .address(Some(address))
750 .build())
751 }
752
753 pub fn read_member(&self, proc: &Process, member_name: &str) -> Result<TypedData, SdbError> {
754 let die = self.type_.get_die()?;
755 let mut children = die.children();
756 let it = children.find(|child| {
757 child
758 .name()
759 .map(|v| v.unwrap_or_default())
760 .unwrap_or_default()
761 == member_name
762 });
763 if it.is_none() {
764 return SdbError::err("No such member");
765 }
766 let var = it.unwrap();
767 let value_type = var.index(DW_AT_type.0 as u64)?.as_type();
768 let byte_offset = if var.contains(DW_AT_data_member_location.0 as u64) {
769 var.index(DW_AT_data_member_location.0 as u64)?.as_int()? as usize
770 } else {
771 var.index(DW_AT_data_bit_offset.0 as u64)?.as_int()? as usize / 8
772 };
773 let data_start = &self.data.as_slice()[byte_offset..];
774 let member_data = &data_start[..value_type.byte_size()?];
775 let data = if self.address.is_some() {
776 TypedData::builder()
777 .data(member_data.to_vec())
778 .type_(value_type.clone())
779 .address(Some(self.address.unwrap() + byte_offset as i64))
780 .build()
781 } else {
782 TypedData::builder()
783 .data(member_data.to_vec())
784 .type_(value_type)
785 .build()
786 };
787 return data.fixup_bitfield(proc, &var);
788 }
789
790 pub fn index(&self, _proc: &Process, index: usize) -> Result<TypedData, SdbError> {
791 let parent_type = self.type_.strip_cv_typedef()?.get_die()?;
792 let tag = parent_type.abbrev_entry().tag;
793 if tag as u16 != DW_TAG_array_type.0 && tag as u16 != DW_TAG_pointer_type.0 {
794 return SdbError::err("Not an array or pointer type");
795 }
796 let value_type = parent_type.index(DW_AT_type.0 as u64)?.as_type();
797 let element_size = value_type.byte_size()?;
798 let offset = index * element_size;
799 if tag as u16 == DW_TAG_pointer_type.0 {
800 let address = VirtualAddress::new(from_bytes::<u64>(&self.data)) + offset as i64;
801 let data_vec = _proc.read_memory(address, element_size)?;
802 return Ok(TypedData::builder()
803 .data(data_vec)
804 .type_(value_type)
805 .address(Some(address))
806 .build());
807 } else {
808 let data_vec = self.data[offset..offset + element_size].to_vec();
809 if let Some(address) = self.address {
810 return Ok(TypedData::builder()
811 .data(data_vec)
812 .type_(value_type)
813 .address(Some(address + offset as i64))
814 .build());
815 }
816 return Ok(TypedData::builder()
817 .data(data_vec)
818 .type_(value_type)
819 .build());
820 }
821 }
822
823 pub fn visualize(&self, proc: &Process, depth: i32 ) -> Result<String, SdbError> {
824 let die = self.type_.get_die()?;
825 #[allow(non_upper_case_globals)]
826 match DwTag(die.abbrev_entry().tag as u16) {
827 DW_TAG_base_type => Ok(visualize_base_type(self)?),
828 DW_TAG_pointer_type => Ok(visualize_pointer_type(proc, self)?),
829 DW_TAG_ptr_to_member_type => Ok(visualize_member_pointer_type(self)?),
830 DW_TAG_array_type => Ok(visualize_array_type(proc, self)?),
831 DW_TAG_class_type | DW_TAG_structure_type | DW_TAG_union_type => {
832 Ok(visualize_class_type(proc, self, depth)?)
833 }
834 DW_TAG_enumeration_type | DW_TAG_typedef | DW_TAG_const_type | DW_TAG_volatile_type => {
835 Ok(TypedData::builder()
836 .data(self.data.clone())
837 .type_(die.index(DW_AT_type.0 as u64)?.as_type())
838 .build()
839 .visualize(proc, 0)?)
840 }
841 _ => SdbError::err("Unsupported type"),
842 }
843 }
844}
845
846fn visualize_base_type(data: &TypedData) -> Result<String, SdbError> {
847 let type_ = data.value_type();
848 let die = type_.get_die()?;
849 let ptr = data.data_ptr();
850 #[allow(non_upper_case_globals)]
851 match DwAte(die.index(DW_AT_encoding.0 as u64)?.as_int()? as u8) {
852 DW_ATE_boolean => Ok((ptr[0] != 0).to_string()),
853 DW_ATE_float => {
854 if die.name()?.unwrap() == "float" {
855 Ok((from_bytes::<f32>(ptr)).to_string())
856 } else if die.name()?.unwrap() == "double" {
857 Ok((from_bytes::<f64>(ptr)).to_string())
858 } else if die.name()?.unwrap() == "long double" {
859 Ok((from_bytes::<F80>(ptr)).to_string())
860 } else {
861 SdbError::err("Unsupported floating point type")
862 }
863 }
864 DW_ATE_signed => match type_.byte_size()? {
865 1 => Ok(from_bytes::<i8>(ptr).to_string()),
866 2 => Ok(from_bytes::<i16>(ptr).to_string()),
867 4 => Ok(from_bytes::<i32>(ptr).to_string()),
868 8 => Ok(from_bytes::<i64>(ptr).to_string()),
869 _ => SdbError::err("Unsupported signed integer size"),
870 },
871 DW_ATE_unsigned => match type_.byte_size()? {
872 1 => Ok(from_bytes::<u8>(ptr).to_string()),
873 2 => Ok(from_bytes::<u16>(ptr).to_string()),
874 4 => Ok(from_bytes::<u32>(ptr).to_string()),
875 8 => Ok(from_bytes::<u64>(ptr).to_string()),
876 _ => SdbError::err("Unsupported unsigned integer size"),
877 },
878 DW_ATE_signed_char => Ok(from_bytes::<i8>(ptr).to_string()),
879 DW_ATE_unsigned_char => Ok(from_bytes::<u8>(ptr).to_string()),
880 DW_ATE_UTF => SdbError::err("DW_ATE_UTF is not implemented"),
881 _ => SdbError::err("Unsupported encoding"),
882 }
883}
884
885fn visualize_pointer_type(proc: &Process, data: &TypedData) -> Result<String, SdbError> {
886 let ptr = from_bytes::<u64>(data.data_ptr());
887 if ptr == 0 {
888 return Ok("0x0".to_string());
889 }
890 if data
891 .value_type()
892 .get_die()?
893 .index(DW_AT_type.0 as u64)?
894 .as_type()
895 .is_char_type()?
896 {
897 return Ok(format!(
898 "\"{}\"",
899 proc.read_string(VirtualAddress::new(ptr))?
900 ));
901 }
902 Ok(format!("0x{ptr:x}"))
903}
904
905fn visualize_member_pointer_type(data: &TypedData) -> Result<String, SdbError> {
906 Ok(format!("0x{:x}", from_bytes::<usize>(data.data_ptr())))
907}
908
909fn visualize_array_type(proc: &Process, data: &TypedData) -> Result<String, SdbError> {
910 let mut dimensions = Vec::new();
911 for child in data.value_type().get_die()?.children() {
912 if child.abbrev_entry().tag as u16 == DW_TAG_subrange_type.0 {
913 dimensions.push(child.index(DW_AT_upper_bound.0 as u64)?.as_int()? as usize + 1);
914 }
915 }
916 dimensions.reverse();
917 let value_type = data
918 .value_type()
919 .get_die()?
920 .index(DW_AT_type.0 as u64)?
921 .as_type();
922 visualize_subrange(proc, &value_type, data.data(), dimensions)
923}
924
925fn visualize_subrange(
926 proc: &Process,
927 value_type: &SdbType,
928 data: &[u8],
929 mut dimensions: Vec<usize>,
930) -> Result<String, SdbError> {
931 if dimensions.is_empty() {
932 let data_vec = data.to_vec();
933 return TypedData::builder()
934 .data(data_vec)
935 .type_(value_type.clone())
936 .build()
937 .visualize(proc, 0);
938 }
939 let mut ret = "[".to_string();
940 let size = dimensions.pop().unwrap();
941 let sub_size = dimensions
942 .iter()
943 .fold(value_type.byte_size()?, |acc, dim| acc * dim);
944 for i in 0..size {
945 let subdata = &data[i * sub_size..];
946 ret.push_str(&visualize_subrange(
947 proc,
948 value_type,
949 subdata,
950 dimensions.clone(),
951 )?);
952 if i != size - 1 {
953 ret.push_str(", ");
954 }
955 }
956 Ok(ret + "]")
957}
958
959fn visualize_class_type(proc: &Process, data: &TypedData, depth: i32) -> Result<String, SdbError> {
960 let mut ret = "{\n".to_string();
961 for child in data.value_type().get_die()?.children() {
962 if child.abbrev_entry().tag as u16 == DW_TAG_member.0
963 && child.contains(DW_AT_data_member_location.0 as u64)
964 || child.contains(DW_AT_data_bit_offset.0 as u64)
965 {
966 let indent = "\t".repeat(depth as usize + 1);
967 let byte_offset = if child.contains(DW_AT_data_member_location.0 as u64) {
968 child.index(DW_AT_data_member_location.0 as u64)?.as_int()? as usize
969 } else {
970 child.index(DW_AT_data_bit_offset.0 as u64)?.as_int()? as usize / 8
971 };
972 let pos = &data.data_ptr()[byte_offset..];
973 let subtype = child.index(DW_AT_type.0 as u64)?.as_type();
974 let member_data = &pos[..subtype.byte_size()?];
975 let data = TypedData::builder()
976 .data(member_data.to_vec())
977 .type_(subtype)
978 .build()
979 .fixup_bitfield(proc, &child)?;
980 let member_str = data.visualize(proc, depth + 1)?;
981 let name = child.name()?.unwrap_or("<unnamed>".to_string());
982 ret.push_str(&format!("{indent}{name}: {member_str}\n"));
983 }
984 }
985 let indent = "\t".repeat(depth as usize);
986 ret.push_str(&format!("{indent}}}"));
987 Ok(ret)
988}
989
990#[derive(Debug, Clone, Copy, PartialEq)]
991pub enum BuiltinType {
992 String,
993 Character,
994 Integer,
995 Boolean,
996 FloatingPoint,
997}
998
999#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1000pub enum ParameterClass {
1001 Integer,
1002 Sse,
1003 Sseup,
1004 X87,
1005 X87up,
1006 ComplexX87,
1007 Memory,
1008 NoClass,
1009}
1010
1011fn classify_class_type(type_: &SdbType) -> Result<[ParameterClass; 2], SdbError> {
1012 if type_.is_non_trivial_for_calls()? {
1013 return SdbError::err("NTFPOC types are not supported");
1014 }
1015
1016 if type_.byte_size()? > 16 || type_.has_unaligned_fields()? {
1017 return Ok([ParameterClass::Memory, ParameterClass::Memory]);
1018 }
1019
1020 let mut classes = [ParameterClass::NoClass, ParameterClass::NoClass];
1021
1022 if type_.get_die()?.abbrev_entry().tag as u16 == DW_TAG_array_type.0 {
1023 let value_type = type_.get_die()?.index(DW_AT_type.0 as u64)?.as_type();
1024 classes = value_type.get_parameter_classes()?;
1025 if type_.byte_size()? > 8 && classes[1] == ParameterClass::NoClass {
1026 classes[1] = classes[0];
1027 }
1028 } else {
1029 for child in type_.get_die()?.children() {
1030 if child.abbrev_entry().tag as u16 == DW_TAG_member.0
1031 && child.contains(DW_AT_data_member_location.0 as u64)
1032 || child.contains(DW_AT_data_bit_offset.0 as u64)
1033 {
1034 classify_class_field(type_, &child, &mut classes, 0)?;
1035 }
1036 }
1037 }
1038
1039 if (classes[0] == ParameterClass::Memory || classes[1] == ParameterClass::Memory)
1040 || (classes[1] == ParameterClass::X87up && classes[0] != ParameterClass::X87)
1041 {
1042 classes[0] = ParameterClass::Memory;
1043 classes[1] = ParameterClass::Memory;
1044 }
1045
1046 Ok(classes)
1047}
1048
1049fn classify_class_field(
1050 type_: &SdbType,
1051 field: &Rc<Die>,
1052 classes: &mut [ParameterClass; 2],
1053 bit_offset: i32,
1054) -> Result<(), SdbError> {
1055 let bitfield_info = field.get_bitfield_information(type_.byte_size()? as u64)?;
1056 let field_type = field.index(DW_AT_type.0 as u64)?.as_type();
1057
1058 let current_bit_offset = if let Some(info) = &bitfield_info {
1059 info.bit_offset as i32 + bit_offset
1060 } else {
1061 field.index(DW_AT_data_member_location.0 as u64)?.as_int()? as i32 * 8 + bit_offset
1062 };
1063
1064 let eightbyte_index = (current_bit_offset / 64) as usize;
1065
1066 if field_type.is_class_type()? {
1067 for child in field_type.get_die()?.children() {
1068 if child.abbrev_entry().tag as u16 == DW_TAG_member.0
1069 && child.contains(DW_AT_data_member_location.0 as u64)
1070 || child.contains(DW_AT_data_bit_offset.0 as u64)
1071 {
1072 classify_class_field(type_, &child, classes, current_bit_offset)?;
1073 }
1074 }
1075 } else {
1076 let field_classes = field_type.get_parameter_classes()?;
1077 classes[eightbyte_index] =
1078 merge_parameter_classes(classes[eightbyte_index], field_classes[0]);
1079 if eightbyte_index == 0 {
1080 classes[1] = merge_parameter_classes(classes[1], field_classes[1]);
1081 }
1082 }
1083 Ok(())
1084}
1085
1086fn merge_parameter_classes(lhs: ParameterClass, rhs: ParameterClass) -> ParameterClass {
1087 if lhs == rhs {
1088 return lhs;
1089 }
1090 if lhs == ParameterClass::NoClass {
1091 return rhs;
1092 }
1093 if rhs == ParameterClass::NoClass {
1094 return lhs;
1095 }
1096 if lhs == ParameterClass::Memory || rhs == ParameterClass::Memory {
1097 return ParameterClass::Memory;
1098 }
1099 if lhs == ParameterClass::Integer || rhs == ParameterClass::Integer {
1100 return ParameterClass::Integer;
1101 }
1102 if lhs == ParameterClass::X87
1103 || rhs == ParameterClass::X87
1104 || lhs == ParameterClass::X87up
1105 || rhs == ParameterClass::X87up
1106 || lhs == ParameterClass::ComplexX87
1107 || rhs == ParameterClass::ComplexX87
1108 {
1109 return ParameterClass::Memory;
1110 }
1111 return ParameterClass::Sse;
1112}
1113
1114fn is_destructor(func: &Rc<Die>) -> Result<bool, SdbError> {
1115 let name = func.name()?;
1116 return Ok(name
1117 .map(|name| name.len() > 1 && name.chars().next().map(|c| c == '~').unwrap_or(false))
1118 .unwrap_or(false));
1119}
1120
1121fn is_copy_or_move_constructor(class_type: &SdbType, func: &Rc<Die>) -> Result<bool, SdbError> {
1122 let class_name = class_type.get_die()?.name()?;
1123 let func_name = func.name()?;
1124
1125 if class_name != func_name {
1126 return Ok(false);
1127 }
1128
1129 let mut i = 0;
1130 for child in func.children() {
1131 if child.abbrev_entry().tag as u16 == DW_TAG_formal_parameter.0 {
1132 if i == 0 {
1133 let param_type = child.index(DW_AT_type.0 as u64)?.as_type();
1134 if param_type.get_die()?.abbrev_entry().tag as u16 != DW_TAG_pointer_type.0 {
1135 return Ok(false);
1136 }
1137 let pointed_type = param_type
1138 .get_die()?
1139 .index(DW_AT_type.0 as u64)?
1140 .as_type()
1141 .strip_cv_typedef()?;
1142 if pointed_type != *class_type {
1143 return Ok(false);
1144 }
1145 } else if i == 1 {
1146 let param_type = child.index(DW_AT_type.0 as u64)?.as_type();
1147 let tag = param_type.get_die()?.abbrev_entry().tag as u16;
1148 if tag != DW_TAG_reference_type.0 && tag != DW_TAG_rvalue_reference_type.0 {
1149 return Ok(false);
1150 }
1151 let ref_type = param_type
1152 .get_die()?
1153 .index(DW_AT_type.0 as u64)?
1154 .as_type()
1155 .strip_cv_typedef()?;
1156 if ref_type != *class_type {
1157 return Ok(false);
1158 }
1159 } else {
1160 return Ok(false);
1161 }
1162 i += 1;
1163 }
1164 }
1165 Ok(i == 2)
1166}
1167
1168pub fn setup_arguments(
1169 target: &Target,
1170 func: &Rc<Die>,
1171 mut args: Vec<TypedData>,
1172 regs: &mut Registers,
1173 return_slot: Option<VirtualAddress>,
1174) -> Result<(), SdbError> {
1175 let int_regs = [
1176 RegisterId::rdi,
1177 RegisterId::rsi,
1178 RegisterId::rdx,
1179 RegisterId::rcx,
1180 RegisterId::r8,
1181 RegisterId::r9,
1182 ];
1183
1184 let sse_regs = [
1185 RegisterId::xmm0,
1186 RegisterId::xmm1,
1187 RegisterId::xmm2,
1188 RegisterId::xmm3,
1189 RegisterId::xmm4,
1190 RegisterId::xmm5,
1191 RegisterId::xmm6,
1192 RegisterId::xmm7,
1193 ];
1194
1195 let mut current_int_reg = 0;
1196 let mut current_sse_reg = 0;
1197 let mut stack_args = Vec::<(TypedData, usize)>::new();
1198 let mut rsp = regs.read_by_id_as::<u64>(RegisterId::rsp)?;
1199
1200 let round_up_to_eightbyte = |size: usize| -> usize { (size + 7) & !7 };
1201
1202 if func.contains(DW_AT_type.0 as u64) {
1203 let ret_type = func.index(DW_AT_type.0 as u64)?.as_type();
1204 let ret_class = ret_type.get_parameter_classes()?[0];
1205 if ret_class == ParameterClass::Memory {
1206 current_int_reg += 1;
1207 if let Some(slot) = return_slot {
1208 regs.write_by_id(int_regs[0], slot.addr(), true)?;
1209 }
1210 }
1211 }
1212
1213 let params = func.parameter_types()?;
1214 for i in 0..params.len() {
1215 let param = ¶ms[i];
1216 if param.is_reference_type()? {
1217 if let Some(address) = args[i].address() {
1218 args[i] = TypedData::builder()
1219 .data(address.addr().to_le_bytes().to_vec())
1220 .type_(SdbType::new_builtin(BuiltinType::Integer))
1221 .build();
1222 } else {
1223 rsp -= args[i].value_type().byte_size()? as u64;
1224 rsp &= !(args[i].value_type().alignment()? as u64 - 1);
1225 target
1226 .get_process()
1227 .write_memory(VirtualAddress::new(rsp), args[i].data())?;
1228 args[i] = TypedData::builder()
1229 .data(rsp.to_le_bytes().to_vec())
1230 .type_(SdbType::new_builtin(BuiltinType::Integer))
1231 .build();
1232 }
1233 }
1234 }
1235
1236 for i in 0..params.len() {
1237 let arg = &args[i];
1238 let param = ¶ms[i];
1239 let param_classes = params[i].get_parameter_classes()?;
1240 let param_size = param.byte_size()?;
1241
1242 let required_int_regs = param_classes
1243 .iter()
1244 .filter(|&&c| c == ParameterClass::Integer)
1245 .count();
1246 let required_sse_regs = param_classes
1247 .iter()
1248 .filter(|&&c| c == ParameterClass::Sse)
1249 .count();
1250
1251 if current_int_reg + required_int_regs > int_regs.len()
1252 || current_sse_reg + required_sse_regs > sse_regs.len()
1253 || (required_int_regs == 0 && required_sse_regs == 0)
1254 {
1255 let size = round_up_to_eightbyte(param_size);
1256 stack_args.push((args[i].clone(), size));
1257 } else {
1258 for j in (0..param_size).step_by(8) {
1259 let reg = match param_classes[j / 8] {
1260 ParameterClass::Integer => {
1261 let reg = int_regs[current_int_reg];
1262 current_int_reg += 1;
1263 reg
1264 }
1265 ParameterClass::Sse => {
1266 let reg = sse_regs[current_sse_reg];
1267 current_sse_reg += 1;
1268 reg
1269 }
1270 ParameterClass::NoClass => continue,
1271 _ => return SdbError::err("Unsupported parameter class"),
1272 };
1273
1274 let mut data = [0u8; 8];
1275 let end = arg.data().len().min(j + 8);
1276 data[..(end - j)].copy_from_slice(&arg.data()[j..end]);
1277 regs.write_by_id(reg, data, true)?;
1278 }
1279 }
1280 }
1281
1282 for (_, size) in &stack_args {
1283 rsp -= *size as u64;
1284 }
1285 rsp &= !0xf;
1286
1287 let mut start_pos = rsp;
1288 for (arg, size) in &stack_args {
1289 target
1290 .get_process()
1291 .write_memory(VirtualAddress::new(start_pos), arg.data())?;
1292 start_pos += *size as u64;
1293 }
1294 regs.write_by_id(RegisterId::rax, current_sse_reg as u64, true)?;
1295 regs.write_by_id(RegisterId::rsp, rsp, true)?;
1296 Ok(())
1297}
1298
1299pub fn read_return_value(
1300 target: &Target,
1301 func: &Rc<Die>,
1302 return_slot: VirtualAddress,
1303 regs: &Registers,
1304) -> Result<TypedData, SdbError> {
1305 let ret_type = func.index(DW_AT_type.0 as u64)?.as_type();
1306 let ret_classes = ret_type.get_parameter_classes()?;
1307
1308 let mut used_int = false;
1309 let mut used_sse = false;
1310
1311 if ret_classes[0] == ParameterClass::Memory {
1312 let value = target
1313 .get_process()
1314 .read_memory(return_slot, ret_type.byte_size()?)?;
1315 return Ok(TypedData::builder()
1316 .data(value)
1317 .type_(func.index(DW_AT_type.0 as u64)?.as_type())
1318 .address(Some(return_slot))
1319 .build());
1320 }
1321
1322 if ret_classes[0] == ParameterClass::X87 {
1323 let data = regs.read_by_id_as::<F80>(RegisterId::st0)?;
1324 let value = to_byte_vec(&data);
1325 target.get_process().write_memory(return_slot, &value)?;
1326 return Ok(TypedData::builder()
1327 .data(value)
1328 .type_(func.index(DW_AT_type.0 as u64)?.as_type())
1329 .address(Some(return_slot))
1330 .build());
1331 }
1332
1333 let mut value = Vec::new();
1334 for ret_class in ret_classes {
1335 match ret_class {
1336 ParameterClass::Integer => {
1337 let reg = if used_int {
1338 RegisterId::rdx
1339 } else {
1340 RegisterId::rax
1341 };
1342 used_int = true;
1343 let data = regs.read_by_id_as::<u64>(reg)?;
1344 let new_value = data.to_le_bytes().to_vec();
1345 value.extend(new_value);
1346 }
1347 ParameterClass::Sse => {
1348 let reg = if used_sse {
1349 RegisterId::xmm1
1350 } else {
1351 RegisterId::xmm0
1352 };
1353 used_sse = true;
1354 let data = regs.read_by_id_as::<Byte128>(reg)?;
1355 value = data.to_vec();
1356 target.get_process().write_memory(return_slot, &value)?;
1357 }
1358 ParameterClass::NoClass => {}
1359 _ => return SdbError::err("Unsupported return type"),
1360 }
1361 }
1362 target.get_process().write_memory(return_slot, &value)?;
1363 Ok(TypedData::builder()
1364 .data(value)
1365 .type_(func.index(DW_AT_type.0 as u64)?.as_type())
1366 .address(Some(return_slot))
1367 .build())
1368}