Coverage Report

Created: 2023-04-25 07:07

/rust/registry/src/index.crates.io-6f17d22bba15001f/gimli-0.27.0/src/write/abbrev.rs
Line
Count
Source (jump to first uncovered line)
1
use alloc::vec::Vec;
2
use indexmap::IndexSet;
3
use std::ops::{Deref, DerefMut};
4
5
use crate::common::{DebugAbbrevOffset, SectionId};
6
use crate::constants;
7
use crate::write::{Result, Section, Writer};
8
9
/// A table of abbreviations that will be stored in a `.debug_abbrev` section.
10
// Requirements:
11
// - values are `Abbreviation`
12
// - insertion returns an abbreviation code for use in writing a DIE
13
// - inserting a duplicate returns the code of the existing value
14
0
#[derive(Debug, Default)]
Unexecuted instantiation: <gimli::write::abbrev::AbbreviationTable as core::default::Default>::default
Unexecuted instantiation: <gimli::write::abbrev::AbbreviationTable as core::default::Default>::default
15
pub(crate) struct AbbreviationTable {
16
    abbrevs: IndexSet<Abbreviation>,
17
}
18
19
impl AbbreviationTable {
20
    /// Add an abbreviation to the table and return its code.
21
0
    pub fn add(&mut self, abbrev: Abbreviation) -> u64 {
22
0
        let (code, _) = self.abbrevs.insert_full(abbrev);
23
0
        // Code must be non-zero
24
0
        (code + 1) as u64
25
0
    }
26
27
    /// Write the abbreviation table to the `.debug_abbrev` section.
28
0
    pub fn write<W: Writer>(&self, w: &mut DebugAbbrev<W>) -> Result<()> {
29
0
        for (code, abbrev) in self.abbrevs.iter().enumerate() {
30
0
            w.write_uleb128((code + 1) as u64)?;
31
0
            abbrev.write(w)?;
32
        }
33
        // Null abbreviation code
34
0
        w.write_u8(0)
35
0
    }
Unexecuted instantiation: <gimli::write::abbrev::AbbreviationTable>::write::<wasmtime_cranelift::debug::write_debuginfo::WriterRelocate>
Unexecuted instantiation: <gimli::write::abbrev::AbbreviationTable>::write::<_>
36
}
37
38
/// An abbreviation describes the shape of a `DebuggingInformationEntry`'s type:
39
/// its tag type, whether it has children, and its set of attributes.
40
0
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
41
pub(crate) struct Abbreviation {
42
    tag: constants::DwTag,
43
    has_children: bool,
44
    attributes: Vec<AttributeSpecification>,
45
}
46
47
impl Abbreviation {
48
    /// Construct a new `Abbreviation`.
49
    #[inline]
50
0
    pub fn new(
51
0
        tag: constants::DwTag,
52
0
        has_children: bool,
53
0
        attributes: Vec<AttributeSpecification>,
54
0
    ) -> Abbreviation {
55
0
        Abbreviation {
56
0
            tag,
57
0
            has_children,
58
0
            attributes,
59
0
        }
60
0
    }
61
62
    /// Write the abbreviation to the `.debug_abbrev` section.
63
    pub fn write<W: Writer>(&self, w: &mut DebugAbbrev<W>) -> Result<()> {
64
0
        w.write_uleb128(self.tag.0.into())?;
65
0
        w.write_u8(if self.has_children {
66
0
            constants::DW_CHILDREN_yes.0
67
        } else {
68
0
            constants::DW_CHILDREN_no.0
69
0
        })?;
70
0
        for attr in &self.attributes {
71
0
            attr.write(w)?;
72
        }
73
        // Null name and form
74
0
        w.write_u8(0)?;
75
0
        w.write_u8(0)
76
0
    }
Unexecuted instantiation: <gimli::write::abbrev::Abbreviation>::write::<wasmtime_cranelift::debug::write_debuginfo::WriterRelocate>
Unexecuted instantiation: <gimli::write::abbrev::Abbreviation>::write::<_>
77
}
78
79
/// The description of an attribute in an abbreviated type.
80
// TODO: support implicit const
81
0
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
82
pub(crate) struct AttributeSpecification {
83
    name: constants::DwAt,
84
    form: constants::DwForm,
85
}
86
87
impl AttributeSpecification {
88
    /// Construct a new `AttributeSpecification`.
89
    #[inline]
90
0
    pub fn new(name: constants::DwAt, form: constants::DwForm) -> AttributeSpecification {
91
0
        AttributeSpecification { name, form }
92
0
    }
93
94
    /// Write the attribute specification to the `.debug_abbrev` section.
95
    #[inline]
96
    pub fn write<W: Writer>(&self, w: &mut DebugAbbrev<W>) -> Result<()> {
97
0
        w.write_uleb128(self.name.0.into())?;
98
0
        w.write_uleb128(self.form.0.into())
99
0
    }
Unexecuted instantiation: <gimli::write::abbrev::AttributeSpecification>::write::<wasmtime_cranelift::debug::write_debuginfo::WriterRelocate>
Unexecuted instantiation: <gimli::write::abbrev::AttributeSpecification>::write::<_>
100
}
101
102
define_section!(
103
    DebugAbbrev,
104
    DebugAbbrevOffset,
105
    "A writable `.debug_abbrev` section."
106
);
107
108
#[cfg(test)]
109
#[cfg(feature = "read")]
110
mod tests {
111
    use super::*;
112
    use crate::constants;
113
    use crate::read;
114
    use crate::write::EndianVec;
115
    use crate::LittleEndian;
116
117
    #[test]
118
    fn test_abbreviation_table() {
119
        let mut abbrevs = AbbreviationTable::default();
120
        let abbrev1 = Abbreviation::new(
121
            constants::DW_TAG_subprogram,
122
            false,
123
            vec![AttributeSpecification::new(
124
                constants::DW_AT_name,
125
                constants::DW_FORM_string,
126
            )],
127
        );
128
        let abbrev2 = Abbreviation::new(
129
            constants::DW_TAG_compile_unit,
130
            true,
131
            vec![
132
                AttributeSpecification::new(constants::DW_AT_producer, constants::DW_FORM_strp),
133
                AttributeSpecification::new(constants::DW_AT_language, constants::DW_FORM_data2),
134
            ],
135
        );
136
        let code1 = abbrevs.add(abbrev1.clone());
137
        assert_eq!(code1, 1);
138
        let code2 = abbrevs.add(abbrev2.clone());
139
        assert_eq!(code2, 2);
140
        assert_eq!(abbrevs.add(abbrev1.clone()), code1);
141
        assert_eq!(abbrevs.add(abbrev2.clone()), code2);
142
143
        let mut debug_abbrev = DebugAbbrev::from(EndianVec::new(LittleEndian));
144
        let debug_abbrev_offset = debug_abbrev.offset();
145
        assert_eq!(debug_abbrev_offset, DebugAbbrevOffset(0));
146
        abbrevs.write(&mut debug_abbrev).unwrap();
147
        assert_eq!(debug_abbrev.offset(), DebugAbbrevOffset(17));
148
149
        let read_debug_abbrev = read::DebugAbbrev::new(debug_abbrev.slice(), LittleEndian);
150
        let read_abbrevs = read_debug_abbrev
151
            .abbreviations(debug_abbrev_offset)
152
            .unwrap();
153
154
        let read_abbrev1 = read_abbrevs.get(code1).unwrap();
155
        assert_eq!(abbrev1.tag, read_abbrev1.tag());
156
        assert_eq!(abbrev1.has_children, read_abbrev1.has_children());
157
        assert_eq!(abbrev1.attributes.len(), read_abbrev1.attributes().len());
158
        assert_eq!(
159
            abbrev1.attributes[0].name,
160
            read_abbrev1.attributes()[0].name()
161
        );
162
        assert_eq!(
163
            abbrev1.attributes[0].form,
164
            read_abbrev1.attributes()[0].form()
165
        );
166
167
        let read_abbrev2 = read_abbrevs.get(code2).unwrap();
168
        assert_eq!(abbrev2.tag, read_abbrev2.tag());
169
        assert_eq!(abbrev2.has_children, read_abbrev2.has_children());
170
        assert_eq!(abbrev2.attributes.len(), read_abbrev2.attributes().len());
171
        assert_eq!(
172
            abbrev2.attributes[0].name,
173
            read_abbrev2.attributes()[0].name()
174
        );
175
        assert_eq!(
176
            abbrev2.attributes[0].form,
177
            read_abbrev2.attributes()[0].form()
178
        );
179
        assert_eq!(
180
            abbrev2.attributes[1].name,
181
            read_abbrev2.attributes()[1].name()
182
        );
183
        assert_eq!(
184
            abbrev2.attributes[1].form,
185
            read_abbrev2.attributes()[1].form()
186
        );
187
    }
188
}