1use alloc::vec::Vec;
2use core::ops::{Deref, DerefMut};
3
4use crate::common::{DebugAbbrevOffset, SectionId};
5use crate::constants;
6use crate::write::{FnvIndexSet, Result, Section, Writer};
7
8#[derive(Debug, Default)]
14pub(crate) struct AbbreviationTable {
15 abbrevs: FnvIndexSet<Abbreviation>,
16}
17
18impl AbbreviationTable {
19 pub fn add(&mut self, abbrev: Abbreviation) -> u64 {
21 let (code, _) = self.abbrevs.insert_full(abbrev);
22 (code + 1) as u64
24 }
25
26 pub fn write<W: Writer>(&self, w: &mut DebugAbbrev<W>) -> Result<()> {
28 for (code, abbrev) in self.abbrevs.iter().enumerate() {
29 w.write_uleb128((code + 1) as u64)?;
30 abbrev.write(w)?;
31 }
32 w.write_u8(0)
34 }
35}
36
37#[derive(Debug, Clone, PartialEq, Eq, Hash)]
40pub(crate) struct Abbreviation {
41 tag: constants::DwTag,
42 has_children: bool,
43 attributes: Vec<AttributeSpecification>,
44}
45
46impl Abbreviation {
47 #[inline]
49 pub fn new(
50 tag: constants::DwTag,
51 has_children: bool,
52 attributes: Vec<AttributeSpecification>,
53 ) -> Abbreviation {
54 Abbreviation {
55 tag,
56 has_children,
57 attributes,
58 }
59 }
60
61 pub fn write<W: Writer>(&self, w: &mut DebugAbbrev<W>) -> Result<()> {
63 w.write_uleb128(self.tag.0.into())?;
64 w.write_u8(if self.has_children {
65 constants::DW_CHILDREN_yes.0
66 } else {
67 constants::DW_CHILDREN_no.0
68 })?;
69 for attr in &self.attributes {
70 attr.write(w)?;
71 }
72 w.write_u8(0)?;
74 w.write_u8(0)
75 }
76}
77
78#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
81pub(crate) struct AttributeSpecification {
82 name: constants::DwAt,
83 form: constants::DwForm,
84 implicit_const_value: i64,
85}
86
87impl AttributeSpecification {
88 #[inline]
90 pub fn new(
91 name: constants::DwAt,
92 form: constants::DwForm,
93 implicit_const_value: Option<i64>,
94 ) -> AttributeSpecification {
95 debug_assert_eq!(
96 form == constants::DW_FORM_implicit_const,
97 implicit_const_value.is_some()
98 );
99 AttributeSpecification {
100 name,
101 form,
102 implicit_const_value: implicit_const_value.unwrap_or(0),
103 }
104 }
105
106 #[inline]
108 pub fn write<W: Writer>(&self, w: &mut DebugAbbrev<W>) -> Result<()> {
109 w.write_uleb128(self.name.0.into())?;
110 w.write_uleb128(self.form.0.into())?;
111 if self.form == constants::DW_FORM_implicit_const {
112 w.write_sleb128(self.implicit_const_value)?;
113 }
114 Ok(())
115 }
116}
117
118define_section!(
119 DebugAbbrev,
120 DebugAbbrevOffset,
121 "A writable `.debug_abbrev` section."
122);
123
124#[cfg(test)]
125#[cfg(feature = "read")]
126mod tests {
127 use super::*;
128 use crate::LittleEndian;
129 use crate::constants;
130 use crate::read;
131 use crate::write::EndianVec;
132
133 #[test]
134 fn test_abbreviation_table() {
135 let mut abbrevs = AbbreviationTable::default();
136 let abbrev1 = Abbreviation::new(
137 constants::DW_TAG_subprogram,
138 false,
139 vec![AttributeSpecification::new(
140 constants::DW_AT_name,
141 constants::DW_FORM_string,
142 None,
143 )],
144 );
145 let abbrev2 = Abbreviation::new(
146 constants::DW_TAG_compile_unit,
147 true,
148 vec![
149 AttributeSpecification::new(
150 constants::DW_AT_producer,
151 constants::DW_FORM_strp,
152 None,
153 ),
154 AttributeSpecification::new(
155 constants::DW_AT_language,
156 constants::DW_FORM_data2,
157 None,
158 ),
159 ],
160 );
161 let code1 = abbrevs.add(abbrev1.clone());
162 assert_eq!(code1, 1);
163 let code2 = abbrevs.add(abbrev2.clone());
164 assert_eq!(code2, 2);
165 assert_eq!(abbrevs.add(abbrev1.clone()), code1);
166 assert_eq!(abbrevs.add(abbrev2.clone()), code2);
167
168 let mut debug_abbrev = DebugAbbrev::from(EndianVec::new(LittleEndian));
169 let debug_abbrev_offset = debug_abbrev.offset();
170 assert_eq!(debug_abbrev_offset, DebugAbbrevOffset(0));
171 abbrevs.write(&mut debug_abbrev).unwrap();
172 assert_eq!(debug_abbrev.offset(), DebugAbbrevOffset(17));
173
174 let read_debug_abbrev = read::DebugAbbrev::new(debug_abbrev.slice(), LittleEndian);
175 let read_abbrevs = read_debug_abbrev
176 .abbreviations(debug_abbrev_offset)
177 .unwrap();
178
179 let read_abbrev1 = read_abbrevs.get(code1).unwrap();
180 assert_eq!(abbrev1.tag, read_abbrev1.tag());
181 assert_eq!(abbrev1.has_children, read_abbrev1.has_children());
182 assert_eq!(abbrev1.attributes.len(), read_abbrev1.attributes().len());
183 assert_eq!(
184 abbrev1.attributes[0].name,
185 read_abbrev1.attributes()[0].name()
186 );
187 assert_eq!(
188 abbrev1.attributes[0].form,
189 read_abbrev1.attributes()[0].form()
190 );
191
192 let read_abbrev2 = read_abbrevs.get(code2).unwrap();
193 assert_eq!(abbrev2.tag, read_abbrev2.tag());
194 assert_eq!(abbrev2.has_children, read_abbrev2.has_children());
195 assert_eq!(abbrev2.attributes.len(), read_abbrev2.attributes().len());
196 assert_eq!(
197 abbrev2.attributes[0].name,
198 read_abbrev2.attributes()[0].name()
199 );
200 assert_eq!(
201 abbrev2.attributes[0].form,
202 read_abbrev2.attributes()[0].form()
203 );
204 assert_eq!(
205 abbrev2.attributes[1].name,
206 read_abbrev2.attributes()[1].name()
207 );
208 assert_eq!(
209 abbrev2.attributes[1].form,
210 read_abbrev2.attributes()[1].form()
211 );
212 }
213}