1 //! Write DWARF debugging information.
2 //!
3 //! ## API Structure
4 //!
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:
7 //!
8 //! * Use the [`DwarfUnit`](./struct.DwarfUnit.html) type when writing DWARF
9 //! for a single compilation unit.
10 //!
11 //! * Use the [`Dwarf`](./struct.Dwarf.html) type when writing DWARF for multiple
12 //! compilation units.
13 //!
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.
18 //!
19 //! ## Example Usage
20 //!
21 //! Write a compilation unit containing only the top level DIE.
22 //!
23 //! ```rust
24 //! use gimli::write::{
25 //!     Address, AttributeValue, DwarfUnit, EndianVec, Error, Range, RangeList, Sections,
26 //! };
27 //!
28 //! fn example() -> Result<(), Error> {
29 //!     // Choose the encoding parameters.
30 //!     let encoding = gimli::Encoding {
31 //!         format: gimli::Format::Dwarf32,
32 //!         version: 5,
33 //!         address_size: 8,
34 //!     };
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),
40 //!         length: 42,
41 //!     }]);
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),
47 //!     );
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.
54 //!         Ok(())
55 //!     })
56 //! }
57 //! # fn main() {
58 //! #     example().unwrap();
59 //! # }
60 
61 use std::error;
62 use std::fmt;
63 use std::result;
64 
65 use crate::constants;
66 
67 mod endian_vec;
68 pub use self::endian_vec::*;
69 
70 mod writer;
71 pub use self::writer::*;
72 
73 #[macro_use]
74 mod section;
75 pub use self::section::*;
76 
77 macro_rules! define_id {
78     ($name:ident, $docs:expr) => {
79         #[doc=$docs]
80         #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
81         pub struct $name {
82             base_id: BaseId,
83             index: usize,
84         }
85 
86         impl $name {
87             #[inline]
88             fn new(base_id: BaseId, index: usize) -> Self {
89                 $name { base_id, index }
90             }
91         }
92     };
93 }
94 
95 macro_rules! define_offsets {
96     ($offsets:ident: $id:ident => $offset:ident, $off_doc:expr) => {
97         #[doc=$off_doc]
98         #[derive(Debug)]
99         pub struct $offsets {
100             base_id: BaseId,
101             // We know ids start at 0.
102             offsets: Vec<$offset>,
103         }
104 
105         impl $offsets {
106             /// Return an empty list of offsets.
107             #[inline]
108             pub fn none() -> Self {
109                 $offsets {
110                     base_id: BaseId::default(),
111                     offsets: Vec::new(),
112                 }
113             }
114 
115             /// Get the offset
116             ///
117             /// # Panics
118             ///
119             /// Panics if `id` is invalid.
120             #[inline]
121             pub fn get(&self, id: $id) -> $offset {
122                 debug_assert_eq!(self.base_id, id.base_id);
123                 self.offsets[id.index]
124             }
125 
126             /// Return the number of offsets.
127             #[inline]
128             pub fn count(&self) -> usize {
129                 self.offsets.len()
130             }
131         }
132     };
133 }
134 
135 mod abbrev;
136 pub use self::abbrev::*;
137 
138 mod cfi;
139 pub use self::cfi::*;
140 
141 mod dwarf;
142 pub use self::dwarf::*;
143 
144 mod line;
145 pub use self::line::*;
146 
147 mod loc;
148 pub use self::loc::*;
149 
150 mod op;
151 pub use self::op::*;
152 
153 mod range;
154 pub use self::range::*;
155 
156 mod str;
157 pub use self::str::*;
158 
159 mod unit;
160 pub use self::unit::*;
161 
162 /// An error that occurred when writing.
163 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
164 pub enum Error {
165     /// The given offset is out of bounds.
166     OffsetOutOfBounds,
167     /// The given length is out of bounds.
168     LengthOutOfBounds,
169     /// The attribute value is an invalid for writing.
170     InvalidAttributeValue,
171     /// The value is too large for the encoding form.
172     ValueTooLarge,
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.
180     InvalidAddress,
181     /// The reference is invalid.
182     InvalidReference,
183     /// A requested feature requires a different DWARF version.
184     NeedVersion(u16),
185     /// Strings in line number program have mismatched forms.
186     LineStringFormMismatch,
187     /// The range is empty or otherwise invalid.
188     InvalidRange,
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,
201 }
202 
203 impl fmt::Display for Error {
fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error>204     fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
205         match *self {
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.")
210             }
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)
215             }
216             Error::InitialLengthOverflow => write!(
217                 f,
218                 "The unit length is too large for the requested DWARF format."
219             ),
220             Error::InvalidAddress => write!(f, "The address is invalid."),
221             Error::InvalidReference => write!(f, "The reference is invalid."),
222             Error::NeedVersion(version) => write!(
223                 f,
224                 "A requested feature requires a DWARF version {}.",
225                 version
226             ),
227             Error::LineStringFormMismatch => {
228                 write!(f, "Strings in line number program have mismatched forms.")
229             }
230             Error::InvalidRange => write!(f, "The range is empty or otherwise invalid."),
231             Error::IncompatibleLineProgramEncoding => write!(
232                 f,
233                 "The line number program encoding is incompatible with the unit encoding."
234             ),
235             Error::InvalidFrameCodeOffset(offset) => write!(
236                 f,
237                 "Could not encode code offset ({}) for a frame instruction.",
238                 offset,
239             ),
240             Error::InvalidFrameDataOffset(offset) => write!(
241                 f,
242                 "Could not encode data offset ({}) for a frame instruction.",
243                 offset,
244             ),
245             Error::UnsupportedPointerEncoding(eh_pe) => {
246                 write!(f, "Unsupported eh_frame pointer encoding ({}).", eh_pe)
247             }
248             Error::UnsupportedCfiExpressionReference => {
249                 write!(f, "Unsupported reference in CFI expression.")
250             }
251             Error::UnsupportedExpressionForwardReference => {
252                 write!(f, "Unsupported forward reference in expression.")
253             }
254         }
255     }
256 }
257 
258 impl error::Error for Error {}
259 
260 /// The result of a write.
261 pub type Result<T> = result::Result<T, Error>;
262 
263 /// An address.
264 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
265 pub enum Address {
266     /// A fixed address that does not require relocation.
267     Constant(u64),
268     /// An address that is relative to a symbol which may be relocated.
269     Symbol {
270         /// The symbol that the address is relative to.
271         ///
272         /// The meaning of this value is decided by the writer, but
273         /// will typically be an index into a symbol table.
274         symbol: usize,
275         /// The offset of the address relative to the symbol.
276         ///
277         /// This will typically be used as the addend in a relocation.
278         addend: i64,
279     },
280 }
281 
282 /// A reference to a `.debug_info` entry.
283 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
284 pub enum Reference {
285     /// An external symbol.
286     ///
287     /// The meaning of this value is decided by the writer, but
288     /// will typically be an index into a symbol table.
289     Symbol(usize),
290     /// An entry in the same section.
291     ///
292     /// This only supports references in units that are emitted together.
293     Entry(UnitId, UnitEntryId),
294 }
295 
296 // This type is only used in debug assertions.
297 #[cfg(not(debug_assertions))]
298 type BaseId = ();
299 
300 #[cfg(debug_assertions)]
301 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
302 struct BaseId(usize);
303 
304 #[cfg(debug_assertions)]
305 impl Default for BaseId {
default() -> Self306     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))
310     }
311 }
312 
313 #[cfg(feature = "read")]
314 mod convert {
315     use super::*;
316     use crate::read;
317 
318     pub(crate) use super::unit::convert::*;
319 
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.
324         Read(read::Error),
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.
332         InvalidAddress,
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.
338         InvalidFileIndex,
339         /// A `.debug_line` directory index is invalid.
340         InvalidDirectoryIndex,
341         /// A `.debug_line` line base is invalid.
342         InvalidLineBase,
343         /// A `.debug_line` reference is invalid.
344         InvalidLineRef,
345         /// A `.debug_info` unit entry reference is invalid.
346         InvalidUnitRef,
347         /// A `.debug_info` reference is invalid.
348         InvalidDebugInfoRef,
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.
358         InvalidBranchTarget,
359         /// Writing this unit type is not supported yet.
360         UnsupportedUnitType,
361     }
362 
363     impl fmt::Display for ConvertError {
fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error>364         fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
365             use self::ConvertError::*;
366             match *self {
367                 Read(ref e) => e.fmt(f),
368                 UnsupportedAttributeValue => {
369                     write!(f, "Writing of this attribute value is not implemented yet.")
370                 }
371                 InvalidAttributeValue => write!(
372                     f,
373                     "This attribute value is an invalid name/form combination."
374                 ),
375                 InvalidDebugInfoOffset => write!(
376                     f,
377                     "A `.debug_info` reference does not refer to a valid entry."
378                 ),
379                 InvalidAddress => write!(f, "An address could not be converted."),
380                 UnsupportedLineInstruction => write!(
381                     f,
382                     "Writing this line number instruction is not implemented yet."
383                 ),
384                 UnsupportedLineStringForm => write!(
385                     f,
386                     "Writing this form of line string is not implemented yet."
387                 ),
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.")
396                 }
397                 UnsupportedCfiInstruction => {
398                     write!(f, "Writing this CFI instruction is not implemented yet.")
399                 }
400                 UnsupportedIndirectAddress => {
401                     write!(f, "Writing indirect pointers is not implemented yet.")
402                 }
403                 UnsupportedOperation => write!(
404                     f,
405                     "Writing this expression operation is not implemented yet."
406                 ),
407                 InvalidBranchTarget => write!(f, "Operation branch target is invalid."),
408                 UnsupportedUnitType => write!(f, "Writing this unit type is not supported yet."),
409             }
410         }
411     }
412 
413     impl error::Error for ConvertError {}
414 
415     impl From<read::Error> for ConvertError {
from(e: read::Error) -> Self416         fn from(e: read::Error) -> Self {
417             ConvertError::Read(e)
418         }
419     }
420 
421     /// The result of a conversion.
422     pub type ConvertResult<T> = result::Result<T, ConvertError>;
423 }
424 #[cfg(feature = "read")]
425 pub use self::convert::*;
426