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

Implement writing of .debug_info, .debug_abbrev and .debug_str #340

Merged
merged 4 commits into from
Nov 19, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ coveralls = { repository = "gimli-rs/gimli" }
arrayvec = { version = "0.4.6", default-features = false }
byteorder = { version = "1.0", default-features = false }
fallible-iterator = { version = "0.1.4", default-features = false }
indexmap = { version = "1.0", optional = true }
stable_deref_trait = { version = "1.1.0", default-features = false }

[dev-dependencies]
Expand All @@ -33,6 +34,6 @@ test-assembler = "0.1.3"
typed-arena = "1"

[features]
std = ["fallible-iterator/std", "stable_deref_trait/std"]
std = ["fallible-iterator/std", "stable_deref_trait/std", "indexmap"]
alloc = ["fallible-iterator/alloc", "stable_deref_trait/alloc"]
default = ["std"]
3 changes: 1 addition & 2 deletions src/arch.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// TODO: don't depend on read
use read::Register;
use common::Register;

macro_rules! registers {
($struct_name:ident, { $($name:ident = ($val:expr, $disp:expr)),+ }) => {
Expand Down
95 changes: 95 additions & 0 deletions src/common.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/// Whether the format of a compilation unit is 32- or 64-bit.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Format {
/// 64-bit DWARF
Dwarf64,
/// 32-bit DWARF
Dwarf32,
}

impl Format {
/// Return the serialized size of an initial length field for the format.
#[inline]
pub fn initial_length_size(self) -> u8 {
match self {
Format::Dwarf32 => 4,
Format::Dwarf64 => 12,
}
}

/// Return the natural word size for the format
#[inline]
pub fn word_size(self) -> u8 {
match self {
Format::Dwarf32 => 4,
Format::Dwarf64 => 8,
}
}
}

/// A DWARF register number.
///
/// The meaning of this value is ABI dependent. This is generally encoded as
/// a ULEB128, but supported architectures need 16 bits at most.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Register(pub u16);

/// An offset into the `.debug_abbrev` section.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct DebugAbbrevOffset<T = usize>(pub T);

/// An offset into the `.debug_info` section.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash)]
pub struct DebugInfoOffset<T = usize>(pub T);

/// An offset into the `.debug_line` section.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DebugLineOffset<T = usize>(pub T);

/// An offset into either the `.debug_loc` section or the `.debug_loclists` section,
/// depending on the version of the unit the offset was contained in.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct LocationListsOffset<T = usize>(pub T);

/// An offset into the `.debug_macinfo` section.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct DebugMacinfoOffset<T = usize>(pub T);

/// An offset into either the `.debug_ranges` section or the `.debug_rnglists` section,
/// depending on the version of the unit the offset was contained in.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct RangeListsOffset<T = usize>(pub T);

/// An offset into the `.debug_str` section.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DebugStrOffset<T = usize>(pub T);

/// An offset into the `.debug_types` section.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct DebugTypesOffset<T = usize>(pub T);

/// A type signature as used in the `.debug_types` section.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct DebugTypeSignature(pub u64);

/// An offset into the `.debug_frame` section.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct DebugFrameOffset<T = usize>(pub T);

impl<T> From<T> for DebugFrameOffset<T> {
#[inline]
fn from(o: T) -> Self {
DebugFrameOffset(o)
}
}

/// An offset into the `.eh_frame` section.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct EhFrameOffset<T = usize>(pub T);

impl<T> From<T> for EhFrameOffset<T> {
#[inline]
fn from(o: T) -> Self {
EhFrameOffset(o)
}
}
28 changes: 28 additions & 0 deletions src/endianity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,34 @@ pub trait Endianity: Debug + Default + Clone + Copy + PartialEq + Eq {
f64::from_bits(self.read_u64(buf))
}

/// Writes an unsigned 16 bit integer `n` to `buf`.
///
/// # Panics
///
/// Panics when `buf.len() < 2`.
#[inline]
fn write_u16(self, buf: &mut [u8], n: u16) {
if self.is_big_endian() {
byteorder::BigEndian::write_u16(buf, n)
} else {
byteorder::LittleEndian::write_u16(buf, n)
}
}

/// Writes an unsigned 32 bit integer `n` to `buf`.
///
/// # Panics
///
/// Panics when `buf.len() < 4`.
#[inline]
fn write_u32(self, buf: &mut [u8], n: u32) {
if self.is_big_endian() {
byteorder::BigEndian::write_u32(buf, n)
} else {
byteorder::LittleEndian::write_u32(buf, n)
}
}

/// Writes an unsigned 64 bit integer `n` to `buf`.
///
/// # Panics
Expand Down
12 changes: 10 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,13 +194,15 @@ extern crate core as std;
extern crate arrayvec;
extern crate byteorder;
extern crate fallible_iterator;
#[cfg(feature = "std")]
extern crate indexmap;
extern crate stable_deref_trait;

#[cfg(feature = "std")]
mod imports {
pub use std::borrow;
pub use std::boxed;
pub use std::collections::btree_map;
pub use std::collections;
pub use std::rc;
pub use std::string;
pub use std::sync::Arc;
Expand All @@ -211,7 +213,7 @@ mod imports {
mod imports {
pub use alloc::borrow;
pub use alloc::boxed;
pub use alloc::collections::btree_map;
pub use alloc::collections;
pub use alloc::rc;
pub use alloc::string;
pub use alloc::sync::Arc;
Expand All @@ -222,6 +224,9 @@ use imports::*;

pub use stable_deref_trait::{CloneStableDeref, StableDeref};

mod common;
pub use common::*;

mod arch;
pub use arch::*;

Expand All @@ -238,5 +243,8 @@ pub mod read;
// For backwards compat.
pub use read::*;

#[cfg(feature = "std")]
pub mod write;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is worth having two traits: read and write that enable their corresponding modules. This way, compilers that are emitting DWARF don't need to pay compile time for DWARF reading, and a stack unwinder doesn't need to pay compile time for DWARF writing.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll do this in a follow up PR.


#[cfg(test)]
mod test_util;
7 changes: 2 additions & 5 deletions src/read/abbrev.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
//! Functions for parsing DWARF debugging abbreviations.

use btree_map;
use collections::btree_map;
use vec::Vec;

use common::DebugAbbrevOffset;
use constants;
use endianity::Endianity;
use read::{EndianSlice, Error, Reader, Result, Section, UnitHeader};

/// An offset into the `.debug_abbrev` section.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct DebugAbbrevOffset<T = usize>(pub T);

/// The `DebugAbbrev` struct represents the abbreviations describing
/// `DebuggingInformationEntry`s' attribute names and forms found in the
/// `.debug_abbrev` section.
Expand Down
9 changes: 4 additions & 5 deletions src/read/aranges.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@ use fallible_iterator::FallibleIterator;
use std::cmp::Ordering;
use std::marker::PhantomData;

use common::{DebugInfoOffset, Format};
use endianity::Endianity;
use read::lookup::{DebugLookup, LookupEntryIter, LookupParser};
use read::{
parse_debug_info_offset, DebugInfoOffset, EndianSlice, Error, Format, Reader, ReaderOffset,
Result, Section,
};
use read::{parse_debug_info_offset, EndianSlice, Error, Reader, ReaderOffset, Result, Section};

#[derive(Debug, Clone, PartialEq, Eq)]
struct ArangeHeader<T = usize> {
Expand Down Expand Up @@ -261,9 +259,10 @@ impl<R: Reader> FallibleIterator for ArangeEntryIter<R> {
#[cfg(test)]
mod tests {
use super::*;
use common::{DebugInfoOffset, Format};
use endianity::LittleEndian;
use read::lookup::LookupParser;
use read::{DebugInfoOffset, EndianSlice, Format};
use read::EndianSlice;

#[test]
fn test_parse_header_ok() {
Expand Down
30 changes: 5 additions & 25 deletions src/read/cfi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,35 +9,14 @@ use std::marker::PhantomData;
use std::mem;
use std::str;

use common::{DebugFrameOffset, EhFrameOffset, Format, Register};
use constants::{self, DwEhPe};
use endianity::Endianity;
use read::{
parse_encoded_pointer, parse_pointer_encoding, EndianSlice, Error, Expression, Format, Pointer,
Reader, ReaderOffset, Register, Result, Section,
parse_encoded_pointer, parse_pointer_encoding, EndianSlice, Error, Expression, Pointer, Reader,
ReaderOffset, Result, Section,
};

/// An offset into the `.debug_frame` section.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct DebugFrameOffset<T = usize>(pub T);

impl<T> From<T> for DebugFrameOffset<T> {
#[inline]
fn from(o: T) -> Self {
DebugFrameOffset(o)
}
}

/// An offset into the `.eh_frame` section.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct EhFrameOffset<T = usize>(pub T);

impl<T> From<T> for EhFrameOffset<T> {
#[inline]
fn from(o: T) -> Self {
EhFrameOffset(o)
}
}

/// `DebugFrame` contains the `.debug_frame` section's frame unwinding
/// information required to unwind to and recover registers from older frames on
/// the stack. For example, this is useful for a debugger that wants to print
Expand Down Expand Up @@ -3274,9 +3253,10 @@ mod tests {
use self::test_assembler::{Endian, Label, LabelMaker, LabelOrNum, Section, ToLabelOrNum};
use super::*;
use super::{parse_cfi_entry, AugmentationData, RegisterRuleMap, UnwindContext};
use common::Format;
use constants;
use endianity::{BigEndian, Endianity, LittleEndian, NativeEndian};
use read::{EndianSlice, Error, Expression, Format, Pointer, Result};
use read::{EndianSlice, Error, Expression, Pointer, Result};
use std::marker::PhantomData;
use std::mem;
use std::u64;
Expand Down
2 changes: 2 additions & 0 deletions src/read/endian_slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ use endianity::Endianity;
use read::{Error, Reader, Result};

/// A `&[u8]` slice with endianity metadata.
///
/// This implements the `Reader` trait, which is used for all reading of DWARF sections.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct EndianSlice<'input, Endian>
where
Expand Down
10 changes: 3 additions & 7 deletions src/read/line.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,10 @@ use std::fmt;
use std::result;
use vec::Vec;

use common::{DebugLineOffset, Format};
use constants;
use endianity::Endianity;
use read::{EndianSlice, Error, Format, Reader, ReaderOffset, Result, Section};

/// An offset into the `.debug_line` section.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DebugLineOffset<T = usize>(pub T);
use read::{EndianSlice, Error, Reader, ReaderOffset, Result, Section};

/// The `DebugLine` struct contains the source location to instruction mapping
/// found in the `.debug_line` section.
Expand Down Expand Up @@ -1464,11 +1461,10 @@ impl<R: Reader> FileEntry<R> {

#[cfg(test)]
mod tests {
use super::StateMachineRegisters;
use super::*;
use constants;
use endianity::LittleEndian;
use read::{EndianSlice, Error, Format};
use read::{EndianSlice, Error};
use std::u8;

#[test]
Expand Down
10 changes: 3 additions & 7 deletions src/read/loclists.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use fallible_iterator::FallibleIterator;

use common::{Format, LocationListsOffset};
use constants;
use endianity::Endianity;
use read::{
AddressIndex, EndianSlice, Error, Expression, Format, Range, RawRange, Reader, ReaderOffset,
Result, Section,
AddressIndex, EndianSlice, Error, Expression, Range, RawRange, Reader, ReaderOffset, Result,
Section,
};

/// The `DebugLoc` struct represents the DWARF strings
Expand Down Expand Up @@ -130,11 +131,6 @@ fn parse_header<R: Reader>(input: &mut R) -> Result<LocListsHeader> {
})
}

/// An offset into either the `.debug_loc` section or the `.debug_loclists` section,
/// depending on the version of the unit the offset was contained in.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct LocationListsOffset<T = usize>(pub T);

/// The DWARF data found in `.debug_loc` and `.debug_loclists` sections.
#[derive(Debug, Clone, Copy)]
pub struct LocationLists<R: Reader> {
Expand Down
6 changes: 2 additions & 4 deletions src/read/lookup.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
use std::marker::PhantomData;

use read::{
parse_debug_info_offset, DebugInfoOffset, Error, Format, Reader, ReaderOffset, Result,
UnitOffset,
};
use common::{DebugInfoOffset, Format};
use read::{parse_debug_info_offset, Error, Reader, ReaderOffset, Result, UnitOffset};

// The various "Accelerated Access" sections (DWARF standard v4 Section 6.1) all have
// similar structures. They consist of a header with metadata and an offset into the
Expand Down
Loading