1 use alloc::vec::Vec; 2 3 use crate::common::Encoding; 4 use crate::write::{ 5 AbbreviationTable, LineProgram, LineStringTable, Result, Sections, StringTable, Unit, 6 UnitTable, Writer, 7 }; 8 9 /// Writable DWARF information for more than one unit. 10 #[derive(Debug, Default)] 11 pub struct Dwarf { 12 /// A table of units. These are primarily stored in the `.debug_info` section, 13 /// but they also contain information that is stored in other sections. 14 pub units: UnitTable, 15 16 /// Extra line number programs that are not associated with a unit. 17 /// 18 /// These should only be used when generating DWARF5 line-only debug 19 /// information. 20 pub line_programs: Vec<LineProgram>, 21 22 /// A table of strings that will be stored in the `.debug_line_str` section. 23 pub line_strings: LineStringTable, 24 25 /// A table of strings that will be stored in the `.debug_str` section. 26 pub strings: StringTable, 27 } 28 29 impl Dwarf { 30 /// Create a new `Dwarf` instance. 31 #[inline] new() -> Self32 pub fn new() -> Self { 33 Self::default() 34 } 35 36 /// Write the DWARF information to the given sections. write<W: Writer>(&mut self, sections: &mut Sections<W>) -> Result<()>37 pub fn write<W: Writer>(&mut self, sections: &mut Sections<W>) -> Result<()> { 38 let line_strings = self.line_strings.write(&mut sections.debug_line_str)?; 39 let strings = self.strings.write(&mut sections.debug_str)?; 40 self.units.write(sections, &line_strings, &strings)?; 41 for line_program in &self.line_programs { 42 line_program.write( 43 &mut sections.debug_line, 44 line_program.encoding(), 45 &line_strings, 46 &strings, 47 )?; 48 } 49 Ok(()) 50 } 51 } 52 53 /// Writable DWARF information for a single unit. 54 #[derive(Debug)] 55 pub struct DwarfUnit { 56 /// A unit. This is primarily stored in the `.debug_info` section, 57 /// but also contains information that is stored in other sections. 58 pub unit: Unit, 59 60 /// A table of strings that will be stored in the `.debug_line_str` section. 61 pub line_strings: LineStringTable, 62 63 /// A table of strings that will be stored in the `.debug_str` section. 64 pub strings: StringTable, 65 } 66 67 impl DwarfUnit { 68 /// Create a new `DwarfUnit`. 69 /// 70 /// Note: you should set `self.unit.line_program` after creation. 71 /// This cannot be done earlier because it may need to reference 72 /// `self.line_strings`. new(encoding: Encoding) -> Self73 pub fn new(encoding: Encoding) -> Self { 74 let unit = Unit::new(encoding, LineProgram::none()); 75 DwarfUnit { 76 unit, 77 line_strings: LineStringTable::default(), 78 strings: StringTable::default(), 79 } 80 } 81 82 /// Write the DWARf information to the given sections. write<W: Writer>(&mut self, sections: &mut Sections<W>) -> Result<()>83 pub fn write<W: Writer>(&mut self, sections: &mut Sections<W>) -> Result<()> { 84 let line_strings = self.line_strings.write(&mut sections.debug_line_str)?; 85 let strings = self.strings.write(&mut sections.debug_str)?; 86 87 let abbrev_offset = sections.debug_abbrev.offset(); 88 let mut abbrevs = AbbreviationTable::default(); 89 90 self.unit.write( 91 sections, 92 abbrev_offset, 93 &mut abbrevs, 94 &line_strings, 95 &strings, 96 )?; 97 // None should exist because we didn't give out any UnitId. 98 assert!(sections.debug_info_refs.is_empty()); 99 assert!(sections.debug_loc_refs.is_empty()); 100 assert!(sections.debug_loclists_refs.is_empty()); 101 102 abbrevs.write(&mut sections.debug_abbrev)?; 103 Ok(()) 104 } 105 } 106 107 #[cfg(feature = "read")] 108 pub(crate) mod convert { 109 use super::*; 110 use crate::read::{self, Reader}; 111 use crate::write::{Address, ConvertResult}; 112 113 impl Dwarf { 114 /// Create a `write::Dwarf` by converting a `read::Dwarf`. 115 /// 116 /// `convert_address` is a function to convert read addresses into the `Address` 117 /// type. For non-relocatable addresses, this function may simply return 118 /// `Address::Constant(address)`. For relocatable addresses, it is the caller's 119 /// responsibility to determine the symbol and addend corresponding to the address 120 /// and return `Address::Symbol { symbol, addend }`. from<R: Reader<Offset = usize>>( dwarf: &read::Dwarf<R>, convert_address: &dyn Fn(u64) -> Option<Address>, ) -> ConvertResult<Dwarf>121 pub fn from<R: Reader<Offset = usize>>( 122 dwarf: &read::Dwarf<R>, 123 convert_address: &dyn Fn(u64) -> Option<Address>, 124 ) -> ConvertResult<Dwarf> { 125 let mut line_strings = LineStringTable::default(); 126 let mut strings = StringTable::default(); 127 let units = UnitTable::from(dwarf, &mut line_strings, &mut strings, convert_address)?; 128 // TODO: convert the line programs that were not referenced by a unit. 129 let line_programs = Vec::new(); 130 Ok(Dwarf { 131 units, 132 line_programs, 133 line_strings, 134 strings, 135 }) 136 } 137 } 138 } 139