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 #[derive(Debug, 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. add(&mut self, abbrev: Abbreviation) -> u6421 pub fn add(&mut self, abbrev: Abbreviation) -> u64 { 22 let (code, _) = self.abbrevs.insert_full(abbrev); 23 // Code must be non-zero 24 (code + 1) as u64 25 } 26 27 /// Write the abbreviation table to the `.debug_abbrev` section. write<W: Writer>(&self, w: &mut DebugAbbrev<W>) -> Result<()>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)?; 31 abbrev.write(w)?; 32 } 33 // Null abbreviation code 34 w.write_u8(0) 35 } 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 #[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] new( tag: constants::DwTag, has_children: bool, attributes: Vec<AttributeSpecification>, ) -> Abbreviation50 pub fn new( 51 tag: constants::DwTag, 52 has_children: bool, 53 attributes: Vec<AttributeSpecification>, 54 ) -> Abbreviation { 55 Abbreviation { 56 tag, 57 has_children, 58 attributes, 59 } 60 } 61 62 /// Write the abbreviation to the `.debug_abbrev` section. write<W: Writer>(&self, w: &mut DebugAbbrev<W>) -> Result<()>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 67 } else { 68 constants::DW_CHILDREN_no.0 69 })?; 70 for attr in &self.attributes { 71 attr.write(w)?; 72 } 73 // Null name and form 74 w.write_u8(0)?; 75 w.write_u8(0) 76 } 77 } 78 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, 85 } 86 87 impl AttributeSpecification { 88 /// Construct a new `AttributeSpecification`. 89 #[inline] new(name: constants::DwAt, form: constants::DwForm) -> AttributeSpecification90 pub fn new(name: constants::DwAt, form: constants::DwForm) -> AttributeSpecification { 91 AttributeSpecification { name, form } 92 } 93 94 /// Write the attribute specification to the `.debug_abbrev` section. 95 #[inline] write<W: Writer>(&self, w: &mut DebugAbbrev<W>) -> Result<()>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()) 99 } 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] test_abbreviation_table()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 } 189