use std::error;
use std::fmt;
use std::result;
use crate::constants;
mod endian_vec;
pub use self::endian_vec::*;
mod writer;
pub use self::writer::*;
#[macro_use]
mod section;
pub use self::section::*;
macro_rules! define_id {
($name:ident, $docs:expr) => {
#[doc=$docs]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct $name {
base_id: BaseId,
index: usize,
}
impl $name {
#[inline]
fn new(base_id: BaseId, index: usize) -> Self {
$name { base_id, index }
}
}
};
}
macro_rules! define_offsets {
($offsets:ident: $id:ident => $offset:ident, $off_doc:expr) => {
#[doc=$off_doc]
#[derive(Debug)]
pub struct $offsets {
base_id: BaseId,
offsets: Vec<$offset>,
}
impl $offsets {
#[inline]
pub fn none() -> Self {
$offsets {
base_id: BaseId::default(),
offsets: Vec::new(),
}
}
#[inline]
pub fn get(&self, id: $id) -> $offset {
debug_assert_eq!(self.base_id, id.base_id);
self.offsets[id.index]
}
#[inline]
pub fn count(&self) -> usize {
self.offsets.len()
}
}
};
}
mod abbrev;
pub use self::abbrev::*;
mod cfi;
pub use self::cfi::*;
mod dwarf;
pub use self::dwarf::*;
mod line;
pub use self::line::*;
mod range;
pub use self::range::*;
mod str;
pub use self::str::*;
mod unit;
pub use self::unit::*;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Error {
OffsetOutOfBounds,
LengthOutOfBounds,
InvalidAttributeValue,
ValueTooLarge,
UnsupportedWordSize(u8),
UnsupportedVersion(u16),
InitialLengthOverflow,
InvalidAddress,
NeedVersion(u16),
LineStringFormMismatch,
InvalidRange,
IncompatibleLineProgramEncoding,
InvalidFrameCodeOffset(u32),
InvalidFrameDataOffset(i32),
UnsupportedPointerEncoding(constants::DwEhPe),
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
match *self {
Error::OffsetOutOfBounds => write!(f, "The given offset is out of bounds."),
Error::LengthOutOfBounds => write!(f, "The given length is out of bounds."),
Error::InvalidAttributeValue => {
write!(f, "The attribute value is an invalid for writing.")
}
Error::ValueTooLarge => write!(f, "The value is too large for the encoding form."),
Error::UnsupportedWordSize(size) => write!(f, "Unsupported word size: {}", size),
Error::UnsupportedVersion(version) => {
write!(f, "Unsupported DWARF version: {}", version)
}
Error::InitialLengthOverflow => write!(
f,
"The unit length is too large for the requested DWARF format."
),
Error::InvalidAddress => write!(f, "The address is invalid."),
Error::NeedVersion(version) => write!(
f,
"A requested feature requires a DWARF version {}.",
version
),
Error::LineStringFormMismatch => {
write!(f, "Strings in line number program have mismatched forms.")
}
Error::InvalidRange => write!(f, "The range is empty or otherwise invalid."),
Error::IncompatibleLineProgramEncoding => write!(
f,
"The line number program encoding is incompatible with the unit encoding."
),
Error::InvalidFrameCodeOffset(offset) => write!(
f,
"Could not encode code offset ({}) for a frame instruction.",
offset,
),
Error::InvalidFrameDataOffset(offset) => write!(
f,
"Could not encode data offset ({}) for a frame instruction.",
offset,
),
Error::UnsupportedPointerEncoding(eh_pe) => {
write!(f, "Unsupported eh_frame pointer encoding ({}).", eh_pe)
}
}
}
}
impl error::Error for Error {}
pub type Result<T> = result::Result<T, Error>;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Address {
Constant(u64),
Symbol {
symbol: usize,
addend: i64,
},
}
#[cfg(not(debug_assertions))]
type BaseId = ();
#[cfg(debug_assertions)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
struct BaseId(usize);
#[cfg(debug_assertions)]
impl Default for BaseId {
fn default() -> Self {
use std::sync::atomic;
static BASE_ID: atomic::AtomicUsize = atomic::AtomicUsize::new(0);
BaseId(BASE_ID.fetch_add(1, atomic::Ordering::Relaxed))
}
}
#[cfg(feature = "read")]
mod convert {
use super::*;
use crate::read;
pub(crate) use super::unit::convert::*;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ConvertError {
Read(read::Error),
UnsupportedAttributeValue,
InvalidAttributeValue,
InvalidDebugInfoOffset,
InvalidAddress,
MissingCompilationDirectory,
MissingCompilationFile,
UnsupportedLineInstruction,
UnsupportedLineStringForm,
InvalidFileIndex,
InvalidDirectoryIndex,
InvalidLineBase,
InvalidLineRef,
InvalidRangeRelativeAddress,
UnsupportedCfiInstruction,
UnsupportedIndirectAddress,
}
impl fmt::Display for ConvertError {
fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
use self::ConvertError::*;
match *self {
Read(ref e) => e.fmt(f),
UnsupportedAttributeValue => {
write!(f, "Writing of this attribute value is not implemented yet.")
}
InvalidAttributeValue => write!(
f,
"This attribute value is an invalid name/form combination."
),
InvalidDebugInfoOffset => write!(
f,
"A `.debug_info` reference does not refer to a valid entry."
),
InvalidAddress => write!(f, "An address could not be converted."),
MissingCompilationDirectory => write!(
f,
"The line number program is missing the compilation directory."
),
MissingCompilationFile => write!(
f,
"The line number program is missing the compilation file."
),
UnsupportedLineInstruction => write!(
f,
"Writing this line number instruction is not implemented yet."
),
UnsupportedLineStringForm => write!(
f,
"Writing this form of line string is not implemented yet."
),
InvalidFileIndex => write!(f, "A `.debug_line` file index is invalid."),
InvalidDirectoryIndex => write!(f, "A `.debug_line` directory index is invalid."),
InvalidLineBase => write!(f, "A `.debug_line` line base is invalid."),
InvalidLineRef => write!(f, "A `.debug_line` reference is invalid."),
InvalidRangeRelativeAddress => {
write!(f, "Invalid relative address in a range list.")
}
UnsupportedCfiInstruction => {
write!(f, "Writing this CFI instruction is not implemented yet.")
}
UnsupportedIndirectAddress => {
write!(f, "Writing indirect pointers is not implemented yet.")
}
}
}
}
impl error::Error for ConvertError {}
impl From<read::Error> for ConvertError {
fn from(e: read::Error) -> Self {
ConvertError::Read(e)
}
}
pub type ConvertResult<T> = result::Result<T, ConvertError>;
}
#[cfg(feature = "read")]
pub use self::convert::*;