//! Write DWARF debugging information. //! //! ## API Structure //! //! This module works by building up a representation of the debugging information //! in memory, and then writing it all at once. It supports two major use cases: //! //! * Use the [`DwarfUnit`](./struct.DwarfUnit.html) type when writing DWARF //! for a single compilation unit. //! //! * Use the [`Dwarf`](./struct.Dwarf.html) type when writing DWARF for multiple //! compilation units. //! //! The module also supports reading in DWARF debugging information and writing it out //! again, possibly after modifying it. Create a [`read::Dwarf`](../read/struct.Dwarf.html) //! instance, and then use [`Dwarf::from`](./struct.Dwarf.html#method.from) to convert //! it to a writable instance. //! //! ## Example Usage //! //! Write a compilation unit containing only the top level DIE. //! //! ```rust //! use gimli::write::{ //! Address, AttributeValue, DwarfUnit, EndianVec, Error, Range, RangeList, Sections, //! }; //! //! fn example() -> Result<(), Error> { //! // Choose the encoding parameters. //! let encoding = gimli::Encoding { //! format: gimli::Format::Dwarf32, //! version: 5, //! address_size: 8, //! }; //! // Create a container for a single compilation unit. //! let mut dwarf = DwarfUnit::new(encoding); //! // Set a range attribute on the root DIE. //! let range_list = RangeList(vec![Range::StartLength { //! begin: Address::Constant(0x100), //! length: 42, //! }]); //! let range_list_id = dwarf.unit.ranges.add(range_list); //! let root = dwarf.unit.root(); //! dwarf.unit.get_mut(root).set( //! gimli::DW_AT_ranges, //! AttributeValue::RangeListRef(range_list_id), //! ); //! // Create a `Vec` for each DWARF section. //! let mut sections = Sections::new(EndianVec::new(gimli::LittleEndian)); //! // Finally, write the DWARF data to the sections. //! dwarf.write(&mut sections)?; //! sections.for_each(|id, data| { //! // Here you can add the data to the output object file. //! Ok(()) //! }) //! } //! # fn main() { //! # example().unwrap(); //! # }
impl $offsets { /// Return an empty list of offsets. #[inline] pubfn none() -> Self {
$offsets {
base_id: BaseId::default(),
offsets: Vec::new(),
}
}
/// Get the offset /// /// # Panics /// /// Panics if `id` is invalid. #[inline] pubfn get(&self, id: $id) -> $offset {
debug_assert_eq!(self.base_id, id.base_id); self.offsets[id.index]
}
/// Return the number of offsets. #[inline] pubfn count(&self) -> usize { self.offsets.len()
}
}
};
}
mod abbrev; pubuseself::abbrev::*;
mod cfi; pubuseself::cfi::*;
mod dwarf; pubuseself::dwarf::*;
mod line; pubuseself::line::*;
mod loc; pubuseself::loc::*;
mod op; pubuseself::op::*;
mod range; pubuseself::range::*;
mod str; pubuseself::str::*;
mod unit; pubuseself::unit::*;
/// An error that occurred when writing. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pubenum Error { /// The given offset is out of bounds.
OffsetOutOfBounds, /// The given length is out of bounds.
LengthOutOfBounds, /// The attribute value is an invalid for writing.
InvalidAttributeValue, /// The value is too large for the encoding form.
ValueTooLarge, /// Unsupported word size.
UnsupportedWordSize(u8), /// Unsupported DWARF version.
UnsupportedVersion(u16), /// The unit length is too large for the requested DWARF format.
InitialLengthOverflow, /// The address is invalid.
InvalidAddress, /// The reference is invalid.
InvalidReference, /// A requested feature requires a different DWARF version.
NeedVersion(u16), /// Strings in line number program have mismatched forms.
LineStringFormMismatch, /// The range is empty or otherwise invalid.
InvalidRange, /// The line number program encoding is incompatible with the unit encoding.
IncompatibleLineProgramEncoding, /// Could not encode code offset for a frame instruction.
InvalidFrameCodeOffset(u32), /// Could not encode data offset for a frame instruction.
InvalidFrameDataOffset(i32), /// Unsupported eh_frame pointer encoding.
UnsupportedPointerEncoding(constants::DwEhPe), /// Unsupported reference in CFI expression.
UnsupportedCfiExpressionReference, /// Unsupported forward reference in expression.
UnsupportedExpressionForwardReference,
}
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::InvalidReference => write!(f, "The reference 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)
}
Error::UnsupportedCfiExpressionReference => {
write!(f, "Unsupported reference in CFI expression.")
}
Error::UnsupportedExpressionForwardReference => {
write!(f, "Unsupported forward reference in expression.")
}
}
}
}
impl error::Error for Error {}
/// The result of a write. pubtype Result<T> = result::Result<T, Error>;
/// An address. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pubenum Address { /// A fixed address that does not require relocation.
Constant(u64), /// An address that is relative to a symbol which may be relocated.
Symbol { /// The symbol that the address is relative to. /// /// The meaning of this value is decided by the writer, but /// will typically be an index into a symbol table.
symbol: usize, /// The offset of the address relative to the symbol. /// /// This will typically be used as the addend in a relocation.
addend: i64,
},
}
/// A reference to a `.debug_info` entry. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pubenum Reference { /// An external symbol. /// /// The meaning of this value is decided by the writer, but /// will typically be an index into a symbol table.
Symbol(usize), /// An entry in the same section. /// /// This only supports references in units that are emitted together.
Entry(UnitId, UnitEntryId),
}
// This type is only used in debug assertions. #[cfg(not(debug_assertions))] type BaseId = ();
#[cfg(feature = "read")] mod convert { usesuper::*; usecrate::read;
pub(crate) usesuper::unit::convert::*;
/// An error that occurred when converting a read value into a write value. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pubenum ConvertError { /// An error occurred when reading.
Read(read::Error), /// Writing of this attribute value is not implemented yet.
UnsupportedAttributeValue, /// This attribute value is an invalid name/form combination.
InvalidAttributeValue, /// A `.debug_info` reference does not refer to a valid entry.
InvalidDebugInfoOffset, /// An address could not be converted.
InvalidAddress, /// Writing this line number instruction is not implemented yet.
UnsupportedLineInstruction, /// Writing this form of line string is not implemented yet.
UnsupportedLineStringForm, /// A `.debug_line` file index is invalid.
InvalidFileIndex, /// A `.debug_line` directory index is invalid.
InvalidDirectoryIndex, /// A `.debug_line` line base is invalid.
InvalidLineBase, /// A `.debug_line` reference is invalid.
InvalidLineRef, /// A `.debug_info` unit entry reference is invalid.
InvalidUnitRef, /// A `.debug_info` reference is invalid.
InvalidDebugInfoRef, /// Invalid relative address in a range list.
InvalidRangeRelativeAddress, /// Writing this CFI instruction is not implemented yet.
UnsupportedCfiInstruction, /// Writing indirect pointers is not implemented yet.
UnsupportedIndirectAddress, /// Writing this expression operation is not implemented yet.
UnsupportedOperation, /// Operation branch target is invalid.
InvalidBranchTarget, /// Writing this unit type is not supported yet.
UnsupportedUnitType,
}
impl fmt::Display for ConvertError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> result::Result<(), fmt::Error> { useself::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."),
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."),
InvalidUnitRef => write!(f, "A `.debug_info` unit entry reference is invalid."),
InvalidDebugInfoRef => write!(f, "A `.debug_info` 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.")
}
UnsupportedOperation => write!(
f, "Writing this expression operation is not implemented yet."
),
InvalidBranchTarget => write!(f, "Operation branch target is invalid."),
UnsupportedUnitType => write!(f, "Writing this unit type is not supported yet."),
}
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.