1use core::error;
63use core::fmt;
64use core::result;
65
66use crate::constants;
67
68type FnvIndexMap<T, V> = indexmap::IndexMap<T, V, fnv::FnvBuildHasher>;
69type FnvIndexSet<T> = indexmap::IndexSet<T, fnv::FnvBuildHasher>;
70
71mod endian_vec;
72pub use self::endian_vec::*;
73
74mod writer;
75pub use self::writer::*;
76
77mod relocate;
78pub use self::relocate::*;
79
80#[macro_use]
81mod section;
82pub use self::section::*;
83
84macro_rules! define_id {
85 ($name:ident, $docs:expr) => {
86 #[doc=$docs]
87 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
88 pub struct $name {
89 base_id: BaseId,
90 index: usize,
91 }
92
93 impl $name {
94 #[inline]
95 fn new(base_id: BaseId, index: usize) -> Self {
96 $name { base_id, index }
97 }
98 }
99 };
100}
101
102macro_rules! define_offsets {
103 ($offsets:ident: $id:ident => $offset:ident, $off_doc:expr) => {
104 #[doc=$off_doc]
105 #[derive(Debug)]
106 pub struct $offsets {
107 base_id: BaseId,
108 offsets: Vec<$offset>,
110 }
111
112 impl $offsets {
113 #[inline]
115 pub fn none() -> Self {
116 $offsets {
117 base_id: BaseId::default(),
118 offsets: Vec::new(),
119 }
120 }
121
122 #[inline]
128 pub fn get(&self, id: $id) -> $offset {
129 debug_assert_eq!(self.base_id, id.base_id);
130 self.offsets[id.index]
131 }
132
133 #[inline]
135 pub fn count(&self) -> usize {
136 self.offsets.len()
137 }
138 }
139 };
140}
141
142mod abbrev;
143pub use self::abbrev::*;
144
145mod cfi;
146pub use self::cfi::*;
147
148mod dwarf;
149pub use self::dwarf::*;
150
151mod line;
152pub use self::line::*;
153
154mod loc;
155pub use self::loc::*;
156
157mod op;
158pub use self::op::*;
159
160mod range;
161pub use self::range::*;
162
163mod str;
164pub use self::str::*;
165
166mod unit;
167pub use self::unit::*;
168
169#[derive(Debug, Clone, Copy, PartialEq, Eq)]
171pub enum Error {
172 OffsetOutOfBounds,
174 LengthOutOfBounds,
176 InvalidAttributeValue,
178 ValueTooLarge,
180 UnsupportedWordSize(u8),
182 UnsupportedVersion(u16),
184 InitialLengthOverflow,
186 InvalidAddress,
188 InvalidReference,
190 NeedVersion(u16),
192 LineStringFormMismatch,
194 InvalidRange,
196 IncompatibleLineProgramEncoding,
198 InvalidFrameCodeOffset(u32),
200 InvalidFrameDataOffset(i32),
202 UnsupportedPointerEncoding(constants::DwEhPe),
204 UnsupportedCfiExpressionReference,
206 UnsupportedExpressionForwardReference,
208}
209
210impl fmt::Display for Error {
211 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> result::Result<(), fmt::Error> {
212 match *self {
213 Error::OffsetOutOfBounds => write!(f, "The given offset is out of bounds."),
214 Error::LengthOutOfBounds => write!(f, "The given length is out of bounds."),
215 Error::InvalidAttributeValue => {
216 write!(f, "The attribute value is an invalid for writing.")
217 }
218 Error::ValueTooLarge => write!(f, "The value is too large for the encoding form."),
219 Error::UnsupportedWordSize(size) => write!(f, "Unsupported word size: {}", size),
220 Error::UnsupportedVersion(version) => {
221 write!(f, "Unsupported DWARF version: {}", version)
222 }
223 Error::InitialLengthOverflow => write!(
224 f,
225 "The unit length is too large for the requested DWARF format."
226 ),
227 Error::InvalidAddress => write!(f, "The address is invalid."),
228 Error::InvalidReference => write!(f, "The reference is invalid."),
229 Error::NeedVersion(version) => write!(
230 f,
231 "A requested feature requires a DWARF version {}.",
232 version
233 ),
234 Error::LineStringFormMismatch => {
235 write!(f, "Strings in line number program have mismatched forms.")
236 }
237 Error::InvalidRange => write!(f, "The range is empty or otherwise invalid."),
238 Error::IncompatibleLineProgramEncoding => write!(
239 f,
240 "The line number program encoding is incompatible with the unit encoding."
241 ),
242 Error::InvalidFrameCodeOffset(offset) => write!(
243 f,
244 "Could not encode code offset ({}) for a frame instruction.",
245 offset,
246 ),
247 Error::InvalidFrameDataOffset(offset) => write!(
248 f,
249 "Could not encode data offset ({}) for a frame instruction.",
250 offset,
251 ),
252 Error::UnsupportedPointerEncoding(eh_pe) => {
253 write!(f, "Unsupported eh_frame pointer encoding ({}).", eh_pe)
254 }
255 Error::UnsupportedCfiExpressionReference => {
256 write!(f, "Unsupported reference in CFI expression.")
257 }
258 Error::UnsupportedExpressionForwardReference => {
259 write!(f, "Unsupported forward reference in expression.")
260 }
261 }
262 }
263}
264
265impl error::Error for Error {}
266
267pub type Result<T> = result::Result<T, Error>;
269
270#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
272pub enum Address {
273 Constant(u64),
275 Symbol {
277 symbol: usize,
282 addend: i64,
286 },
287}
288
289#[cfg(not(debug_assertions))]
291type BaseId = ();
292
293#[cfg(debug_assertions)]
294#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
295struct BaseId(usize);
296
297#[cfg(debug_assertions)]
298impl Default for BaseId {
299 fn default() -> Self {
300 use core::sync::atomic;
301 static BASE_ID: atomic::AtomicUsize = atomic::AtomicUsize::new(0);
302 BaseId(BASE_ID.fetch_add(1, atomic::Ordering::Relaxed))
303 }
304}
305
306#[cfg(feature = "read")]
307mod convert {
308 use super::*;
309 use crate::read;
310
311 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
313 pub enum ConvertError {
314 Read(read::Error),
316 Write(Error),
318 UnsupportedAttributeValue,
320 InvalidAttributeValue,
322 InvalidDebugInfoOffset,
324 InvalidAddress,
326 UnsupportedLineInstruction,
328 UnsupportedLineStringForm,
330 MissingLineEndSequence,
332 MissingCompilationName,
334 MissingCompilationDirectory,
336 InvalidFileIndex,
338 InvalidDirectoryIndex,
340 InvalidLineBase,
342 InvalidLineRef,
344 InvalidUnitRef,
346 InvalidDebugInfoRef,
348 InvalidRangeRelativeAddress,
350 UnsupportedCfiInstruction,
352 UnsupportedIndirectAddress,
354 UnsupportedOperation,
356 InvalidBranchTarget,
358 UnsupportedUnitType,
360 }
361
362 impl fmt::Display for ConvertError {
363 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> result::Result<(), fmt::Error> {
364 use self::ConvertError::*;
365 match *self {
366 Read(ref e) => e.fmt(f),
367 Write(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 MissingLineEndSequence => write!(
389 f,
390 "A `DW_LNE_end_sequence` instruction was missing at the end of a sequence."
391 ),
392 MissingCompilationName => write!(f, "The name of the compilation unit is missing."),
393 MissingCompilationDirectory => {
394 write!(f, "The path of the compilation directory is missing.")
395 }
396 InvalidFileIndex => write!(f, "A `.debug_line` file index is invalid."),
397 InvalidDirectoryIndex => write!(f, "A `.debug_line` directory index is invalid."),
398 InvalidLineBase => write!(f, "A `.debug_line` line base is invalid."),
399 InvalidLineRef => write!(f, "A `.debug_line` reference is invalid."),
400 InvalidUnitRef => write!(f, "A `.debug_info` unit entry reference is invalid."),
401 InvalidDebugInfoRef => write!(f, "A `.debug_info` reference is invalid."),
402 InvalidRangeRelativeAddress => {
403 write!(f, "Invalid relative address in a range list.")
404 }
405 UnsupportedCfiInstruction => {
406 write!(f, "Writing this CFI instruction is not implemented yet.")
407 }
408 UnsupportedIndirectAddress => {
409 write!(f, "Writing indirect pointers is not implemented yet.")
410 }
411 UnsupportedOperation => write!(
412 f,
413 "Writing this expression operation is not implemented yet."
414 ),
415 InvalidBranchTarget => write!(f, "Operation branch target is invalid."),
416 UnsupportedUnitType => write!(f, "Writing this unit type is not supported yet."),
417 }
418 }
419 }
420
421 impl error::Error for ConvertError {}
422
423 impl From<read::Error> for ConvertError {
424 fn from(e: read::Error) -> Self {
425 ConvertError::Read(e)
426 }
427 }
428
429 impl From<Error> for ConvertError {
430 fn from(e: Error) -> Self {
431 ConvertError::Write(e)
432 }
433 }
434
435 pub type ConvertResult<T> = result::Result<T, ConvertError>;
437}
438#[cfg(feature = "read")]
439pub use self::convert::*;