2 use indexmap
::IndexSet
;
3 use std
::ops
::{Deref, DerefMut}
;
5 use crate::common
::{DebugAbbrevOffset, SectionId}
;
7 use crate::write
::{Result, Section, Writer}
;
9 /// A table of abbreviations that will be stored in a `.debug_abbrev` section.
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 #[derive(Debug, Default)]
15 pub(crate) struct AbbreviationTable
{
16 abbrevs
: IndexSet
<Abbreviation
>,
19 impl AbbreviationTable
{
20 /// Add an abbreviation to the table and return its code.
21 pub fn add(&mut self, abbrev
: Abbreviation
) -> u64 {
22 let (code
, _
) = self.abbrevs
.insert_full(abbrev
);
23 // Code must be non-zero
27 /// Write the abbreviation table to the `.debug_abbrev` section.
28 pub fn write
<W
: Writer
>(&self, w
: &mut DebugAbbrev
<W
>) -> Result
<()> {
29 for (code
, abbrev
) in self.abbrevs
.iter().enumerate() {
30 w
.write_uleb128((code
+ 1) as u64)?
;
33 // Null abbreviation code
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 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
41 pub(crate) struct Abbreviation
{
42 tag
: constants
::DwTag
,
44 attributes
: Vec
<AttributeSpecification
>,
48 /// Construct a new `Abbreviation`.
51 tag
: constants
::DwTag
,
53 attributes
: Vec
<AttributeSpecification
>,
62 /// Write the abbreviation to the `.debug_abbrev` section.
63 pub fn write
<W
: Writer
>(&self, w
: &mut DebugAbbrev
<W
>) -> Result
<()> {
64 w
.write_uleb128(self.tag
.0.into
())?
;
65 w
.write_u8(if self.has_children
{
66 constants
::DW_CHILDREN_yes
.0
68 constants
::DW_CHILDREN_no
.0
70 for attr
in &self.attributes
{
79 /// The description of an attribute in an abbreviated type.
80 // TODO: support implicit const
81 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
82 pub(crate) struct AttributeSpecification
{
83 name
: constants
::DwAt
,
84 form
: constants
::DwForm
,
87 impl AttributeSpecification
{
88 /// Construct a new `AttributeSpecification`.
90 pub fn new(name
: constants
::DwAt
, form
: constants
::DwForm
) -> AttributeSpecification
{
91 AttributeSpecification { name, form }
94 /// Write the attribute specification to the `.debug_abbrev` section.
96 pub fn write
<W
: Writer
>(&self, w
: &mut DebugAbbrev
<W
>) -> Result
<()> {
97 w
.write_uleb128(self.name
.0.into
())?
;
98 w
.write_uleb128(self.form
.0.into
())
105 "A writable `.debug_abbrev` section."
109 #[cfg(feature = "read")]
112 use crate::constants
;
114 use crate::write
::EndianVec
;
115 use crate::LittleEndian
;
118 fn test_abbreviation_table() {
119 let mut abbrevs
= AbbreviationTable
::default();
120 let abbrev1
= Abbreviation
::new(
121 constants
::DW_TAG_subprogram
,
123 vec
![AttributeSpecification
::new(
124 constants
::DW_AT_name
,
125 constants
::DW_FORM_string
,
128 let abbrev2
= Abbreviation
::new(
129 constants
::DW_TAG_compile_unit
,
132 AttributeSpecification
::new(constants
::DW_AT_producer
, constants
::DW_FORM_strp
),
133 AttributeSpecification
::new(constants
::DW_AT_language
, constants
::DW_FORM_data2
),
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
);
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));
149 let read_debug_abbrev
= read
::DebugAbbrev
::new(debug_abbrev
.slice(), LittleEndian
);
150 let read_abbrevs
= read_debug_abbrev
151 .abbreviations(debug_abbrev_offset
)
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());
159 abbrev1
.attributes
[0].name
,
160 read_abbrev1
.attributes()[0].name()
163 abbrev1
.attributes
[0].form
,
164 read_abbrev1
.attributes()[0].form()
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());
172 abbrev2
.attributes
[0].name
,
173 read_abbrev2
.attributes()[0].name()
176 abbrev2
.attributes
[0].form
,
177 read_abbrev2
.attributes()[0].form()
180 abbrev2
.attributes
[1].name
,
181 read_abbrev2
.attributes()[1].name()
184 abbrev2
.attributes
[1].form
,
185 read_abbrev2
.attributes()[1].form()