Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

write: improve high level API #382

Merged
merged 9 commits into from
Feb 11, 2019
9 changes: 9 additions & 0 deletions src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,3 +146,12 @@ impl<T> From<T> for EhFrameOffset<T> {
EhFrameOffset(o)
}
}

/// An offset into the `.debug_info` or `.debug_types` sections.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash)]
pub enum UnitSectionOffset<T = usize> {
/// An offset into the `.debug_info` section.
DebugInfoOffset(DebugInfoOffset<T>),
/// An offset into the `.debug_types` section.
DebugTypesOffset(DebugTypesOffset<T>),
}
10 changes: 1 addition & 9 deletions src/read/dwarf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use common::{
DebugAddrBase, DebugAddrIndex, DebugInfoOffset, DebugLineStrOffset, DebugLocListsBase,
DebugLocListsIndex, DebugRngListsBase, DebugRngListsIndex, DebugStrOffset, DebugStrOffsetsBase,
DebugStrOffsetsIndex, DebugTypesOffset, Encoding, LocationListsOffset, RangeListsOffset,
UnitSectionOffset,
};
use constants;
use read::{
Expand Down Expand Up @@ -460,15 +461,6 @@ impl<R: Reader> Unit<R> {
}
}

/// An offset into the `.debug_info` or `.debug_types` sections.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash)]
pub enum UnitSectionOffset<T = usize> {
/// An offset into the `.debug_info` section.
DebugInfoOffset(DebugInfoOffset<T>),
/// An offset into the `.debug_types` section.
DebugTypesOffset(DebugTypesOffset<T>),
}

impl<T: ReaderOffset> UnitSectionOffset<T> {
/// Convert an offset to be relative to the start of the given unit,
/// instead of relative to the start of the section.
Expand Down
132 changes: 132 additions & 0 deletions src/write/dwarf.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
use vec::Vec;

use common::Encoding;
use 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 {
/// 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();

let mut debug_info_refs = Vec::new();
self.unit.write(
sections,
abbrev_offset,
&mut abbrevs,
&line_strings,
&strings,
&mut debug_info_refs,
)?;
// None should exist because we didn't give out any UnitId.
assert!(debug_info_refs.is_empty());

abbrevs.write(&mut sections.debug_abbrev)?;
Ok(())
}
}

#[cfg(feature = "read")]
pub(crate) mod convert {
use super::*;
use read::{self, Reader};
use 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::Absolute(address)`. For relocatable addresses, it is the caller's
/// responsibility to determine the symbol and addend corresponding to the address
/// and return `Address::Relative { symbol, addend }`.
pub fn from<R: Reader<Offset = usize>>(
dwarf: &read::Dwarf<R>,
convert_address: &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,
})
}
}
}
8 changes: 8 additions & 0 deletions src/write/endian_vec.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::mem;
use vec::Vec;

use endianity::Endianity;
Expand Down Expand Up @@ -36,6 +37,13 @@ where
pub fn into_vec(self) -> Vec<u8> {
self.vec
}

/// Take any written data out of the `EndianVec`, leaving an empty `Vec` in its place.
pub fn take(&mut self) -> Vec<u8> {
let mut vec = Vec::new();
mem::swap(&mut self.vec, &mut vec);
vec
}
}

impl<Endian> Writer for EndianVec<Endian>
Expand Down
Loading