use alloc::vec::Vec; use crate::common::Encoding; use crate::write::{ AbbreviationTable, LineProgram, LineStringTable, Result, Sections, StringTable, Unit, UnitTable, Writer, }; /// Writable DWARF information for more than one unit. #[derive(Debug, Default)] pub struct Dwarf { /// A table of units. These are primarily stored in the `.debug_info` section, /// but they also contain information that is stored in other sections. pub units: UnitTable, /// Extra line number programs that are not associated with a unit. /// /// These should only be used when generating DWARF5 line-only debug /// information. pub line_programs: Vec, /// A table of strings that will be stored in the `.debug_line_str` section. pub line_strings: LineStringTable, /// A table of strings that will be stored in the `.debug_str` section. pub strings: StringTable, } impl Dwarf { /// Create a new `Dwarf` instance. #[inline] pub fn new() -> Self { Self::default() } /// Write the DWARF information to the given sections. pub fn write(&mut self, sections: &mut Sections) -> Result<()> { let line_strings = self.line_strings.write(&mut sections.debug_line_str)?; let strings = self.strings.write(&mut sections.debug_str)?; self.units.write(sections, &line_strings, &strings)?; for line_program in &self.line_programs { line_program.write( &mut sections.debug_line, line_program.encoding(), &line_strings, &strings, )?; } Ok(()) } } /// Writable DWARF information for a single unit. #[derive(Debug)] pub struct DwarfUnit { /// A unit. This is primarily stored in the `.debug_info` section, /// but also contains information that is stored in other sections. pub unit: Unit, /// A table of strings that will be stored in the `.debug_line_str` section. pub line_strings: LineStringTable, /// A table of strings that will be stored in the `.debug_str` section. pub strings: StringTable, } impl DwarfUnit { /// Create a new `DwarfUnit`. /// /// Note: you should set `self.unit.line_program` after creation. /// This cannot be done earlier because it may need to reference /// `self.line_strings`. pub fn new(encoding: Encoding) -> Self { let unit = Unit::new(encoding, LineProgram::none()); DwarfUnit { unit, line_strings: LineStringTable::default(), strings: StringTable::default(), } } /// Write the DWARf information to the given sections. pub fn write(&mut self, sections: &mut Sections) -> Result<()> { let line_strings = self.line_strings.write(&mut sections.debug_line_str)?; let strings = self.strings.write(&mut sections.debug_str)?; let abbrev_offset = sections.debug_abbrev.offset(); let mut abbrevs = AbbreviationTable::default(); self.unit.write( sections, abbrev_offset, &mut abbrevs, &line_strings, &strings, )?; // None should exist because we didn't give out any UnitId. assert!(sections.debug_info_refs.is_empty()); assert!(sections.debug_loc_refs.is_empty()); assert!(sections.debug_loclists_refs.is_empty()); abbrevs.write(&mut sections.debug_abbrev)?; Ok(()) } } #[cfg(feature = "read")] pub(crate) mod convert { use super::*; use crate::read::{self, Reader}; use crate::write::{Address, ConvertResult}; impl Dwarf { /// Create a `write::Dwarf` by converting a `read::Dwarf`. /// /// `convert_address` is a function to convert read addresses into the `Address` /// type. For non-relocatable addresses, this function may simply return /// `Address::Constant(address)`. For relocatable addresses, it is the caller's /// responsibility to determine the symbol and addend corresponding to the address /// and return `Address::Symbol { symbol, addend }`. pub fn from>( dwarf: &read::Dwarf, convert_address: &dyn Fn(u64) -> Option
, ) -> ConvertResult { let mut line_strings = LineStringTable::default(); let mut strings = StringTable::default(); let units = UnitTable::from(dwarf, &mut line_strings, &mut strings, convert_address)?; // TODO: convert the line programs that were not referenced by a unit. let line_programs = Vec::new(); Ok(Dwarf { units, line_programs, line_strings, strings, }) } } }