1 //! Write DWARF debugging information.
5 //! This module works by building up a representation of the debugging information
6 //! in memory, and then writing it all at once. It supports two major use cases:
8 //! * Use the [`DwarfUnit`](./struct.DwarfUnit.html) type when writing DWARF
9 //! for a single compilation unit.
11 //! * Use the [`Dwarf`](./struct.Dwarf.html) type when writing DWARF for multiple
12 //! compilation units.
14 //! The module also supports reading in DWARF debugging information and writing it out
15 //! again, possibly after modifying it. Create a [`read::Dwarf`](../read/struct.Dwarf.html)
16 //! instance, and then use [`Dwarf::from`](./struct.Dwarf.html#method.from) to convert
17 //! it to a writable instance.
21 //! Write a compilation unit containing only the top level DIE.
24 //! use gimli::write::{
25 //! Address, AttributeValue, DwarfUnit, EndianVec, Error, Range, RangeList, Sections,
28 //! fn example() -> Result<(), Error> {
29 //! // Choose the encoding parameters.
30 //! let encoding = gimli::Encoding {
31 //! format: gimli::Format::Dwarf32,
35 //! // Create a container for a single compilation unit.
36 //! let mut dwarf = DwarfUnit::new(encoding);
37 //! // Set a range attribute on the root DIE.
38 //! let range_list = RangeList(vec![Range::StartLength {
39 //! begin: Address::Constant(0x100),
42 //! let range_list_id = dwarf.unit.ranges.add(range_list);
43 //! let root = dwarf.unit.root();
44 //! dwarf.unit.get_mut(root).set(
45 //! gimli::DW_AT_ranges,
46 //! AttributeValue::RangeListRef(range_list_id),
48 //! // Create a `Vec` for each DWARF section.
49 //! let mut sections = Sections::new(EndianVec::new(gimli::LittleEndian));
50 //! // Finally, write the DWARF data to the sections.
51 //! dwarf.write(&mut sections)?;
52 //! sections.for_each(|id, data| {
53 //! // Here you can add the data to the output object file.
58 //! # example().unwrap();
68 pub use self::endian_vec
::*;
71 pub use self::writer
::*;
75 pub use self::section
::*;
77 macro_rules
! define_id
{
78 ($name
:ident
, $docs
:expr
) => {
80 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
88 fn new(base_id
: BaseId
, index
: usize) -> Self {
89 $name { base_id, index }
95 macro_rules
! define_offsets
{
96 ($offsets
:ident
: $id
:ident
=> $offset
:ident
, $off_doc
:expr
) => {
101 // We know ids start at 0.
102 offsets
: Vec
<$offset
>,
106 /// Return an empty list of offsets.
108 pub fn none() -> Self {
110 base_id
: BaseId
::default(),
119 /// Panics if `id` is invalid.
121 pub fn get(&self, id
: $id
) -> $offset
{
122 debug_assert_eq
!(self.base_id
, id
.base_id
);
123 self.offsets
[id
.index
]
126 /// Return the number of offsets.
128 pub fn count(&self) -> usize {
136 pub use self::abbrev
::*;
139 pub use self::cfi
::*;
142 pub use self::dwarf
::*;
145 pub use self::line
::*;
148 pub use self::loc
::*;
154 pub use self::range
::*;
157 pub use self::str::*;
160 pub use self::unit
::*;
162 /// An error that occurred when writing.
163 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
165 /// The given offset is out of bounds.
167 /// The given length is out of bounds.
169 /// The attribute value is an invalid for writing.
170 InvalidAttributeValue
,
171 /// The value is too large for the encoding form.
173 /// Unsupported word size.
174 UnsupportedWordSize(u8),
175 /// Unsupported DWARF version.
176 UnsupportedVersion(u16),
177 /// The unit length is too large for the requested DWARF format.
178 InitialLengthOverflow
,
179 /// The address is invalid.
181 /// The reference is invalid.
183 /// A requested feature requires a different DWARF version.
185 /// Strings in line number program have mismatched forms.
186 LineStringFormMismatch
,
187 /// The range is empty or otherwise invalid.
189 /// The line number program encoding is incompatible with the unit encoding.
190 IncompatibleLineProgramEncoding
,
191 /// Could not encode code offset for a frame instruction.
192 InvalidFrameCodeOffset(u32),
193 /// Could not encode data offset for a frame instruction.
194 InvalidFrameDataOffset(i32),
195 /// Unsupported eh_frame pointer encoding.
196 UnsupportedPointerEncoding(constants
::DwEhPe
),
197 /// Unsupported reference in CFI expression.
198 UnsupportedCfiExpressionReference
,
199 /// Unsupported forward reference in expression.
200 UnsupportedExpressionForwardReference
,
203 impl fmt
::Display
for Error
{
204 fn fmt(&self, f
: &mut fmt
::Formatter
) -> result
::Result
<(), fmt
::Error
> {
206 Error
::OffsetOutOfBounds
=> write
!(f
, "The given offset is out of bounds."),
207 Error
::LengthOutOfBounds
=> write
!(f
, "The given length is out of bounds."),
208 Error
::InvalidAttributeValue
=> {
209 write
!(f
, "The attribute value is an invalid for writing.")
211 Error
::ValueTooLarge
=> write
!(f
, "The value is too large for the encoding form."),
212 Error
::UnsupportedWordSize(size
) => write
!(f
, "Unsupported word size: {}", size
),
213 Error
::UnsupportedVersion(version
) => {
214 write
!(f
, "Unsupported DWARF version: {}", version
)
216 Error
::InitialLengthOverflow
=> write
!(
218 "The unit length is too large for the requested DWARF format."
220 Error
::InvalidAddress
=> write
!(f
, "The address is invalid."),
221 Error
::InvalidReference
=> write
!(f
, "The reference is invalid."),
222 Error
::NeedVersion(version
) => write
!(
224 "A requested feature requires a DWARF version {}.",
227 Error
::LineStringFormMismatch
=> {
228 write
!(f
, "Strings in line number program have mismatched forms.")
230 Error
::InvalidRange
=> write
!(f
, "The range is empty or otherwise invalid."),
231 Error
::IncompatibleLineProgramEncoding
=> write
!(
233 "The line number program encoding is incompatible with the unit encoding."
235 Error
::InvalidFrameCodeOffset(offset
) => write
!(
237 "Could not encode code offset ({}) for a frame instruction.",
240 Error
::InvalidFrameDataOffset(offset
) => write
!(
242 "Could not encode data offset ({}) for a frame instruction.",
245 Error
::UnsupportedPointerEncoding(eh_pe
) => {
246 write
!(f
, "Unsupported eh_frame pointer encoding ({}).", eh_pe
)
248 Error
::UnsupportedCfiExpressionReference
=> {
249 write
!(f
, "Unsupported reference in CFI expression.")
251 Error
::UnsupportedExpressionForwardReference
=> {
252 write
!(f
, "Unsupported forward reference in expression.")
258 impl error
::Error
for Error {}
260 /// The result of a write.
261 pub type Result
<T
> = result
::Result
<T
, Error
>;
264 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
266 /// A fixed address that does not require relocation.
268 /// An address that is relative to a symbol which may be relocated.
270 /// The symbol that the address is relative to.
272 /// The meaning of this value is decided by the writer, but
273 /// will typically be an index into a symbol table.
275 /// The offset of the address relative to the symbol.
277 /// This will typically be used as the addend in a relocation.
282 /// A reference to a `.debug_info` entry.
283 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
285 /// An external symbol.
287 /// The meaning of this value is decided by the writer, but
288 /// will typically be an index into a symbol table.
290 /// An entry in the same section.
292 /// This only supports references in units that are emitted together.
293 Entry(UnitId
, UnitEntryId
),
296 // This type is only used in debug assertions.
297 #[cfg(not(debug_assertions))]
300 #[cfg(debug_assertions)]
301 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
302 struct BaseId(usize);
304 #[cfg(debug_assertions)]
305 impl Default
for BaseId
{
306 fn default() -> Self {
307 use std
::sync
::atomic
;
308 static BASE_ID
: atomic
::AtomicUsize
= atomic
::AtomicUsize
::new(0);
309 BaseId(BASE_ID
.fetch_add(1, atomic
::Ordering
::Relaxed
))
313 #[cfg(feature = "read")]
318 pub(crate) use super::unit
::convert
::*;
320 /// An error that occurred when converting a read value into a write value.
321 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
322 pub enum ConvertError
{
323 /// An error occurred when reading.
325 /// Writing of this attribute value is not implemented yet.
326 UnsupportedAttributeValue
,
327 /// This attribute value is an invalid name/form combination.
328 InvalidAttributeValue
,
329 /// A `.debug_info` reference does not refer to a valid entry.
330 InvalidDebugInfoOffset
,
331 /// An address could not be converted.
333 /// Writing this line number instruction is not implemented yet.
334 UnsupportedLineInstruction
,
335 /// Writing this form of line string is not implemented yet.
336 UnsupportedLineStringForm
,
337 /// A `.debug_line` file index is invalid.
339 /// A `.debug_line` directory index is invalid.
340 InvalidDirectoryIndex
,
341 /// A `.debug_line` line base is invalid.
343 /// A `.debug_line` reference is invalid.
345 /// A `.debug_info` unit entry reference is invalid.
347 /// A `.debug_info` reference is invalid.
349 /// Invalid relative address in a range list.
350 InvalidRangeRelativeAddress
,
351 /// Writing this CFI instruction is not implemented yet.
352 UnsupportedCfiInstruction
,
353 /// Writing indirect pointers is not implemented yet.
354 UnsupportedIndirectAddress
,
355 /// Writing this expression operation is not implemented yet.
356 UnsupportedOperation
,
357 /// Operation branch target is invalid.
359 /// Writing this unit type is not supported yet.
363 impl fmt
::Display
for ConvertError
{
364 fn fmt(&self, f
: &mut fmt
::Formatter
) -> result
::Result
<(), fmt
::Error
> {
365 use self::ConvertError
::*;
367 Read(ref e
) => e
.fmt(f
),
368 UnsupportedAttributeValue
=> {
369 write
!(f
, "Writing of this attribute value is not implemented yet.")
371 InvalidAttributeValue
=> write
!(
373 "This attribute value is an invalid name/form combination."
375 InvalidDebugInfoOffset
=> write
!(
377 "A `.debug_info` reference does not refer to a valid entry."
379 InvalidAddress
=> write
!(f
, "An address could not be converted."),
380 UnsupportedLineInstruction
=> write
!(
382 "Writing this line number instruction is not implemented yet."
384 UnsupportedLineStringForm
=> write
!(
386 "Writing this form of line string is not implemented yet."
388 InvalidFileIndex
=> write
!(f
, "A `.debug_line` file index is invalid."),
389 InvalidDirectoryIndex
=> write
!(f
, "A `.debug_line` directory index is invalid."),
390 InvalidLineBase
=> write
!(f
, "A `.debug_line` line base is invalid."),
391 InvalidLineRef
=> write
!(f
, "A `.debug_line` reference is invalid."),
392 InvalidUnitRef
=> write
!(f
, "A `.debug_info` unit entry reference is invalid."),
393 InvalidDebugInfoRef
=> write
!(f
, "A `.debug_info` reference is invalid."),
394 InvalidRangeRelativeAddress
=> {
395 write
!(f
, "Invalid relative address in a range list.")
397 UnsupportedCfiInstruction
=> {
398 write
!(f
, "Writing this CFI instruction is not implemented yet.")
400 UnsupportedIndirectAddress
=> {
401 write
!(f
, "Writing indirect pointers is not implemented yet.")
403 UnsupportedOperation
=> write
!(
405 "Writing this expression operation is not implemented yet."
407 InvalidBranchTarget
=> write
!(f
, "Operation branch target is invalid."),
408 UnsupportedUnitType
=> write
!(f
, "Writing this unit type is not supported yet."),
413 impl error
::Error
for ConvertError {}
415 impl From
<read
::Error
> for ConvertError
{
416 fn from(e
: read
::Error
) -> Self {
417 ConvertError
::Read(e
)
421 /// The result of a conversion.
422 pub type ConvertResult
<T
> = result
::Result
<T
, ConvertError
>;
424 #[cfg(feature = "read")]
425 pub use self::convert
::*;