rust_debug/evaluate/
evaluate.rs

1use super::attributes;
2use crate::call_stack::MemoryAccess;
3use crate::registers::Registers;
4use std::convert::TryInto;
5
6use gimli::{DwAte, Location, Piece, Reader};
7
8use anyhow::{anyhow, Result};
9use log::{debug, error, info};
10
11use std::fmt;
12
13/// A wrapper for `gimli::Piece` which also contains a boolean that describes if this piece has
14/// already been used to evaluate a value.
15/// This means that the offset in the type information should be used.
16#[derive(Debug, Clone)]
17struct MyPiece<R: Reader<Offset = usize>> {
18    /// The piece which contains location information.
19    pub piece: Piece<R>,
20
21    /// Is true if this piece has already been used to evaluate a value.
22    pub used_before: bool,
23}
24impl<R: Reader<Offset = usize>> MyPiece<R> {
25    /// Creates a new `MyPiece`.
26    pub fn new(piece: Piece<R>) -> MyPiece<R> {
27        MyPiece {
28            piece,
29            used_before: false,
30        }
31    }
32
33    /// Updates the size in_bits value and return a boolean which tells if the piece is consumed
34    /// and should be removed.
35    ///
36    /// Description:
37    ///
38    /// * `bit_size` - How many bits of data needed from the piece.
39    pub fn should_remove(&mut self, bit_size: u64) -> bool {
40        match self.piece.size_in_bits {
41            Some(val) => {
42                if val > bit_size {
43                    self.piece.size_in_bits = Some(val - bit_size);
44                    self.used_before = true;
45                    false
46                } else {
47                    self.used_before = true;
48                    self.piece.size_in_bits = Some(0);
49                    true
50                }
51            }
52            None => {
53                self.used_before = true;
54                false
55            }
56        }
57    }
58}
59
60/// Describes all the different Rust types values in the form of a tree structure.
61#[derive(Debug, Clone)]
62pub enum EvaluatorValue<R: Reader<Offset = usize>> {
63    /// A base_type type and value with location information.
64    Value(BaseTypeValue, ValueInformation),
65
66    /// A pointer_type type and value.
67    PointerTypeValue(Box<PointerTypeValue<R>>),
68
69    /// A variant type and value.
70    VariantValue(Box<VariantValue<R>>),
71
72    /// A variant_part type and value.
73    VariantPartValue(Box<VariantPartValue<R>>),
74
75    /// A subrange_type type and value.
76    SubrangeTypeValue(SubrangeTypeValue),
77
78    /// gimli-rs bytes value.
79    Bytes(R),
80
81    /// A array type value.
82    Array(Box<ArrayTypeValue<R>>),
83
84    /// A struct type value.
85    Struct(Box<StructureTypeValue<R>>),
86
87    /// A enum type value.
88    Enum(Box<EnumerationTypeValue<R>>),
89
90    /// A union type value.
91    Union(Box<UnionTypeValue<R>>),
92
93    /// A attribute type value.
94    Member(Box<MemberValue<R>>),
95
96    /// The value is optimized away.
97    OptimizedOut, // NOTE: Value is optimized out.
98
99    /// The variable has no location currently but had or will have one. Note that the location can
100    /// be a constant stored in the DWARF stack.
101    LocationOutOfRange,
102
103    /// The value is size 0 bits.
104    ZeroSize,
105}
106
107impl<R: Reader<Offset = usize>> fmt::Display for EvaluatorValue<R> {
108    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
109        match self {
110            EvaluatorValue::Value(val, _) => val.fmt(f),
111            EvaluatorValue::PointerTypeValue(pt) => pt.fmt(f),
112            EvaluatorValue::VariantValue(var) => var.fmt(f),
113            EvaluatorValue::VariantPartValue(vpa) => vpa.fmt(f),
114            EvaluatorValue::SubrangeTypeValue(srt) => srt.fmt(f),
115            EvaluatorValue::Bytes(byt) => write!(f, "{:?}", byt),
116            EvaluatorValue::Array(arr) => arr.fmt(f),
117            EvaluatorValue::Struct(stu) => stu.fmt(f),
118            EvaluatorValue::Enum(enu) => enu.fmt(f),
119            EvaluatorValue::Union(uni) => uni.fmt(f),
120            EvaluatorValue::Member(mem) => mem.fmt(f),
121            EvaluatorValue::OptimizedOut => write!(f, "< OptimizedOut >"),
122            EvaluatorValue::LocationOutOfRange => write!(f, "< LocationOutOfRange >"),
123            EvaluatorValue::ZeroSize => write!(f, "< ZeroSize >"),
124        }
125    }
126}
127
128impl<R: Reader<Offset = usize>> EvaluatorValue<R> {
129    /// Will return this value as a `BaseTypeValue` struct if possible.
130    pub fn to_value(self) -> Option<BaseTypeValue> {
131        match self {
132            EvaluatorValue::Value(val, _) => Some(val),
133            EvaluatorValue::Member(val) => val.value.to_value(),
134            EvaluatorValue::OptimizedOut => None,
135            EvaluatorValue::ZeroSize => None,
136            _ => None, // TODO: Find a better solution then this.
137        }
138    }
139
140    /// Will return the type of this value as a `String`.
141    pub fn get_type(&self) -> String {
142        match self {
143            // TODO Update
144            EvaluatorValue::Value(val, _) => val.get_type(),
145            EvaluatorValue::Array(arr) => arr.get_type(),
146            EvaluatorValue::Struct(stu) => stu.get_type(),
147            EvaluatorValue::Enum(enu) => enu.get_type(),
148            EvaluatorValue::Union(uni) => uni.get_type(),
149            EvaluatorValue::Member(mem) => mem.get_type(),
150            _ => "<unknown>".to_owned(),
151        }
152    }
153
154    /// Will return a `Vec` of location and unparsed value infromation about the value.
155    pub fn get_variable_information(self) -> Vec<ValueInformation> {
156        match self {
157            EvaluatorValue::Value(_, var_info) => vec![var_info],
158            EvaluatorValue::Array(arr) => {
159                let mut info = vec![];
160                for val in arr.values {
161                    info.append(&mut val.get_variable_information());
162                }
163                info
164            }
165            EvaluatorValue::Struct(st) => {
166                let mut info = vec![];
167                for val in st.members {
168                    info.append(&mut val.get_variable_information());
169                }
170                info
171            }
172            EvaluatorValue::Enum(en) => en.variant.get_variable_information(),
173            EvaluatorValue::Union(un) => {
174                let mut info = vec![];
175                for val in un.members {
176                    info.append(&mut val.get_variable_information());
177                }
178                info
179            }
180            EvaluatorValue::Member(me) => me.value.get_variable_information(),
181            EvaluatorValue::OptimizedOut => {
182                vec![ValueInformation::new(
183                    None,
184                    vec![ValuePiece::Dwarf { value: None }],
185                )]
186            }
187            _ => vec![],
188        }
189    }
190
191    /// Evaluate a list of `Piece`s into a value and parse it to the given type.
192    ///
193    /// Description:
194    ///
195    /// * `dwarf` - A reference to gimli-rs `Dwarf` struct.
196    /// * `registers` - A register struct for accessing the register values.
197    /// * `mem` - A struct for accessing the memory of the debug target.
198    /// * `pieces` - A list of gimli-rs pieces containing the location information..
199    /// * `unit_offset` - A offset to the `Unit` which contains the given type DIE.
200    /// * `die_offset` - A offset to the DIE that contains the type of the value.
201    ///
202    /// This function will use the location information in the `pieces` parameter to read the
203    /// values and parse it to the given type.
204    pub fn evaluate_variable_with_type<M: MemoryAccess>(
205        dwarf: &gimli::Dwarf<R>,
206        registers: &Registers,
207        mem: &mut M,
208        pieces: &[Piece<R>],
209        unit_offset: gimli::UnitSectionOffset,
210        die_offset: gimli::UnitOffset,
211    ) -> Result<EvaluatorValue<R>> {
212        log::info!("evaluate_variable_with_type");
213        // Initialize the memory offset to 0.
214        let data_offset: u64 = 0;
215
216        // Get the unit of the current state.
217        let unit = match unit_offset {
218            gimli::UnitSectionOffset::DebugInfoOffset(offset) => {
219                let header = dwarf.debug_info.header_from_offset(offset)?;
220                dwarf.unit(header)?
221            }
222            gimli::UnitSectionOffset::DebugTypesOffset(_offset) => {
223                let mut iter = dwarf.debug_types.units();
224                let mut result = None;
225                while let Some(header) = iter.next()? {
226                    if header.offset() == unit_offset {
227                        result = Some(dwarf.unit(header)?);
228                        break;
229                    }
230                }
231                match result {
232                    Some(val) => val,
233                    None => {
234                        error!("Could not find unit from offset");
235                        return Err(anyhow!("Could not find unit from offset"));
236                    }
237                }
238            }
239        };
240        info!("Found unit");
241
242        // Get the die of the current state.
243        let die = &unit.entry(die_offset)?;
244        info!("Found die");
245
246        let mut my_pieces = pieces.iter().map(|p| MyPiece::new(p.clone())).collect();
247        info!("has pieces");
248
249        // Continue evaluating the value of the current state.
250        EvaluatorValue::eval_type(
251            registers,
252            mem,
253            dwarf,
254            &unit,
255            die,
256            data_offset,
257            &mut my_pieces,
258        )
259    }
260
261    /// This function will evaluate the given pieces into a unsigned 32 bit integer.
262    ///
263    /// Description:
264    ///
265    /// * `registers` - A register struct for accessing the register values.
266    /// * `mem` - A struct for accessing the memory of the debug target.
267    /// * `pieces` - A list of gimli-rs pieces containing the location information..
268    pub fn evaluate_variable<M: MemoryAccess>(
269        registers: &Registers,
270        mem: &mut M,
271        pieces: &[Piece<R>],
272    ) -> Result<EvaluatorValue<R>> {
273        log::debug!("evaluate_variable");
274        let mut my_pieces = pieces.iter().map(|p| MyPiece::new(p.clone())).collect();
275        EvaluatorValue::handle_eval_piece(registers, mem, 4, 0, DwAte(1), &mut my_pieces)
276    }
277
278    /// Will maybe consume a number of pieces to evaluate a base type.
279    ///
280    /// Description:
281    ///
282    /// * `registers` - A register struct for accessing the register values.
283    /// * `mem` - A struct for accessing the memory of the debug target.
284    /// * `byte_size` - The size of the base type in bytes.
285    /// * `data_offset` - The memory address offset.
286    /// * `encoding` - The encoding of the base type.
287    /// * `pieces` - A list of pieces containing the location and size information.
288    fn handle_eval_piece<M: MemoryAccess>(
289        registers: &Registers,
290        mem: &mut M,
291        byte_size: u64,
292        data_offset: u64,
293        encoding: DwAte,
294        pieces: &mut Vec<MyPiece<R>>,
295    ) -> Result<EvaluatorValue<R>> {
296        debug!("encoding: {:?}", encoding);
297        debug!("byte_size: {:?}", byte_size);
298        debug!("pieces: {:?}", pieces);
299        if pieces.is_empty() {
300            return Ok(EvaluatorValue::OptimizedOut);
301        }
302
303        let mut all_bytes = vec![];
304        let mut value_pieces = vec![];
305        while all_bytes.len() < byte_size.try_into()? {
306            if pieces.is_empty() {
307                error!("Unreachable");
308                return Err(anyhow!("Unreachable"));
309                //return Ok(EvaluatorValue::OptimizedOut);
310            }
311
312            // Evaluate the bytes needed from one gimli::Piece.
313            match pieces[0].piece.clone().location {
314                Location::Empty => {
315                    // Remove piece if whole object is used.
316                    let bit_size = 8 * (byte_size - all_bytes.len() as u64);
317                    if pieces[0].should_remove(bit_size) {
318                        pieces.remove(0);
319                    }
320                    return Ok(EvaluatorValue::OptimizedOut);
321                }
322                Location::Register { ref register } => {
323                    match registers.get_register_value(&register.0) {
324                        Some(val) => {
325                            // TODO: Mask the important bits?
326                            let mut bytes = vec![];
327                            bytes.extend_from_slice(&val.to_le_bytes());
328
329                            bytes = trim_piece_bytes(bytes, &pieces[0].piece, 4); // 4 because 32 bit registers
330                            let bytes_len = bytes.len();
331
332                            all_bytes.extend_from_slice(&bytes);
333                            value_pieces.extend_from_slice(&[ValuePiece::Register {
334                                register: register.0,
335                                byte_size: bytes_len,
336                            }]);
337
338                            // Remove piece if whole object is used.
339                            let bit_size = 8 * (bytes_len as u64);
340                            if pieces[0].should_remove(bit_size) {
341                                pieces.remove(0);
342                            }
343                        }
344                        None => return Err(anyhow!("Requires reg")),
345                    };
346                }
347                Location::Address { mut address } => {
348                    // Check if `data_offset` should be used.
349                    address += {
350                        if pieces[0].used_before {
351                            data_offset
352                        } else {
353                            0
354                        }
355                    };
356
357                    let num_bytes = match pieces[0].piece.size_in_bits {
358                        Some(val) => {
359                            let max_num_bytes = (val + 8 - 1) / 8;
360                            let needed_num_bytes = byte_size - all_bytes.len() as u64;
361                            if max_num_bytes < needed_num_bytes {
362                                max_num_bytes
363                            } else {
364                                needed_num_bytes
365                            }
366                        }
367                        None => byte_size - all_bytes.len() as u64,
368                    } as usize;
369
370                    let bytes = match mem.get_address(&(address as u32), num_bytes) {
371                        Some(val) => val,
372                        None => {
373                            error!(
374                                "can not read address: {:x} num_bytes: {:?}, Return error",
375                                address as u64, num_bytes
376                            );
377                            return Err(anyhow!(
378                                "can not read address: {:x} num_bytes: {:?}, Return error",
379                                address as u64,
380                                num_bytes
381                            ));
382                        }
383                    };
384
385                    all_bytes.extend_from_slice(&bytes);
386                    value_pieces.extend_from_slice(&[ValuePiece::Memory {
387                        address: address as u32,
388                        byte_size: num_bytes,
389                    }]);
390
391                    // Remove piece if whole object is used.
392                    let bit_size = 8 * num_bytes as u64;
393                    if pieces[0].should_remove(bit_size) {
394                        pieces.remove(0);
395                    }
396                }
397                Location::Value { value } => {
398                    // Remove piece if whole object is used.
399                    let bit_size = 8 * (byte_size - all_bytes.len() as u64);
400                    if pieces[0].should_remove(bit_size) {
401                        pieces.remove(0);
402                    }
403
404                    let parsed_value = convert_from_gimli_value(value);
405                    return match parsed_value {
406                        BaseTypeValue::Generic(v) => {
407                            let correct_value = match (encoding, byte_size) {
408                                (DwAte(1), 4) => BaseTypeValue::Address32(v as u32),
409                                //(DwAte(1), 4) => BaseTypeValue::Reg32(v as u32),
410                                (DwAte(2), _) => BaseTypeValue::Bool(v != 0),
411                                (DwAte(7), 1) => BaseTypeValue::U8(v as u8),
412                                (DwAte(7), 2) => BaseTypeValue::U16(v as u16),
413                                (DwAte(7), 4) => BaseTypeValue::U32(v as u32),
414                                (DwAte(7), 8) => BaseTypeValue::U64(v as u64),
415                                (DwAte(5), 1) => BaseTypeValue::I8(v as i8),
416                                (DwAte(5), 2) => BaseTypeValue::I16(v as i16),
417                                (DwAte(5), 4) => BaseTypeValue::I32(v as i32),
418                                (DwAte(5), 8) => BaseTypeValue::I64(v as i64),
419                                (DwAte(4), 4) => BaseTypeValue::F32(v as f32),
420                                (DwAte(4), 8) => BaseTypeValue::F64(v as f64),
421                                _ => BaseTypeValue::Generic(v),
422                            };
423                            //
424                            Ok(EvaluatorValue::Value(
425                                correct_value,
426                                ValueInformation::new(
427                                    None,
428                                    vec![ValuePiece::Dwarf { value: Some(value) }],
429                                ),
430                            ))
431                        }
432                        _ => Ok(EvaluatorValue::Value(
433                            parsed_value,
434                            ValueInformation {
435                                raw: None,
436                                pieces: vec![ValuePiece::Dwarf { value: Some(value) }],
437                            },
438                        )),
439                    };
440                }
441
442                Location::Bytes { mut value } => {
443                    let mut bytes = vec![];
444                    let mut loops = byte_size as usize - all_bytes.len();
445                    if value.len() < loops {
446                        loops = value.len();
447                    }
448                    for _i in 0..loops {
449                        bytes.push(value.read_u8()?);
450                    }
451
452                    value_pieces.extend_from_slice(&[ValuePiece::Bytes {
453                        bytes: bytes.clone(),
454                    }]);
455
456                    all_bytes.extend_from_slice(&bytes.into_boxed_slice());
457
458                    // Remove piece if whole object is used.
459                    let bit_size = 8 * (byte_size - all_bytes.len() as u64);
460                    if pieces[0].should_remove(bit_size) {
461                        pieces.remove(0);
462                    }
463
464                    //return Ok(EvaluatorValue::Bytes(value.clone()));
465                }
466                Location::ImplicitPointer {
467                    value: _,
468                    byte_offset: _,
469                } => {
470                    error!("Unimplemented");
471                    return Err(anyhow!("Unimplemented"));
472                }
473            }
474        }
475
476        while all_bytes.len() > byte_size as usize {
477            all_bytes.pop(); // NOTE: Removes extra bytes if value is from register and less the 4 byts
478        }
479
480        Ok(EvaluatorValue::Value(
481            BaseTypeValue::parse_base_type(all_bytes.clone(), encoding)?,
482            ValueInformation::new(Some(all_bytes.clone()), value_pieces),
483        ))
484    }
485
486    /// Evaluate and parse the type by going down the tree of type dies.
487    ///
488    /// Description:
489    ///
490    /// * `registers` - A register struct for accessing the register values.
491    /// * `mem` - A struct for accessing the memory of the debug target.
492    /// * `dwarf` - A reference to gimli-rs `Dwarf` struct.
493    /// * `unit` - A compilation unit which contains the given DIE.
494    /// * `die` - The current type die in the type tree.
495    /// * `data_offset` - The memory address offset.
496    /// * `pieces` - A list of pieces containing the location and size information.
497    fn eval_type<M: MemoryAccess>(
498        registers: &Registers,
499        mem: &mut M,
500        dwarf: &gimli::Dwarf<R>,
501        unit: &gimli::Unit<R>,
502        die: &gimli::DebuggingInformationEntry<'_, '_, R>,
503        data_offset: u64,
504        pieces: &mut Vec<MyPiece<R>>,
505    ) -> Result<EvaluatorValue<R>> {
506        info!("tag: {:?}", die.tag());
507        match die.tag() {
508            gimli::DW_TAG_base_type => {
509                // Make sure that the die has the tag DW_TAG_base_type.
510                match die.tag() {
511                    gimli::DW_TAG_base_type => (),
512                    _ => {
513                        error!("Expected DW_TAG_base_type die, this should never happen");
514                        return Err(anyhow!(
515                            "Expected DW_TAG_base_type die, this should never happen"
516                        ));
517                    }
518                };
519
520                check_alignment(die, data_offset, pieces)?;
521
522                // Get byte size and encoding from the die.
523                let byte_size = match attributes::byte_size_attribute(die)? {
524                    Some(val) => val,
525                    None => {
526                        error!("Missing required byte size attribute");
527                        return Err(anyhow!("Missing required byte size attribute"));
528                    }
529                };
530
531                if byte_size == 0 {
532                    return Ok(EvaluatorValue::ZeroSize);
533                }
534
535                let encoding = match attributes::encoding_attribute(die)? {
536                    Some(val) => val,
537                    None => {
538                        error!("Missing required encoding attribute");
539                        return Err(anyhow!("Missing required encoding attribute"));
540                    }
541                };
542
543                // Evaluate the value.
544                EvaluatorValue::handle_eval_piece(
545                    registers,
546                    mem,
547                    byte_size,
548                    data_offset, // TODO
549                    encoding,
550                    pieces,
551                )
552            }
553            gimli::DW_TAG_pointer_type => {
554                info!("DW_TAG_pointer_type");
555                // Make sure that the die has the tag DW_TAG_pointer_type.
556                match die.tag() {
557                    gimli::DW_TAG_pointer_type => (),
558                    _ => {
559                        error!("Expected DW_TAG_pointer_type die, this should never happen");
560                        return Err(anyhow!(
561                            "Expected DW_TAG_pointer_type die, this should never happen"
562                        ));
563                    }
564                };
565
566                check_alignment(die, data_offset, pieces)?;
567
568                // Get the name of the pointer type.
569                let name = attributes::name_attribute(dwarf, die)?;
570
571                // Evaluate the pointer type value.
572                let address_class = match attributes::address_class_attribute(die)? {
573                    Some(val) => val,
574                    None => {
575                        error!("Die is missing required attribute DW_AT_address_class");
576                        return Err(anyhow!(
577                            "Die is missing required attribute DW_AT_address_class"
578                        ));
579                    }
580                };
581
582                // This vill evaluate the address
583                let address = match address_class.0 {
584                    0 => {
585                        EvaluatorValue::handle_eval_piece(
586                            registers,
587                            mem,
588                            4, // This Should be set dependent on the system(4 for 32 bit systems)
589                            data_offset,
590                            DwAte(1),
591                            pieces,
592                        )?
593                    }
594                    _ => {
595                        error!("Unimplemented DwAddr code"); // NOTE: The codes are architecture specific.
596                        return Err(anyhow!("Unimplemented DwAddr code"));
597                    }
598                };
599
600                let value = match (attributes::type_attribute(dwarf, unit, die)?, &address) {
601                    (
602                        Some((section_offset, unit_offset)),
603                        EvaluatorValue::Value(BaseTypeValue::Address32(address_value), _),
604                    ) => {
605                        // Get the variable die.
606                        let header = dwarf.debug_info.header_from_offset(
607                            match section_offset.as_debug_info_offset() {
608                                Some(val) => val,
609                                None => {
610                                    error!(
611                                        "Could not convert section offset into debug info offset"
612                                    );
613                                    return Err(anyhow!(
614                                        "Could not convert section offset into debug info offset"
615                                    ));
616                                }
617                            },
618                        )?;
619
620                        let type_unit = gimli::Unit::new(dwarf, header)?;
621                        let type_die = type_unit.entry(unit_offset)?;
622                        let mut new_pieces = vec![MyPiece::new(Piece {
623                            size_in_bits: None,
624                            bit_offset: None,
625                            location: Location::<R>::Address {
626                                address: *address_value as u64,
627                            },
628                        })];
629                        EvaluatorValue::eval_type(
630                            registers,
631                            mem,
632                            dwarf,
633                            &type_unit,
634                            &type_die,
635                            0,
636                            &mut new_pieces,
637                        )?
638                    }
639                    _ => EvaluatorValue::OptimizedOut,
640                };
641
642                Ok(EvaluatorValue::PointerTypeValue(Box::new(
643                    PointerTypeValue {
644                        name,
645                        address,
646                        value,
647                    },
648                )))
649
650                // TODO: Use DW_AT_type and the evaluated address to evaluate the pointer.
651            }
652            gimli::DW_TAG_array_type => {
653                // Make sure that the die has the tag DW_TAG_array_type.
654                match die.tag() {
655                    gimli::DW_TAG_array_type => (),
656                    _ => {
657                        error!("Expected DW_TAG_array_type die, this should never happen");
658                        return Err(anyhow!(
659                            "Expected DW_TAG_array_type die, this should never happen"
660                        ));
661                    }
662                };
663
664                check_alignment(die, data_offset, pieces)?;
665
666                let mut children = get_children(unit, die)?;
667                let mut i = 0;
668                while i < children.len() {
669                    let die = unit.entry(children[i])?;
670                    match die.tag() {
671                        gimli::DW_TAG_subrange_type => (),
672                        _ => {
673                            let _c = children.remove(i);
674                            i -= 1;
675                        }
676                    }
677                    i += 1;
678                }
679
680                if children.len() != 1 {
681                    error!("Unreachable");
682                    return Err(anyhow!("Unreachable"));
683                }
684
685                let dimension_die = unit.entry(children[0])?;
686
687                let subrange_type_value = match EvaluatorValue::eval_type(
688                    registers,
689                    mem,
690                    dwarf,
691                    unit,
692                    &dimension_die,
693                    data_offset,
694                    pieces,
695                )? {
696                    EvaluatorValue::SubrangeTypeValue(subrange_type_value) => subrange_type_value,
697                    _ => {
698                        error!("Unreachable");
699                        return Err(anyhow!("Unreachable"));
700                    }
701                };
702
703                let mut values = vec![];
704
705                // Evaluate all the values in the array.
706                match subrange_type_value.get_count()? {
707                    Some(count) => {
708                        // Get type attribute unit and die.
709                        let (type_unit, die_offset) = get_type_info(dwarf, unit, die)?;
710                        let type_die = &type_unit.entry(die_offset)?;
711
712                        // Evaluate all the values in the array.
713                        for _i in 0..count {
714                            values.push(EvaluatorValue::eval_type(
715                                registers,
716                                mem,
717                                dwarf,
718                                &type_unit,
719                                type_die,
720                                data_offset,
721                                pieces,
722                            )?);
723                        }
724                    }
725                    None => (),
726                };
727
728                Ok(EvaluatorValue::Array(Box::new(ArrayTypeValue {
729                    subrange_type_value,
730                    values,
731                })))
732            }
733            gimli::DW_TAG_structure_type => {
734                // Make sure that the die has the tag DW_TAG_structure_type.
735                match die.tag() {
736                    gimli::DW_TAG_structure_type => (),
737                    _ => {
738                        error!("Expected DW_TAG_structure_type die, this should never happen");
739                        return Err(anyhow!(
740                            "Expected DW_TAG_structure_type die, this should never happen"
741                        ));
742                    }
743                };
744
745                check_alignment(die, data_offset, pieces)?;
746
747                let name = match attributes::name_attribute(dwarf, die)? {
748                    Some(val) => val,
749                    None => {
750                        error!("Expected the structure type die to have a name attribute");
751                        return Err(anyhow!(
752                            "Expected the structure type die to have a name attribute"
753                        ));
754                    }
755                };
756
757                // Get all the DW_TAG_member dies.
758                let children = get_children(unit, die)?;
759                let mut member_dies = Vec::new();
760                for c in &children {
761                    let c_die = unit.entry(*c)?;
762                    match c_die.tag() {
763                        // If it is a DW_TAG_variant_part die then it is a enum and only have on value.
764                        gimli::DW_TAG_variant_part => {
765                            // Get the value.
766                            let members = vec![EvaluatorValue::eval_type(
767                                registers,
768                                mem,
769                                dwarf,
770                                unit,
771                                &c_die,
772                                data_offset,
773                                pieces,
774                            )?];
775
776                            return Ok(EvaluatorValue::Struct(Box::new(StructureTypeValue {
777                                name,
778                                members,
779                            })));
780                        }
781                        gimli::DW_TAG_member => {
782                            let data_member_location =
783                                match attributes::data_member_location_attribute(&c_die)? {
784                                    Some(val) => val,
785                                    None => {
786                                        error!(
787                                "Expected member die to have attribute DW_AT_data_member_location"
788                            );
789                                        return Err(
790                                            anyhow!(
791                                "Expected member die to have attribute DW_AT_data_member_location"),
792                                        );
793                                    }
794                                };
795                            member_dies.push((data_member_location, c_die))
796                        }
797                        _ => continue,
798                    };
799                }
800
801                // Sort the members in the evaluation order.
802                member_dies.sort_by_key(|m| m.0);
803
804                // Evaluate all the members.
805                let mut members = vec![];
806                for member_die in &member_dies {
807                    let member = match member_die.1.tag() {
808                        gimli::DW_TAG_member => EvaluatorValue::eval_type(
809                            registers,
810                            mem,
811                            dwarf,
812                            unit,
813                            &member_die.1,
814                            data_offset,
815                            pieces,
816                        )?,
817                        tag => {
818                            error!("Unexpected die tag: {:?}", tag);
819                            return Err(anyhow!("Unimplemented"));
820                        }
821                    };
822                    members.push(member);
823                }
824
825                Ok(EvaluatorValue::Struct(Box::new(StructureTypeValue {
826                    name,
827                    members,
828                })))
829            }
830            gimli::DW_TAG_union_type => {
831                // Make sure that the die has the tag DW_TAG_union_type.
832                match die.tag() {
833                    gimli::DW_TAG_union_type => (),
834                    _ => {
835                        error!("Expected DW_TAG_union_type die, this should never happen");
836                        return Err(anyhow!(
837                            "Expected DW_TAG_union_type die, this should never happen"
838                        ));
839                    }
840                };
841
842                check_alignment(die, data_offset, pieces)?;
843
844                let name = match attributes::name_attribute(dwarf, die)? {
845                    Some(val) => val,
846                    None => {
847                        error!("Expected union type die to have a name attribute");
848                        return Err(anyhow!("Expected union type die to have a name attribute"));
849                    }
850                };
851
852                // Get all children of type DW_TAG_member.
853                let children = get_children(unit, die)?;
854                let mut member_dies = vec![];
855                for c in children {
856                    let c_die = unit.entry(c)?;
857                    match c_die.tag() {
858                        gimli::DW_TAG_member => {
859                            let data_member_location =
860                                match attributes::data_member_location_attribute(&c_die)? {
861                                    Some(val) => val,
862                                    None => {
863                                        error!("Expected member die to have attribute DW_AT_data_member_location");
864                                        return Err(anyhow!("Expected member die to have attribute DW_AT_data_member_location"));
865                                    }
866                                };
867                            member_dies.push((data_member_location, c_die))
868                        }
869                        _ => continue,
870                    };
871                }
872
873                // Sort all the members in the order they need to be evaluated.
874                member_dies.sort_by_key(|m| m.0);
875
876                // Evaluate all the members.
877                let mut members = vec![];
878                for member_die in &member_dies {
879                    let member = match member_die.1.tag() {
880                        gimli::DW_TAG_member => EvaluatorValue::eval_type(
881                            registers,
882                            mem,
883                            dwarf,
884                            unit,
885                            &member_die.1,
886                            data_offset,
887                            pieces,
888                        )?,
889                        tag => {
890                            error!("Unexpected die with tag {:?}", tag);
891                            return Err(anyhow!("Unimplemented"));
892                        }
893                    };
894                    members.push(member);
895                }
896
897                Ok(EvaluatorValue::Union(Box::new(UnionTypeValue {
898                    name,
899                    members,
900                })))
901            }
902            gimli::DW_TAG_member => {
903                // Make sure that the die has the tag DW_TAG_member
904                match die.tag() {
905                    gimli::DW_TAG_member => (),
906                    _ => {
907                        error!("Expected DW_TAG_member die, this should never happen");
908                        return Err(anyhow!(
909                            "Expected DW_TAG_member die, this should never happen"
910                        ));
911                    }
912                };
913
914                // Get the name of the member.
915                let name = attributes::name_attribute(dwarf, die)?;
916
917                // Calculate the new data offset.
918                let new_data_offset = match attributes::data_member_location_attribute(die)? {
919                    // NOTE: Seams it can also be a location description and not an offset. Dwarf 5 page 118
920                    Some(val) => data_offset + val,
921                    None => data_offset,
922                };
923
924                check_alignment(die, new_data_offset, pieces)?;
925
926                // Get the type attribute unit and die.
927                let (type_unit, die_offset) = get_type_info(dwarf, unit, die)?;
928                let type_die = &type_unit.entry(die_offset)?;
929
930                // Evaluate the value.
931                let value = EvaluatorValue::eval_type(
932                    registers,
933                    mem,
934                    dwarf,
935                    &type_unit,
936                    type_die,
937                    new_data_offset,
938                    pieces,
939                )?;
940
941                Ok(EvaluatorValue::Member(Box::new(MemberValue {
942                    name,
943                    value,
944                })))
945            }
946            gimli::DW_TAG_enumeration_type => {
947                // Make sure that the die has the tag DW_TAG_enumeration_type
948                match die.tag() {
949                    gimli::DW_TAG_enumeration_type => (),
950                    _ => {
951                        error!("Expected DW_TAG_enumeration_type die, this should never happen");
952                        return Err(anyhow!(
953                            "Expected DW_TAG_enumeration_type die, this should never happen"
954                        ));
955                    }
956                };
957
958                check_alignment(die, data_offset, pieces)?;
959
960                // Get type attribute unit and die.
961                let (type_unit, die_offset) = get_type_info(dwarf, unit, die)?;
962                let type_die = &type_unit.entry(die_offset)?;
963
964                // Get type value.
965                let variant = EvaluatorValue::eval_type(
966                    registers,
967                    mem,
968                    dwarf,
969                    &type_unit,
970                    type_die,
971                    data_offset,
972                    pieces,
973                )?;
974
975                // Go through the children and find the correct enumerator value.
976                let children = get_children(unit, die)?;
977
978                let mut enumerators = vec![];
979                for c in children {
980                    let c_die = unit.entry(c)?;
981                    match c_die.tag() {
982                        gimli::DW_TAG_enumerator => {
983                            let name = attributes::name_attribute(dwarf, &c_die)?;
984
985                            let const_value = match attributes::const_value_attribute(&c_die)? {
986                                Some(val) => val,
987                                None => {
988                                    error!("Expected enumeration type die to have attribute DW_AT_const_value");
989                                    return Err(anyhow!("Expected enumeration type die to have attribute DW_AT_const_value"));
990                                }
991                            };
992
993                            enumerators.push(EnumeratorValue { name, const_value });
994                        }
995                        gimli::DW_TAG_subprogram => (),
996                        tag => {
997                            error!("Unimplemented for tag: {:?}", tag);
998                            return Err(anyhow!("Unimplemented"));
999                        }
1000                    };
1001                }
1002
1003                // Get the name of the enum type and the enum variant.
1004                let name = match attributes::name_attribute(dwarf, die)? {
1005                    Some(val) => val,
1006                    None => {
1007                        error!("Expected enumeration type die to have attribute DW_AT_name");
1008                        return Err(anyhow!(
1009                            "Expected enumeration type die to have attribute DW_AT_name"
1010                        ));
1011                    }
1012                };
1013
1014                Ok(EvaluatorValue::Enum(Box::new(EnumerationTypeValue {
1015                    name,
1016                    variant,
1017                    enumerators,
1018                })))
1019            }
1020            gimli::DW_TAG_variant_part => {
1021                // Make sure that the die has tag DW_TAG_variant_part
1022                match die.tag() {
1023                    gimli::DW_TAG_variant_part => (),
1024                    _ => {
1025                        error!("Expected DW_TAG_variant_part die, this should never happen");
1026                        return Err(anyhow!(
1027                            "Expected DW_TAG_variant_part die, this should never happen"
1028                        ));
1029                    }
1030                };
1031
1032                check_alignment(die, data_offset, pieces)?;
1033
1034                // Get the enum variant.
1035                // TODO: If variant is optimised out then return optimised out and remove the pieces for
1036                // this type if needed.
1037
1038                let variant: Option<MemberValue<R>> = match attributes::discr_attribute(die)? {
1039                    Some(die_offset) => {
1040                        let member_die = &unit.entry(die_offset)?;
1041
1042                        // Evaluate the DW_TAG_member value.
1043                        match member_die.tag() {
1044                            gimli::DW_TAG_member => match EvaluatorValue::eval_type(
1045                                registers,
1046                                mem,
1047                                dwarf,
1048                                unit,
1049                                member_die,
1050                                data_offset,
1051                                pieces,
1052                            )? {
1053                                EvaluatorValue::Member(member) => Some(*member),
1054                                _ => {
1055                                    error!("Unreachable");
1056                                    return Err(anyhow!("Unreachable"));
1057                                }
1058                            },
1059                            _ => {
1060                                error!("Unreachable");
1061                                return Err(anyhow!("Unreachable"));
1062                            }
1063                        }
1064                    }
1065                    None => None,
1066                };
1067
1068                // The value should be a unsigned int thus convert the value to a u64.
1069                let variant_number = match variant.clone() {
1070                    Some(MemberValue { name: _name, value }) => match value.to_value() {
1071                        Some(val) => Some(get_udata(val)?),
1072                        None => None,
1073                    },
1074                    None => None,
1075                };
1076
1077                let original_pieces = pieces.clone();
1078                // Find  all the DW_TAG_variant dies and evaluate them.
1079                let mut variants = vec![];
1080                let children = get_children(unit, die)?;
1081                for c in &children {
1082                    let c_die = unit.entry(*c)?;
1083                    if c_die.tag() == gimli::DW_TAG_variant {
1084                        let mut temp_pieces = original_pieces.clone();
1085                        // Evaluate the value of the variant.
1086                        let variant = match EvaluatorValue::eval_type(
1087                            registers,
1088                            mem,
1089                            dwarf,
1090                            unit,
1091                            &c_die,
1092                            data_offset,
1093                            &mut temp_pieces,
1094                        )? {
1095                            EvaluatorValue::VariantValue(variant) => variant,
1096                            _ => {
1097                                error!("Unreachable");
1098                                return Err(anyhow!("Unreachable"));
1099                            }
1100                        };
1101
1102                        if let (Some(discr_value), Some(variant_num)) =
1103                            (variant.discr_value, variant_number)
1104                        {
1105                            // If This is the variant then update the piece index.
1106                            if discr_value == variant_num {
1107                                *pieces = temp_pieces;
1108                            }
1109                        };
1110
1111                        variants.push(*variant);
1112                    };
1113                }
1114
1115                Ok(EvaluatorValue::VariantPartValue(Box::new(
1116                    VariantPartValue { variant, variants },
1117                )))
1118            }
1119            gimli::DW_TAG_variant => {
1120                check_alignment(die, data_offset, pieces)?;
1121
1122                let mut members = vec![];
1123
1124                // Find the child die of type DW_TAG_member
1125                let children = get_children(unit, die)?;
1126                for c in children {
1127                    let c_die = unit.entry(c)?;
1128                    if c_die.tag() == gimli::DW_TAG_member {
1129                        // Evaluate the value of the member.
1130                        let member = match EvaluatorValue::eval_type(
1131                            registers,
1132                            mem,
1133                            dwarf,
1134                            unit,
1135                            &c_die,
1136                            data_offset,
1137                            pieces,
1138                        )? {
1139                            EvaluatorValue::Member(member) => member,
1140                            _ => {
1141                                error!("Unreachable");
1142                                return Err(anyhow!("Unreachable"));
1143                            }
1144                        };
1145
1146                        members.push(member);
1147                    };
1148                }
1149
1150                if members.len() != 1 {
1151                    error!("Unreachable");
1152                    return Err(anyhow!("Unreachable"));
1153                    // DW_TAG_variant should only have one member child.
1154                }
1155
1156                let discr_value = attributes::discr_value_attribute(die)?;
1157
1158                Ok(EvaluatorValue::VariantValue(Box::new(VariantValue {
1159                    discr_value,
1160                    child: *members[0].clone(),
1161                })))
1162            }
1163            gimli::DW_TAG_subrange_type => {
1164                // Make sure that the die has the tag DW_TAG_subrange_type
1165                match die.tag() {
1166                    gimli::DW_TAG_subrange_type => (),
1167                    _ => {
1168                        error!("Expected DW_TAG_subrange_type die, this should never happen");
1169                        return Err(anyhow!(
1170                            "Expected DW_TAG_subrange_type die, this should never happen"
1171                        ));
1172                    }
1173                };
1174
1175                let lower_bound = attributes::lower_bound_attribute(die)?;
1176
1177                // If the die has a count attribute then that is the value.
1178                match attributes::count_attribute(die)? {
1179                    // NOTE: This could be replace with lower and upper bound
1180                    Some(count) => Ok(EvaluatorValue::SubrangeTypeValue(SubrangeTypeValue {
1181                        lower_bound,
1182                        count: Some(count),
1183                        base_type_value: None,
1184                    })),
1185                    None => {
1186                        // Get the type unit and die.
1187                        let (type_unit, die_offset) = match get_type_info(dwarf, unit, die) {
1188                            Ok(val) => val,
1189                            Err(_) => {
1190                                error!("Expected subrange type die to have type information");
1191                                return Err(anyhow!(
1192                                    "Expected subrange type die to have type information"
1193                                ));
1194                            }
1195                        };
1196                        let type_die = &type_unit.entry(die_offset)?;
1197
1198                        // Evaluate the type attribute value.
1199                        let base_type_value = match EvaluatorValue::eval_type(
1200                            registers,
1201                            mem,
1202                            dwarf,
1203                            &type_unit,
1204                            type_die,
1205                            data_offset,
1206                            pieces,
1207                        )? {
1208                            EvaluatorValue::Value(base_type_value, value_information) => {
1209                                Some((base_type_value, value_information))
1210                            }
1211                            _ => {
1212                                error!("Unreachable");
1213                                return Err(anyhow!("Unreachable"));
1214                            }
1215                        };
1216                        Ok(EvaluatorValue::SubrangeTypeValue(SubrangeTypeValue {
1217                            lower_bound,
1218                            count: None,
1219                            base_type_value,
1220                        }))
1221                    }
1222                }
1223            }
1224            gimli::DW_TAG_subroutine_type => {
1225                error!("Unimplemented");
1226                Err(anyhow!("Unimplemented"))
1227            }
1228            gimli::DW_TAG_subprogram => {
1229                error!("Unimplemented");
1230                Err(anyhow!("Unimplemented"))
1231            }
1232            gimli::DW_TAG_string_type => {
1233                error!("Unimplemented");
1234                Err(anyhow!("Unimplemented"))
1235            }
1236            gimli::DW_TAG_generic_subrange => {
1237                error!("Unimplemented");
1238                Err(anyhow!("Unimplemented"))
1239            }
1240            gimli::DW_TAG_template_type_parameter => {
1241                error!("Unimplemented");
1242                Err(anyhow!("Unimplemented"))
1243            }
1244            tag => {
1245                error!("Unimplemented for tag {:?}", tag);
1246                Err(anyhow!("Unimplemented"))
1247            }
1248        }
1249    }
1250}
1251
1252/// Parse a `BaseTypeValue` struct to a `u64` value.
1253///
1254/// Description:
1255///
1256/// * `value` - The `BaseTypeValue` that will be turned into a `u64`.
1257pub fn get_udata(value: BaseTypeValue) -> Result<u64> {
1258    match value {
1259        BaseTypeValue::U8(v) => Ok(v as u64),
1260        BaseTypeValue::U16(v) => Ok(v as u64),
1261        BaseTypeValue::U32(v) => Ok(v as u64),
1262        BaseTypeValue::U64(v) => Ok(v),
1263        BaseTypeValue::Generic(v) => Ok(v),
1264        _ => {
1265            error!("Unimplemented");
1266            Err(anyhow!("Unimplemented"))
1267        }
1268    }
1269}
1270
1271/// Format a `Vec` of `EvaluatorValue`s into a `String` that describes the value and type.
1272///
1273/// Description:
1274///
1275/// * `values` - A list of `EvaluatorValue`s that will be formatted into a `String`.
1276fn format_values<R: Reader<Offset = usize>>(values: &Vec<EvaluatorValue<R>>) -> String {
1277    let len = values.len();
1278    if len == 0 {
1279        return "".to_string();
1280    } else if len == 1 {
1281        return format!("{}", values[0]);
1282    }
1283
1284    let mut res = format!("{}", values[0]);
1285    for value in values.iter().take(len).skip(1) {
1286        res = format!("{}, {}", res, value);
1287    }
1288    res
1289}
1290
1291/// Format a `Vec` of `EvaluatorValue`s into a `String` that describes the type.
1292///
1293/// Description:
1294///
1295/// * `values` - A list of `EvaluatorValue`s that will be formatted into a `String`.
1296fn format_types<R: Reader<Offset = usize>>(values: &Vec<EvaluatorValue<R>>) -> String {
1297    let len = values.len();
1298    if len == 0 {
1299        return "".to_string();
1300    } else if len == 1 {
1301        return values[0].get_type();
1302    }
1303
1304    let mut res = values[0].get_type();
1305    for value in values.iter().take(len).skip(1) {
1306        res = format!("{}, {}", res, value.get_type());
1307    }
1308    res
1309}
1310
1311/// Struct that represents a array type.
1312#[derive(Debug, Clone)]
1313pub struct ArrayTypeValue<R: Reader<Offset = usize>> {
1314    /// subrange_type information.
1315    pub subrange_type_value: SubrangeTypeValue,
1316
1317    /// The list of values in the array.
1318    pub values: Vec<EvaluatorValue<R>>,
1319}
1320
1321impl<R: Reader<Offset = usize>> fmt::Display for ArrayTypeValue<R> {
1322    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1323        write!(f, "[ {} ]", format_values(&self.values))
1324    }
1325}
1326
1327impl<R: Reader<Offset = usize>> ArrayTypeValue<R> {
1328    /// Get the type of the array as a `String`.
1329    pub fn get_type(&self) -> String {
1330        format!("[ {} ]", format_types(&self.values))
1331    }
1332}
1333
1334/// Struct that represents a struct type.
1335#[derive(Debug, Clone)]
1336pub struct StructureTypeValue<R: Reader<Offset = usize>> {
1337    /// The name of the struct.
1338    pub name: String,
1339
1340    /// All the attributes of the struct.
1341    pub members: Vec<EvaluatorValue<R>>,
1342}
1343
1344impl<R: Reader<Offset = usize>> fmt::Display for StructureTypeValue<R> {
1345    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1346        write!(f, "{} {{ {} }}", self.name, format_values(&self.members))
1347    }
1348}
1349
1350impl<R: Reader<Offset = usize>> StructureTypeValue<R> {
1351    /// Get the type of the struct as a `String`.
1352    pub fn get_type(&self) -> String {
1353        format!("{} {{ {} }}", self.name, format_types(&self.members))
1354    }
1355}
1356
1357/// Struct that represents a enum type.
1358#[derive(Debug, Clone)]
1359pub struct EnumerationTypeValue<R: Reader<Offset = usize>> {
1360    /// The name of the Enum.
1361    pub name: String,
1362
1363    /// The name of the Enum.
1364    pub variant: EvaluatorValue<R>,
1365
1366    /// The value of the enum.
1367    pub enumerators: Vec<EnumeratorValue>,
1368}
1369
1370impl<R: Reader<Offset = usize>> fmt::Display for EnumerationTypeValue<R> {
1371    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1372        write!(f, "{}::{}", self.name, self.variant)
1373    }
1374}
1375
1376impl<R: Reader<Offset = usize>> EnumerationTypeValue<R> {
1377    /// Get the type of the enum as a `String`.
1378    pub fn get_type(&self) -> String {
1379        format!("{}::{}", self.name, self.variant.get_type())
1380    }
1381}
1382
1383/// Struct that represents a union type.
1384#[derive(Debug, Clone)]
1385pub struct UnionTypeValue<R: Reader<Offset = usize>> {
1386    /// The name of the union type
1387    pub name: String,
1388
1389    /// The values of the union type.
1390    pub members: Vec<EvaluatorValue<R>>,
1391}
1392
1393impl<R: Reader<Offset = usize>> fmt::Display for UnionTypeValue<R> {
1394    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1395        write!(f, "{} ( {} )", self.name, format_values(&self.members))
1396    }
1397}
1398
1399impl<R: Reader<Offset = usize>> UnionTypeValue<R> {
1400    /// Get the type of the union as a `String`.
1401    pub fn get_type(&self) -> String {
1402        format!("{} ( {} )", self.name, format_types(&self.members))
1403    }
1404}
1405
1406/// Struct that represents a attribute type.
1407#[derive(Debug, Clone)]
1408pub struct MemberValue<R: Reader<Offset = usize>> {
1409    /// The name of the attribute.
1410    pub name: Option<String>,
1411
1412    /// The value of the attribute.
1413    pub value: EvaluatorValue<R>,
1414}
1415
1416impl<R: Reader<Offset = usize>> fmt::Display for MemberValue<R> {
1417    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1418        match &self.name {
1419            Some(name) => write!(f, "{}::{}", name, self.value),
1420            None => write!(f, "{}", self.value),
1421        }
1422    }
1423}
1424
1425impl<R: Reader<Offset = usize>> MemberValue<R> {
1426    /// Get the type of the attribute as a `String`.
1427    pub fn get_type(&self) -> String {
1428        match &self.name {
1429            Some(name) => format!("{}::{}", name, self.value.get_type()),
1430            None => self.value.get_type(),
1431        }
1432    }
1433}
1434
1435/// Struct that represents a pointer type.
1436#[derive(Debug, Clone)]
1437pub struct PointerTypeValue<R: Reader<Offset = usize>> {
1438    /// The name of the pointer type.
1439    pub name: Option<String>,
1440
1441    /// The value of the attribute.
1442    pub address: EvaluatorValue<R>,
1443
1444    /// The value stored at the pointed location
1445    pub value: EvaluatorValue<R>,
1446    // DW_TAG_pointer_type contains:
1447    // * DW_AT_type
1448    // * DW_AT_name
1449    // * DW_AT_address_class
1450}
1451
1452impl<R: Reader<Offset = usize>> fmt::Display for PointerTypeValue<R> {
1453    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1454        match &self.name {
1455            Some(name) => write!(f, "{}::{}", name, self.value),
1456            None => write!(f, "{}", self.value),
1457        }
1458    }
1459}
1460
1461impl<R: Reader<Offset = usize>> PointerTypeValue<R> {
1462    /// Get the type of the pointer type as a `String`.
1463    pub fn get_type(&self) -> String {
1464        match &self.name {
1465            Some(name) => format!("{}::{}", name, self.value.get_type()),
1466            None => self.value.get_type(),
1467        }
1468    }
1469}
1470
1471/// Struct that represents a enumerator.
1472#[derive(Debug, Clone)]
1473pub struct EnumeratorValue {
1474    /// The name of the enumerator.
1475    pub name: Option<String>,
1476
1477    /// The value of the attribute.
1478    pub const_value: u64,
1479    // DW_TAG_enumerator contains:
1480    // * DW_AT_name
1481    // * DW_AT_const_value
1482}
1483
1484impl fmt::Display for EnumeratorValue {
1485    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1486        match &self.name {
1487            Some(name) => write!(f, "{}::{}", name, self.const_value),
1488            None => write!(f, "{}", self.const_value),
1489        }
1490    }
1491}
1492
1493impl EnumeratorValue {
1494    /// Get the type of the enumerator as a `String`.
1495    pub fn get_type(&self) -> String {
1496        format!("{:?}", self.name)
1497    }
1498}
1499
1500/// Struct that represents a variant.
1501#[derive(Debug, Clone)]
1502pub struct VariantValue<R: Reader<Offset = usize>> {
1503    /// The discr value
1504    pub discr_value: Option<u64>,
1505
1506    /// The child value
1507    pub child: MemberValue<R>,
1508    // DW_TAG_variant contains:
1509    // * DW_AT_discr_value
1510    // * A child with tag DW_TAG_member
1511}
1512
1513impl<R: Reader<Offset = usize>> fmt::Display for VariantValue<R> {
1514    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1515        match &self.discr_value {
1516            Some(discr) => write!(f, "{}::{}", discr, self.child),
1517            None => write!(f, "{}", self.child),
1518        }
1519    }
1520}
1521
1522impl<R: Reader<Offset = usize>> VariantValue<R> {
1523    /// Get the type of the variant as a `String`.
1524    pub fn get_type(&self) -> String {
1525        match &self.discr_value {
1526            Some(discr) => format!("{} {}", discr, self.child.get_type()),
1527            None => self.child.get_type(),
1528        }
1529    }
1530}
1531
1532/// Struct that represents a variant_part.
1533#[derive(Debug, Clone)]
1534pub struct VariantPartValue<R: Reader<Offset = usize>> {
1535    /// The variant value
1536    pub variant: Option<MemberValue<R>>,
1537
1538    /// The variants
1539    pub variants: Vec<VariantValue<R>>,
1540    // DW_TAG_variant_part contains:
1541    // * DW_AT_discr_value
1542    // * A child with tag DW_TAG_member
1543    // * Children with tag DW_TAG_variant
1544}
1545
1546impl<R: Reader<Offset = usize>> fmt::Display for VariantPartValue<R> {
1547    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1548        let mut variants = "{".to_string();
1549        for v in &self.variants {
1550            variants = format!("{} {},", variants, v);
1551        }
1552        variants = format!("{} {}", variants, "}");
1553        match &self.variant {
1554            // TODO: Improve
1555            Some(variant) => write!(f, "< variant: {} >, {}", variant, variants),
1556            None => write!(f, "{}", variants),
1557        }
1558    }
1559}
1560
1561impl<R: Reader<Offset = usize>> VariantPartValue<R> {
1562    /// Get the type of the variant_part as a `String`.
1563    pub fn get_type(&self) -> String {
1564        // TODO: Improve
1565        match &self.variant {
1566            Some(variant) => variant.to_string(),
1567            None => "".to_owned(),
1568        }
1569    }
1570}
1571
1572/// Struct that represents a variant.
1573#[derive(Debug, Clone)]
1574pub struct SubrangeTypeValue {
1575    /// The lowser bound
1576    pub lower_bound: Option<u64>,
1577
1578    /// The count
1579    pub count: Option<u64>,
1580
1581    /// The count value but evaluated. // TODO: Combine count and number to one attriute.
1582    pub base_type_value: Option<(BaseTypeValue, ValueInformation)>,
1583    // DW_TAG_variant contains:
1584    // * DW_AT_type
1585    // * DW_AT_lower_bound
1586    // * DW_AT_count
1587}
1588
1589impl fmt::Display for SubrangeTypeValue {
1590    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1591        match self.get_count() {
1592            Ok(Some(count)) => write!(f, "{}", count),
1593            _ => write!(f, ""),
1594        }
1595    }
1596}
1597
1598impl SubrangeTypeValue {
1599    /// Get the type of the subrange_type as a `String`.
1600    pub fn get_type(&self) -> String {
1601        match &self.base_type_value {
1602            Some((val, _)) => val.get_type(),
1603            None => "u64".to_string(),
1604        }
1605    }
1606
1607    pub fn get_count(&self) -> Result<Option<u64>> {
1608        match self.count {
1609            Some(val) => Ok(Some(val)),
1610            None => match &self.base_type_value {
1611                Some((btv, _)) => Ok(Some(get_udata(btv.clone())?)),
1612                None => Ok(None),
1613            },
1614        }
1615    }
1616}
1617
1618/// A enum representing the base types in DWARF.
1619#[derive(Debug, Clone)]
1620pub enum BaseTypeValue {
1621    /// generic value.
1622    Generic(u64),
1623
1624    /// 32 bit address.
1625    Address32(u32),
1626
1627    /// 32 bit register value.
1628    Reg32(u32),
1629
1630    /// boolean
1631    Bool(bool),
1632
1633    /// 8 bit unsigned integer.
1634    U8(u8),
1635
1636    /// 16 bit unsigned integer.
1637    U16(u16),
1638
1639    /// 32 bit unsigned integer.
1640    U32(u32),
1641
1642    /// 64 bit unsigned integer.
1643    U64(u64),
1644
1645    /// 8 bit signed integer.
1646    I8(i8),
1647
1648    /// 16 bit signed integer.
1649    I16(i16),
1650
1651    /// 32 bit signed integer.
1652    I32(i32),
1653
1654    /// 64 bit signed integer.
1655    I64(i64),
1656
1657    /// 32 bit float.
1658    F32(f32),
1659
1660    /// 64 bit float.
1661    F64(f64),
1662}
1663
1664impl fmt::Display for BaseTypeValue {
1665    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1666        match self {
1667            BaseTypeValue::Bool(val) => write!(f, "{}", val),
1668            BaseTypeValue::Generic(val) => write!(f, "{}", val),
1669            BaseTypeValue::I8(val) => write!(f, "{}", val),
1670            BaseTypeValue::U8(val) => write!(f, "{}", val),
1671            BaseTypeValue::I16(val) => write!(f, "{}", val),
1672            BaseTypeValue::U16(val) => write!(f, "{}", val),
1673            BaseTypeValue::I32(val) => write!(f, "{}", val),
1674            BaseTypeValue::U32(val) => write!(f, "{}", val),
1675            BaseTypeValue::I64(val) => write!(f, "{}", val),
1676            BaseTypeValue::U64(val) => write!(f, "{}", val),
1677            BaseTypeValue::F32(val) => write!(f, "{}", val),
1678            BaseTypeValue::F64(val) => write!(f, "{}", val),
1679            BaseTypeValue::Address32(val) => write!(f, "'Address' {:#10x}", val),
1680            BaseTypeValue::Reg32(val) => write!(f, "0x{:x}", val),
1681        }
1682    }
1683}
1684
1685impl BaseTypeValue {
1686    /// Parse a DWARF base type.
1687    ///
1688    /// Description:
1689    ///
1690    /// * `data` - The value in bytes.
1691    /// * `encoding` - The DWARF encoding of the value.
1692    ///
1693    /// Will parse the given bytes into the encoding type.
1694    /// The size of the given `data` parameter will be used when parsing.
1695    pub fn parse_base_type(data: Vec<u8>, encoding: DwAte) -> Result<BaseTypeValue> {
1696        if data.is_empty() {
1697            return Err(anyhow!("Expected data to be larger then 0"));
1698        }
1699
1700        // TODO: Fix so not any data size can be sent into this function.
1701        Ok(match (encoding, data.len()) {
1702            // Source: DWARF 4 page 168-169 and 77
1703            (DwAte(1), 4) => BaseTypeValue::Address32(u32::from_le_bytes(match data.try_into() {
1704                Ok(val) => val,
1705                Err(err) => {
1706                    error!("{:?}", err);
1707                    return Err(anyhow!("{:?}", err));
1708                }
1709            })), // DW_ATE_address = 1 // TODO: Different size addresses?
1710            (DwAte(2), 1) => BaseTypeValue::Bool(
1711                (u8::from_le_bytes(match data.try_into() {
1712                    Ok(val) => val,
1713                    Err(err) => {
1714                        error!("{:?}", err);
1715                        return Err(anyhow!("{:?}", err));
1716                    }
1717                })) == 1,
1718            ), // DW_ATE_boolean = 2 // TODO: Use modulus?
1719            (DwAte(2), 2) => BaseTypeValue::Bool(
1720                (u16::from_le_bytes(match data.try_into() {
1721                    Ok(val) => val,
1722                    Err(err) => {
1723                        error!("{:?}", err);
1724                        return Err(anyhow!("{:?}", err));
1725                    }
1726                })) == 1,
1727            ), // DW_ATE_boolean = 2 // TODO: Use modulus?
1728            (DwAte(2), 4) => BaseTypeValue::Bool(
1729                (u32::from_le_bytes(match data.try_into() {
1730                    Ok(val) => val,
1731                    Err(err) => {
1732                        error!("{:?}", err);
1733                        return Err(anyhow!("{:?}", err));
1734                    }
1735                })) == 1,
1736            ), // DW_ATE_boolean = 2 // TODO: Use modulus?
1737
1738            //        (DwAte(3), _) => ,   // DW_ATE_complex_float = 3 // NOTE: Seems like a C++ thing
1739            (DwAte(4), 4) => BaseTypeValue::F32(f32::from_le_bytes(match data.try_into() {
1740                Ok(val) => val,
1741                Err(err) => {
1742                    error!("{:?}", err);
1743                    return Err(anyhow!("{:?}", err));
1744                }
1745            })), // DW_ATE_float = 4
1746            (DwAte(4), 8) => BaseTypeValue::F64(f64::from_le_bytes(match data.try_into() {
1747                Ok(val) => val,
1748                Err(err) => {
1749                    error!("{:?}", err);
1750                    return Err(anyhow!("{:?}", err));
1751                }
1752            })), // DW_ATE_float = 4
1753
1754            (DwAte(5), 1) => BaseTypeValue::I8(i8::from_le_bytes(match data.try_into() {
1755                Ok(val) => val,
1756                Err(err) => {
1757                    error!("{:?}", err);
1758                    return Err(anyhow!("{:?}", err));
1759                }
1760            })), // (DW_ATE_signed = 5, 8)
1761            (DwAte(5), 2) => BaseTypeValue::I16(i16::from_le_bytes(match data.try_into() {
1762                Ok(val) => val,
1763                Err(err) => {
1764                    error!("{:?}", err);
1765                    return Err(anyhow!("{:?}", err));
1766                }
1767            })), // (DW_ATE_signed = 5, 16)
1768            (DwAte(5), 4) => BaseTypeValue::I32(i32::from_le_bytes(match data.try_into() {
1769                Ok(val) => val,
1770                Err(err) => {
1771                    error!("{:?}", err);
1772                    return Err(anyhow!("{:?}", err));
1773                }
1774            })), // (DW_ATE_signed = 5, 32)
1775            (DwAte(5), 8) => BaseTypeValue::I64(i64::from_le_bytes(match data.try_into() {
1776                Ok(val) => val,
1777                Err(err) => {
1778                    error!("{:?}", err);
1779                    return Err(anyhow!("{:?}", err));
1780                }
1781            })), // (DW_ATE_signed = 5, 64)
1782
1783            //        (DwAte(6), _) => ,     // DW_ATE_signed_char = 6 // TODO: Add type
1784            (DwAte(7), 1) => BaseTypeValue::U8(u8::from_le_bytes(match data.try_into() {
1785                Ok(val) => val,
1786                Err(err) => {
1787                    error!("{:?}", err);
1788                    return Err(anyhow!("{:?}", err));
1789                }
1790            })), // (DW_ATE_unsigned = 7, 8)
1791            (DwAte(7), 2) => BaseTypeValue::U16(u16::from_le_bytes(match data.try_into() {
1792                Ok(val) => val,
1793                Err(err) => {
1794                    error!("{:?}", err);
1795                    return Err(anyhow!("{:?}", err));
1796                }
1797            })), // (DW_ATE_unsigned = 7, 16)
1798            (DwAte(7), 4) => BaseTypeValue::U32(u32::from_le_bytes(match data.try_into() {
1799                Ok(val) => val,
1800                Err(err) => {
1801                    error!("{:?}", err);
1802                    return Err(anyhow!("{:?}", err));
1803                }
1804            })), // (DW_ATE_unsigned = 7, 32)
1805            (DwAte(7), 8) => BaseTypeValue::U64(u64::from_le_bytes(match data.try_into() {
1806                Ok(val) => val,
1807                Err(err) => {
1808                    error!("{:?}", err);
1809                    return Err(anyhow!("{:?}", err));
1810                }
1811            })), // (DW_ATE_unsigned = 7, 64)
1812            _ => {
1813                error!("encoding {}, byte_size: {}", encoding, data.len());
1814                return Err(anyhow!("encoding {}, byte_size: {}", encoding, data.len()));
1815            }
1816        })
1817    }
1818
1819    /// Get the base type as a `String` with the Rust names.
1820    pub fn get_type(&self) -> String {
1821        match self {
1822            BaseTypeValue::Bool(_) => "bool".to_owned(),
1823            BaseTypeValue::Generic(_) => "<unknown>".to_owned(),
1824            BaseTypeValue::I8(_) => "i8".to_owned(),
1825            BaseTypeValue::U8(_) => "u8".to_owned(),
1826            BaseTypeValue::I16(_) => "i16".to_owned(),
1827            BaseTypeValue::U16(_) => "u16".to_owned(),
1828            BaseTypeValue::I32(_) => "i32".to_owned(),
1829            BaseTypeValue::U32(_) => "u32".to_owned(),
1830            BaseTypeValue::I64(_) => "i64".to_owned(),
1831            BaseTypeValue::U64(_) => "u64".to_owned(),
1832            BaseTypeValue::F32(_) => "f32".to_owned(),
1833            BaseTypeValue::F64(_) => "f63".to_owned(),
1834            BaseTypeValue::Address32(_) => "<32 bit address>".to_owned(),
1835            BaseTypeValue::Reg32(_) => "<32 bit register value>".to_owned(),
1836        }
1837    }
1838}
1839
1840/// Convert a `BaseTypeValue` to a `gimli::Value`.
1841///
1842/// Description:
1843///
1844/// * `value` - The value that will be converted into a `gimli::Value` stuct.
1845pub fn convert_to_gimli_value(value: BaseTypeValue) -> gimli::Value {
1846    match value {
1847        BaseTypeValue::Bool(val) => gimli::Value::Generic(match val {
1848            true => 1,
1849            false => 0,
1850        }),
1851        BaseTypeValue::Generic(val) => gimli::Value::Generic(val),
1852        BaseTypeValue::I8(val) => gimli::Value::I8(val),
1853        BaseTypeValue::U8(val) => gimli::Value::U8(val),
1854        BaseTypeValue::I16(val) => gimli::Value::I16(val),
1855        BaseTypeValue::U16(val) => gimli::Value::U16(val),
1856        BaseTypeValue::I32(val) => gimli::Value::I32(val),
1857        BaseTypeValue::U32(val) => gimli::Value::U32(val),
1858        BaseTypeValue::I64(val) => gimli::Value::I64(val),
1859        BaseTypeValue::U64(val) => gimli::Value::U64(val),
1860        BaseTypeValue::F32(val) => gimli::Value::F32(val),
1861        BaseTypeValue::F64(val) => gimli::Value::F64(val),
1862        BaseTypeValue::Address32(val) => gimli::Value::Generic(val as u64),
1863        BaseTypeValue::Reg32(val) => gimli::Value::U32(val),
1864    }
1865}
1866
1867/// Convert a `gimli::Value` to a `BaseTypeValue`.
1868///
1869/// Description:
1870///
1871/// * `value` - The value that will be converted into a `BaseTypeValue` stuct.
1872pub fn convert_from_gimli_value(value: gimli::Value) -> BaseTypeValue {
1873    match value {
1874        gimli::Value::Generic(val) => BaseTypeValue::Generic(val),
1875        gimli::Value::I8(val) => BaseTypeValue::I8(val),
1876        gimli::Value::U8(val) => BaseTypeValue::U8(val),
1877        gimli::Value::I16(val) => BaseTypeValue::I16(val),
1878        gimli::Value::U16(val) => BaseTypeValue::U16(val),
1879        gimli::Value::I32(val) => BaseTypeValue::I32(val),
1880        gimli::Value::U32(val) => BaseTypeValue::U32(val),
1881        gimli::Value::I64(val) => BaseTypeValue::I64(val),
1882        gimli::Value::U64(val) => BaseTypeValue::U64(val),
1883        gimli::Value::F32(val) => BaseTypeValue::F32(val),
1884        gimli::Value::F64(val) => BaseTypeValue::F64(val),
1885    }
1886}
1887
1888/// Will retrieve the type DIE and compilation unit for a given die.
1889///
1890/// Description:
1891///
1892/// * `dwarf` - A reference to gimli-rs `Dwarf` struct.
1893/// * `unit` - A compilation unit which contains the given DIE.
1894/// * `die` - The DIE which contain a reference to the type DIE.
1895fn get_type_info<R: Reader<Offset = usize>>(
1896    dwarf: &gimli::Dwarf<R>,
1897    unit: &gimli::Unit<R>,
1898    die: &gimli::DebuggingInformationEntry<'_, '_, R>,
1899) -> Result<(gimli::Unit<R>, gimli::UnitOffset)> {
1900    let (unit_offset, die_offset) = match attributes::type_attribute(dwarf, unit, die)? {
1901        Some(val) => val,
1902        None => {
1903            error!("Die doesn't have the required DW_AT_type attribute");
1904            return Err(anyhow!(
1905                "Die doesn't have the required DW_AT_type attribute"
1906            ));
1907        }
1908    };
1909    let unit = match unit_offset {
1910        gimli::UnitSectionOffset::DebugInfoOffset(offset) => {
1911            let header = dwarf.debug_info.header_from_offset(offset)?;
1912            dwarf.unit(header)?
1913        }
1914        gimli::UnitSectionOffset::DebugTypesOffset(_offset) => {
1915            let mut iter = dwarf.debug_types.units();
1916            let mut result = None;
1917            while let Some(header) = iter.next()? {
1918                if header.offset() == unit_offset {
1919                    result = Some(dwarf.unit(header)?);
1920                    break;
1921                }
1922            }
1923            match result {
1924                Some(val) => val,
1925                None => {
1926                    error!("Could not get unit from unit offset");
1927                    return Err(anyhow!("Could not get unit from unit offset"));
1928                }
1929            }
1930        }
1931    };
1932
1933    Ok((unit, die_offset))
1934}
1935
1936/// Will check that the address is correctly aligned.
1937///
1938/// Description:
1939///
1940/// * `die` - The type DIE to check alignment for.
1941/// * `data_offset` - The memory address offset.
1942/// * `pieces` - A list of pieces containing the location and size information.
1943fn check_alignment<R: Reader<Offset = usize>>(
1944    die: &gimli::DebuggingInformationEntry<'_, '_, R>,
1945    mut data_offset: u64,
1946    pieces: &Vec<MyPiece<R>>,
1947) -> Result<()> {
1948    match attributes::alignment_attribute(die)? {
1949        Some(alignment) => {
1950            if pieces.is_empty() {
1951                return Ok(());
1952            }
1953
1954            if pieces.is_empty() {
1955                data_offset = 0;
1956            }
1957
1958            if let Location::Address { address } = pieces[0].piece.location {
1959                let mut addr = address + (data_offset / 4) * 4;
1960                addr -= addr % 4; // TODO: Is this correct?
1961
1962                if addr % alignment != 0 {
1963                    error!("Address not aligned");
1964                    return Err(anyhow!("Address not aligned"));
1965                }
1966            };
1967        }
1968        None => (),
1969    };
1970
1971    Ok(())
1972}
1973
1974/// Will retrieve the list of children DIEs for a DIE.
1975///
1976/// Description:
1977///
1978/// * `unit` - The compilation unit which contains the given DIE.
1979/// * `die` - The DIE to find the children for.
1980fn get_children<R: Reader<Offset = usize>>(
1981    unit: &gimli::Unit<R>,
1982    die: &gimli::DebuggingInformationEntry<'_, '_, R>,
1983) -> Result<Vec<gimli::UnitOffset>> {
1984    let mut result = Vec::new();
1985    let mut tree = unit.entries_tree(Some(die.offset()))?;
1986    let node = tree.root()?;
1987
1988    let mut children = node.children();
1989    while let Some(child) = children.next()? {
1990        result.push(child.entry().offset());
1991    }
1992
1993    Ok(result)
1994}
1995
1996/// Will remove the unnecessary bytes.
1997///
1998/// Description:
1999///
2000/// * `bytes` - The bytes to be trimmed of unnecessary bytes.
2001/// * `piece` - The piece the given bytes is evaluated from.
2002/// * `byte_size` - The byte size of the resulting trim.
2003///
2004/// Some pieces contain more bytes then the type describes.
2005/// Thus this function removes those unused bytes.
2006fn trim_piece_bytes<R: Reader<Offset = usize>>(
2007    mut bytes: Vec<u8>,
2008    piece: &Piece<R>,
2009    byte_size: usize,
2010) -> Vec<u8> {
2011    let piece_byte_size = match piece.size_in_bits {
2012        Some(size) => ((size + 8 - 1) / 8) as usize,
2013        None => byte_size,
2014    };
2015
2016    let piece_byte_offset = match piece.bit_offset {
2017        Some(offset) => {
2018            //if offset % 8 == 0 {
2019            //    error!("Expected the offset to be in bytes, got {} bits", offset);
2020            //    return Err(anyhow!("Expected the offset to be in bytes, got {} bits", offset));
2021            //}
2022            ((offset + 8 - 1) / 8) as usize
2023        }
2024        None => 0,
2025    };
2026
2027    for _ in 0..piece_byte_offset {
2028        bytes.pop();
2029    }
2030
2031    while bytes.len() > piece_byte_size {
2032        // TODO: Check that this follows the ABI.
2033        bytes.remove(0);
2034    }
2035
2036    bytes
2037}
2038
2039/// Contains the unparsed value and the location of it.
2040#[derive(Debug, Clone)]
2041pub struct ValueInformation {
2042    pub raw: Option<Vec<u8>>, // byte size and raw value
2043    pub pieces: Vec<ValuePiece>,
2044}
2045
2046impl ValueInformation {
2047    /// Create a new `ValueInformation` struct
2048    ///
2049    /// Description:
2050    ///
2051    /// * `raw` - The unparsed value.
2052    /// * `pieces` - The location of the value.
2053    pub fn new(raw: Option<Vec<u8>>, pieces: Vec<ValuePiece>) -> ValueInformation {
2054        ValueInformation { raw, pieces }
2055    }
2056}
2057
2058/// A struct that describes the size and location of a value.
2059#[derive(Debug, Clone)]
2060pub enum ValuePiece {
2061    /// Contains which register the value is located and the size of it.
2062    Register {
2063        /// The register the value is stored.
2064        register: u16,
2065
2066        /// The size of the value.
2067        byte_size: usize,
2068    },
2069
2070    /// Contains which address the value is located and the size of it.
2071    Memory {
2072        /// The address the value is stored.
2073        address: u32,
2074
2075        /// The size of the value.
2076        byte_size: usize,
2077    },
2078
2079    /// Contains the value stored on the DWARF stack.
2080    Dwarf {
2081        /// The value stored on the DWARF stack.
2082        /// If it is `None` then the value is optimized out.
2083        value: Option<gimli::Value>,
2084    },
2085
2086    /// TODO
2087    Bytes { bytes: Vec<u8> },
2088}