| 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 ] |
| 32 | pub fn new() -> Self { |
| 33 | Self::default() |
| 34 | } |
| 35 | |
| 36 | /// Write the DWARF information to the given sections. |
| 37 | pub fn write<W: Writer>(&mut self, sections: &mut Sections<W>) -> Result<()> { |
| 38 | let line_strings: DebugLineStrOffsets = self.line_strings.write(&mut sections.debug_line_str)?; |
| 39 | let strings: DebugStrOffsets = self.strings.write(&mut sections.debug_str)?; |
| 40 | self.units.write(sections, &line_strings, &strings)?; |
| 41 | for line_program: &LineProgram 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`. |
| 73 | 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. |
| 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 }`. |
| 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 | |