libsdb/
types.rs

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 /* 0 */) -> 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 = &params[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 = &params[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}