1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
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<LineProgram>,
/// 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<W: Writer>(&mut self, sections: &mut Sections<W>) -> 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<W: Writer>(&mut self, sections: &mut Sections<W>) -> 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<R: Reader<Offset = usize>>(
dwarf: &read::Dwarf<R>,
convert_address: &dyn Fn(u64) -> Option<Address>,
) -> ConvertResult<Dwarf> {
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,
})
}
}
}