2 use std
::ops
::{Deref, DerefMut}
;
3 use std
::{slice, usize}
;
6 DebugAbbrevOffset
, DebugInfoOffset
, DebugLineOffset
, DebugMacinfoOffset
, DebugMacroOffset
,
7 DebugStrOffset
, DebugTypeSignature
, DwoId
, Encoding
, Format
, SectionId
,
10 use crate::leb128
::write
::{sleb128_size, uleb128_size}
;
12 Abbreviation
, AbbreviationTable
, Address
, AttributeSpecification
, BaseId
, DebugLineStrOffsets
,
13 DebugStrOffsets
, Error
, Expression
, FileId
, LineProgram
, LineStringId
, LocationListId
,
14 LocationListOffsets
, LocationListTable
, RangeListId
, RangeListOffsets
, RangeListTable
,
15 Reference
, Result
, Section
, Sections
, StringId
, Writer
,
18 define_id
!(UnitId
, "An identifier for a unit in a `UnitTable`.");
20 define_id
!(UnitEntryId
, "An identifier for an entry in a `Unit`.");
22 /// A table of units that will be stored in the `.debug_info` section.
23 #[derive(Debug, Default)]
24 pub struct UnitTable
{
30 /// Create a new unit and add it to the table.
32 /// `address_size` must be in bytes.
34 /// Returns the `UnitId` of the new unit.
36 pub fn add(&mut self, unit
: Unit
) -> UnitId
{
37 let id
= UnitId
::new(self.base_id
, self.units
.len());
38 self.units
.push(unit
);
42 /// Return the number of units.
44 pub fn count(&self) -> usize {
48 /// Return the id of a unit.
52 /// Panics if `index >= self.count()`.
54 pub fn id(&self, index
: usize) -> UnitId
{
55 assert
!(index
< self.count());
56 UnitId
::new(self.base_id
, index
)
59 /// Get a reference to a unit.
63 /// Panics if `id` is invalid.
65 pub fn get(&self, id
: UnitId
) -> &Unit
{
66 debug_assert_eq
!(self.base_id
, id
.base_id
);
70 /// Get a mutable reference to a unit.
74 /// Panics if `id` is invalid.
76 pub fn get_mut(&mut self, id
: UnitId
) -> &mut Unit
{
77 debug_assert_eq
!(self.base_id
, id
.base_id
);
78 &mut self.units
[id
.index
]
81 /// Write the units to the given sections.
83 /// `strings` must contain the `.debug_str` offsets of the corresponding
85 pub fn write
<W
: Writer
>(
87 sections
: &mut Sections
<W
>,
88 line_strings
: &DebugLineStrOffsets
,
89 strings
: &DebugStrOffsets
,
90 ) -> Result
<DebugInfoOffsets
> {
91 let mut offsets
= DebugInfoOffsets
{
92 base_id
: self.base_id
,
95 for unit
in &mut self.units
{
96 // TODO: maybe share abbreviation tables
97 let abbrev_offset
= sections
.debug_abbrev
.offset();
98 let mut abbrevs
= AbbreviationTable
::default();
100 offsets
.units
.push(unit
.write(
108 abbrevs
.write(&mut sections
.debug_abbrev
)?
;
112 &mut sections
.debug_info_refs
,
113 &mut sections
.debug_info
.0,
117 &mut sections
.debug_loc_refs
,
118 &mut sections
.debug_loc
.0,
122 &mut sections
.debug_loclists_refs
,
123 &mut sections
.debug_loclists
.0,
131 fn write_section_refs
<W
: Writer
>(
132 references
: &mut Vec
<DebugInfoReference
>,
134 offsets
: &DebugInfoOffsets
,
136 for r
in references
.drain(..) {
137 let entry_offset
= offsets
.entry(r
.unit
, r
.entry
).0;
138 debug_assert_ne
!(entry_offset
, 0);
139 w
.write_offset_at(r
.offset
, entry_offset
, SectionId
::DebugInfo
, r
.size
)?
;
144 /// A unit's debugging information.
148 /// The encoding parameters for this unit.
150 /// The line number program for this unit.
151 pub line_program
: LineProgram
,
152 /// A table of range lists used by this unit.
153 pub ranges
: RangeListTable
,
154 /// A table of location lists used by this unit.
155 pub locations
: LocationListTable
,
156 /// All entries in this unit. The order is unrelated to the tree order.
158 // - entries form a tree
159 // - entries can be added in any order
160 // - entries have a fixed id
161 // - able to quickly lookup an entry from its id
162 // Limitations of current implemention:
163 // - mutable iteration of children is messy due to borrow checker
164 entries
: Vec
<DebuggingInformationEntry
>,
165 /// The index of the root entry in entries.
170 /// Create a new `Unit`.
171 pub fn new(encoding
: Encoding
, line_program
: LineProgram
) -> Self {
172 let base_id
= BaseId
::default();
173 let ranges
= RangeListTable
::default();
174 let locations
= LocationListTable
::default();
175 let mut entries
= Vec
::new();
176 let root
= DebuggingInformationEntry
::new(
180 constants
::DW_TAG_compile_unit
,
193 /// Return the encoding parameters for this unit.
195 pub fn encoding(&self) -> Encoding
{
199 /// Return the DWARF version for this unit.
201 pub fn version(&self) -> u16 {
202 self.encoding
.version
205 /// Return the address size in bytes for this unit.
207 pub fn address_size(&self) -> u8 {
208 self.encoding
.address_size
211 /// Return the DWARF format for this unit.
213 pub fn format(&self) -> Format
{
217 /// Return the number of `DebuggingInformationEntry`s created for this unit.
219 /// This includes entries that no longer have a parent.
221 pub fn count(&self) -> usize {
225 /// Return the id of the root entry.
227 pub fn root(&self) -> UnitEntryId
{
231 /// Add a new `DebuggingInformationEntry` to this unit and return its id.
233 /// The `parent` must be within the same unit.
237 /// Panics if `parent` is invalid.
239 pub fn add(&mut self, parent
: UnitEntryId
, tag
: constants
::DwTag
) -> UnitEntryId
{
240 debug_assert_eq
!(self.base_id
, parent
.base_id
);
241 DebuggingInformationEntry
::new(self.base_id
, &mut self.entries
, Some(parent
), tag
)
244 /// Get a reference to an entry.
248 /// Panics if `id` is invalid.
250 pub fn get(&self, id
: UnitEntryId
) -> &DebuggingInformationEntry
{
251 debug_assert_eq
!(self.base_id
, id
.base_id
);
252 &self.entries
[id
.index
]
255 /// Get a mutable reference to an entry.
259 /// Panics if `id` is invalid.
261 pub fn get_mut(&mut self, id
: UnitEntryId
) -> &mut DebuggingInformationEntry
{
262 debug_assert_eq
!(self.base_id
, id
.base_id
);
263 &mut self.entries
[id
.index
]
266 /// Return true if `self.line_program` is used by a DIE.
267 fn line_program_in_use(&self) -> bool
{
268 if self.line_program
.is_none() {
271 if !self.line_program
.is_empty() {
275 for entry
in &self.entries
{
276 for attr
in &entry
.attrs
{
277 if let AttributeValue
::FileIndex(Some(_
)) = attr
.value
{
286 /// Write the unit to the given sections.
287 pub(crate) fn write
<W
: Writer
>(
289 sections
: &mut Sections
<W
>,
290 abbrev_offset
: DebugAbbrevOffset
,
291 abbrevs
: &mut AbbreviationTable
,
292 line_strings
: &DebugLineStrOffsets
,
293 strings
: &DebugStrOffsets
,
294 ) -> Result
<UnitOffsets
> {
295 let line_program
= if self.line_program_in_use() {
296 self.entries
[self.root
.index
]
297 .set(constants
::DW_AT_stmt_list
, AttributeValue
::LineProgramRef
);
298 Some(self.line_program
.write(
299 &mut sections
.debug_line
,
305 self.entries
[self.root
.index
].delete(constants
::DW_AT_stmt_list
);
309 // TODO: use .debug_types for type units in DWARF v4.
310 let w
= &mut sections
.debug_info
;
312 let mut offsets
= UnitOffsets
{
313 base_id
: self.base_id
,
315 // Entries can be written in any order, so create the complete vec now.
316 entries
: vec
![EntryOffset
::none(); self.entries
.len()],
319 let length_offset
= w
.write_initial_length(self.format())?
;
320 let length_base
= w
.len();
322 w
.write_u16(self.version())?
;
323 if 2 <= self.version() && self.version() <= 4 {
326 SectionId
::DebugAbbrev
,
327 self.format().word_size(),
329 w
.write_u8(self.address_size())?
;
330 } else if self.version() == 5 {
331 w
.write_u8(constants
::DW_UT_compile
.0)?
;
332 w
.write_u8(self.address_size())?
;
335 SectionId
::DebugAbbrev
,
336 self.format().word_size(),
339 return Err(Error
::UnsupportedVersion(self.version()));
342 // Calculate all DIE offsets, so that we are able to output references to them.
343 // However, references to base types in expressions use ULEB128, so base types
344 // must be moved to the front before we can calculate offsets.
345 self.reorder_base_types();
346 let mut offset
= w
.len();
347 self.entries
[self.root
.index
].calculate_offsets(
354 let range_lists
= self.ranges
.write(sections
, self.encoding
)?
;
355 // Location lists can't be written until we have DIE offsets.
358 .write(sections
, self.encoding
, Some(&offsets
))?
;
360 let w
= &mut sections
.debug_info
;
361 let mut unit_refs
= Vec
::new();
362 self.entries
[self.root
.index
].write(
364 &mut sections
.debug_info_refs
,
376 let length
= (w
.len() - length_base
) as u64;
377 w
.write_initial_length_at(length_offset
, length
, self.format())?
;
379 for (offset
, entry
) in unit_refs
{
380 // This does not need relocation.
383 offsets
.unit_offset(entry
),
384 self.format().word_size(),
391 /// Reorder base types to come first so that typed stack operations
392 /// can get their offset.
393 fn reorder_base_types(&mut self) {
394 let root
= &self.entries
[self.root
.index
];
395 let mut root_children
= Vec
::with_capacity(root
.children
.len());
396 for entry
in &root
.children
{
397 if self.entries
[entry
.index
].tag
== constants
::DW_TAG_base_type
{
398 root_children
.push(*entry
);
401 for entry
in &root
.children
{
402 if self.entries
[entry
.index
].tag
!= constants
::DW_TAG_base_type
{
403 root_children
.push(*entry
);
406 self.entries
[self.root
.index
].children
= root_children
;
410 /// A Debugging Information Entry (DIE).
412 /// DIEs have a set of attributes and optionally have children DIEs as well.
414 /// DIEs form a tree without any cycles. This is enforced by specifying the
415 /// parent when creating a DIE, and disallowing changes of parent.
417 pub struct DebuggingInformationEntry
{
419 parent
: Option
<UnitEntryId
>,
420 tag
: constants
::DwTag
,
421 /// Whether to emit `DW_AT_sibling`.
423 attrs
: Vec
<Attribute
>,
424 children
: Vec
<UnitEntryId
>,
427 impl DebuggingInformationEntry
{
428 /// Create a new `DebuggingInformationEntry`.
432 /// Panics if `parent` is invalid.
433 #[allow(clippy::new_ret_no_self)]
436 entries
: &mut Vec
<DebuggingInformationEntry
>,
437 parent
: Option
<UnitEntryId
>,
438 tag
: constants
::DwTag
,
440 let id
= UnitEntryId
::new(base_id
, entries
.len());
441 entries
.push(DebuggingInformationEntry
{
447 children
: Vec
::new(),
449 if let Some(parent
) = parent
{
450 debug_assert_eq
!(base_id
, parent
.base_id
);
451 assert_ne
!(parent
, id
);
452 entries
[parent
.index
].children
.push(id
);
457 /// Return the id of this entry.
459 pub fn id(&self) -> UnitEntryId
{
463 /// Return the parent of this entry.
465 pub fn parent(&self) -> Option
<UnitEntryId
> {
469 /// Return the tag of this entry.
471 pub fn tag(&self) -> constants
::DwTag
{
475 /// Return `true` if a `DW_AT_sibling` attribute will be emitted.
477 pub fn sibling(&self) -> bool
{
481 /// Set whether a `DW_AT_sibling` attribute will be emitted.
483 /// The attribute will only be emitted if the DIE has children.
485 pub fn set_sibling(&mut self, sibling
: bool
) {
486 self.sibling
= sibling
;
489 /// Iterate over the attributes of this entry.
491 pub fn attrs(&self) -> slice
::Iter
<Attribute
> {
495 /// Iterate over the attributes of this entry for modification.
497 pub fn attrs_mut(&mut self) -> slice
::IterMut
<Attribute
> {
498 self.attrs
.iter_mut()
501 /// Get an attribute.
502 pub fn get(&self, name
: constants
::DwAt
) -> Option
<&AttributeValue
> {
505 .find(|attr
| attr
.name
== name
)
506 .map(|attr
| &attr
.value
)
509 /// Get an attribute for modification.
510 pub fn get_mut(&mut self, name
: constants
::DwAt
) -> Option
<&mut AttributeValue
> {
513 .find(|attr
| attr
.name
== name
)
514 .map(|attr
| &mut attr
.value
)
517 /// Set an attribute.
519 /// Replaces any existing attribute with the same name.
523 /// Panics if `name` is `DW_AT_sibling`. Use `set_sibling` instead.
524 pub fn set(&mut self, name
: constants
::DwAt
, value
: AttributeValue
) {
525 assert_ne
!(name
, constants
::DW_AT_sibling
);
526 if let Some(attr
) = self.attrs
.iter_mut().find(|attr
| attr
.name
== name
) {
530 self.attrs
.push(Attribute { name, value }
);
533 /// Delete an attribute.
535 /// Replaces any existing attribute with the same name.
536 pub fn delete(&mut self, name
: constants
::DwAt
) {
537 self.attrs
.retain(|x
| x
.name
!= name
);
540 /// Iterate over the children of this entry.
542 /// Note: use `Unit::add` to add a new child to this entry.
544 pub fn children(&self) -> slice
::Iter
<UnitEntryId
> {
548 /// Return the type abbreviation for this DIE.
549 fn abbreviation(&self, encoding
: Encoding
) -> Result
<Abbreviation
> {
550 let mut attrs
= Vec
::new();
552 if self.sibling
&& !self.children
.is_empty() {
553 let form
= match encoding
.format
{
554 Format
::Dwarf32
=> constants
::DW_FORM_ref4
,
555 Format
::Dwarf64
=> constants
::DW_FORM_ref8
,
557 attrs
.push(AttributeSpecification
::new(constants
::DW_AT_sibling
, form
));
560 for attr
in &self.attrs
{
561 attrs
.push(attr
.specification(encoding
)?
);
564 Ok(Abbreviation
::new(
566 !self.children
.is_empty(),
571 fn calculate_offsets(
575 offsets
: &mut UnitOffsets
,
576 abbrevs
: &mut AbbreviationTable
,
578 offsets
.entries
[self.id
.index
].offset
= DebugInfoOffset(*offset
);
579 offsets
.entries
[self.id
.index
].abbrev
= abbrevs
.add(self.abbreviation(unit
.encoding())?
);
580 *offset
+= self.size(unit
, offsets
);
581 if !self.children
.is_empty() {
582 for child
in &self.children
{
583 unit
.entries
[child
.index
].calculate_offsets(unit
, offset
, offsets
, abbrevs
)?
;
591 fn size(&self, unit
: &Unit
, offsets
: &UnitOffsets
) -> usize {
592 let mut size
= uleb128_size(offsets
.abbrev(self.id
));
593 if self.sibling
&& !self.children
.is_empty() {
594 size
+= unit
.format().word_size() as usize;
596 for attr
in &self.attrs
{
597 size
+= attr
.value
.size(unit
, offsets
);
602 /// Write the entry to the given sections.
603 #[allow(clippy::too_many_arguments)]
606 w
: &mut DebugInfo
<W
>,
607 debug_info_refs
: &mut Vec
<DebugInfoReference
>,
608 unit_refs
: &mut Vec
<(DebugInfoOffset
, UnitEntryId
)>,
610 offsets
: &mut UnitOffsets
,
611 abbrevs
: &mut AbbreviationTable
,
612 line_program
: Option
<DebugLineOffset
>,
613 line_strings
: &DebugLineStrOffsets
,
614 strings
: &DebugStrOffsets
,
615 range_lists
: &RangeListOffsets
,
616 loc_lists
: &LocationListOffsets
,
618 debug_assert_eq
!(offsets
.debug_info_offset(self.id
), w
.offset());
619 w
.write_uleb128(offsets
.abbrev(self.id
))?
;
621 let sibling_offset
= if self.sibling
&& !self.children
.is_empty() {
622 let offset
= w
.offset();
623 w
.write_udata(0, unit
.format().word_size())?
;
629 for attr
in &self.attrs
{
644 if !self.children
.is_empty() {
645 for child
in &self.children
{
646 unit
.entries
[child
.index
].write(
664 if let Some(offset
) = sibling_offset
{
665 let next_offset
= (w
.offset().0 - offsets
.unit
.0) as u64;
666 // This does not need relocation.
667 w
.write_udata_at(offset
.0, next_offset
, unit
.format().word_size())?
;
673 /// An attribute in a `DebuggingInformationEntry`, consisting of a name and
674 /// associated value.
675 #[derive(Debug, Clone, PartialEq, Eq)]
676 pub struct Attribute
{
677 name
: constants
::DwAt
,
678 value
: AttributeValue
,
682 /// Get the name of this attribute.
684 pub fn name(&self) -> constants
::DwAt
{
688 /// Get the value of this attribute.
690 pub fn get(&self) -> &AttributeValue
{
694 /// Set the value of this attribute.
696 pub fn set(&mut self, value
: AttributeValue
) {
700 /// Return the type specification for this attribute.
701 fn specification(&self, encoding
: Encoding
) -> Result
<AttributeSpecification
> {
702 Ok(AttributeSpecification
::new(
704 self.value
.form(encoding
)?
,
709 /// The value of an attribute in a `DebuggingInformationEntry`.
710 #[derive(Debug, Clone, PartialEq, Eq)]
711 pub enum AttributeValue
{
712 /// "Refers to some location in the address space of the described program."
715 /// A slice of an arbitrary number of bytes.
718 /// A one byte constant data value. How to interpret the byte depends on context.
720 /// From section 7 of the standard: "Depending on context, it may be a
721 /// signed integer, an unsigned integer, a floating-point constant, or
725 /// A two byte constant data value. How to interpret the bytes depends on context.
727 /// This value will be converted to the target endian before writing.
729 /// From section 7 of the standard: "Depending on context, it may be a
730 /// signed integer, an unsigned integer, a floating-point constant, or
734 /// A four byte constant data value. How to interpret the bytes depends on context.
736 /// This value will be converted to the target endian before writing.
738 /// From section 7 of the standard: "Depending on context, it may be a
739 /// signed integer, an unsigned integer, a floating-point constant, or
743 /// An eight byte constant data value. How to interpret the bytes depends on context.
745 /// This value will be converted to the target endian before writing.
747 /// From section 7 of the standard: "Depending on context, it may be a
748 /// signed integer, an unsigned integer, a floating-point constant, or
752 /// A signed integer constant.
755 /// An unsigned integer constant.
758 /// "The information bytes contain a DWARF expression (see Section 2.5) or
759 /// location description (see Section 2.6)."
762 /// A boolean that indicates presence or absence of the attribute.
765 /// An attribute that is always present.
768 /// A reference to a `DebuggingInformationEntry` in this unit.
769 UnitRef(UnitEntryId
),
771 /// A reference to a `DebuggingInformationEntry` in a potentially different unit.
772 DebugInfoRef(Reference
),
774 /// An offset into the `.debug_info` section of the supplementary object file.
776 /// The API does not currently assist with generating this offset.
777 /// This variant will be removed from the API once support for writing
778 /// supplementary object files is implemented.
779 DebugInfoRefSup(DebugInfoOffset
),
781 /// A reference to a line number program.
784 /// A reference to a location list.
785 LocationListRef(LocationListId
),
787 /// An offset into the `.debug_macinfo` section.
789 /// The API does not currently assist with generating this offset.
790 /// This variant will be removed from the API once support for writing
791 /// `.debug_macinfo` sections is implemented.
792 DebugMacinfoRef(DebugMacinfoOffset
),
794 /// An offset into the `.debug_macro` section.
796 /// The API does not currently assist with generating this offset.
797 /// This variant will be removed from the API once support for writing
798 /// `.debug_macro` sections is implemented.
799 DebugMacroRef(DebugMacroOffset
),
801 /// A reference to a range list.
802 RangeListRef(RangeListId
),
804 /// A type signature.
806 /// The API does not currently assist with generating this signature.
807 /// This variant will be removed from the API once support for writing
808 /// `.debug_types` sections is implemented.
809 DebugTypesRef(DebugTypeSignature
),
811 /// A reference to a string in the `.debug_str` section.
814 /// An offset into the `.debug_str` section of the supplementary object file.
816 /// The API does not currently assist with generating this offset.
817 /// This variant will be removed from the API once support for writing
818 /// supplementary object files is implemented.
819 DebugStrRefSup(DebugStrOffset
),
821 /// A reference to a string in the `.debug_line_str` section.
822 LineStringRef(LineStringId
),
824 /// A slice of bytes representing a string. Must not include null bytes.
825 /// Not guaranteed to be UTF-8 or anything like that.
828 /// The value of a `DW_AT_encoding` attribute.
829 Encoding(constants
::DwAte
),
831 /// The value of a `DW_AT_decimal_sign` attribute.
832 DecimalSign(constants
::DwDs
),
834 /// The value of a `DW_AT_endianity` attribute.
835 Endianity(constants
::DwEnd
),
837 /// The value of a `DW_AT_accessibility` attribute.
838 Accessibility(constants
::DwAccess
),
840 /// The value of a `DW_AT_visibility` attribute.
841 Visibility(constants
::DwVis
),
843 /// The value of a `DW_AT_virtuality` attribute.
844 Virtuality(constants
::DwVirtuality
),
846 /// The value of a `DW_AT_language` attribute.
847 Language(constants
::DwLang
),
849 /// The value of a `DW_AT_address_class` attribute.
850 AddressClass(constants
::DwAddr
),
852 /// The value of a `DW_AT_identifier_case` attribute.
853 IdentifierCase(constants
::DwId
),
855 /// The value of a `DW_AT_calling_convention` attribute.
856 CallingConvention(constants
::DwCc
),
858 /// The value of a `DW_AT_inline` attribute.
859 Inline(constants
::DwInl
),
861 /// The value of a `DW_AT_ordering` attribute.
862 Ordering(constants
::DwOrd
),
864 /// An index into the filename entries from the line number information
865 /// table for the unit containing this value.
866 FileIndex(Option
<FileId
>),
869 impl AttributeValue
{
870 /// Return the form that will be used to encode this value.
871 pub fn form(&self, encoding
: Encoding
) -> Result
<constants
::DwForm
> {
872 // TODO: missing forms:
873 // - DW_FORM_indirect
874 // - DW_FORM_implicit_const
875 // - FW_FORM_block1/block2/block4
876 // - DW_FORM_str/strx1/strx2/strx3/strx4
877 // - DW_FORM_addrx/addrx1/addrx2/addrx3/addrx4
879 // - DW_FORM_line_strp
880 // - DW_FORM_loclistx
881 // - DW_FORM_rnglistx
882 let form
= match *self {
883 AttributeValue
::Address(_
) => constants
::DW_FORM_addr
,
884 AttributeValue
::Block(_
) => constants
::DW_FORM_block
,
885 AttributeValue
::Data1(_
) => constants
::DW_FORM_data1
,
886 AttributeValue
::Data2(_
) => constants
::DW_FORM_data2
,
887 AttributeValue
::Data4(_
) => constants
::DW_FORM_data4
,
888 AttributeValue
::Data8(_
) => constants
::DW_FORM_data8
,
889 AttributeValue
::Exprloc(_
) => constants
::DW_FORM_exprloc
,
890 AttributeValue
::Flag(_
) => constants
::DW_FORM_flag
,
891 AttributeValue
::FlagPresent
=> constants
::DW_FORM_flag_present
,
892 AttributeValue
::UnitRef(_
) => {
893 // Using a fixed size format lets us write a placeholder before we know
895 match encoding
.format
{
896 Format
::Dwarf32
=> constants
::DW_FORM_ref4
,
897 Format
::Dwarf64
=> constants
::DW_FORM_ref8
,
900 AttributeValue
::DebugInfoRef(_
) => constants
::DW_FORM_ref_addr
,
901 AttributeValue
::DebugInfoRefSup(_
) => {
902 // TODO: should this depend on the size of supplementary section?
903 match encoding
.format
{
904 Format
::Dwarf32
=> constants
::DW_FORM_ref_sup4
,
905 Format
::Dwarf64
=> constants
::DW_FORM_ref_sup8
,
908 AttributeValue
::LineProgramRef
909 | AttributeValue
::LocationListRef(_
)
910 | AttributeValue
::DebugMacinfoRef(_
)
911 | AttributeValue
::DebugMacroRef(_
)
912 | AttributeValue
::RangeListRef(_
) => {
913 if encoding
.version
== 2 || encoding
.version
== 3 {
914 match encoding
.format
{
915 Format
::Dwarf32
=> constants
::DW_FORM_data4
,
916 Format
::Dwarf64
=> constants
::DW_FORM_data8
,
919 constants
::DW_FORM_sec_offset
922 AttributeValue
::DebugTypesRef(_
) => constants
::DW_FORM_ref_sig8
,
923 AttributeValue
::StringRef(_
) => constants
::DW_FORM_strp
,
924 AttributeValue
::DebugStrRefSup(_
) => constants
::DW_FORM_strp_sup
,
925 AttributeValue
::LineStringRef(_
) => constants
::DW_FORM_line_strp
,
926 AttributeValue
::String(_
) => constants
::DW_FORM_string
,
927 AttributeValue
::Encoding(_
)
928 | AttributeValue
::DecimalSign(_
)
929 | AttributeValue
::Endianity(_
)
930 | AttributeValue
::Accessibility(_
)
931 | AttributeValue
::Visibility(_
)
932 | AttributeValue
::Virtuality(_
)
933 | AttributeValue
::Language(_
)
934 | AttributeValue
::AddressClass(_
)
935 | AttributeValue
::IdentifierCase(_
)
936 | AttributeValue
::CallingConvention(_
)
937 | AttributeValue
::Inline(_
)
938 | AttributeValue
::Ordering(_
)
939 | AttributeValue
::FileIndex(_
)
940 | AttributeValue
::Udata(_
) => constants
::DW_FORM_udata
,
941 AttributeValue
::Sdata(_
) => constants
::DW_FORM_sdata
,
946 fn size(&self, unit
: &Unit
, offsets
: &UnitOffsets
) -> usize {
947 macro_rules
! debug_assert_form
{
949 debug_assert_eq
!(self.form(unit
.encoding()).unwrap(), $form
)
953 AttributeValue
::Address(_
) => {
954 debug_assert_form
!(constants
::DW_FORM_addr
);
955 unit
.address_size() as usize
957 AttributeValue
::Block(ref val
) => {
958 debug_assert_form
!(constants
::DW_FORM_block
);
959 uleb128_size(val
.len() as u64) + val
.len()
961 AttributeValue
::Data1(_
) => {
962 debug_assert_form
!(constants
::DW_FORM_data1
);
965 AttributeValue
::Data2(_
) => {
966 debug_assert_form
!(constants
::DW_FORM_data2
);
969 AttributeValue
::Data4(_
) => {
970 debug_assert_form
!(constants
::DW_FORM_data4
);
973 AttributeValue
::Data8(_
) => {
974 debug_assert_form
!(constants
::DW_FORM_data8
);
977 AttributeValue
::Sdata(val
) => {
978 debug_assert_form
!(constants
::DW_FORM_sdata
);
981 AttributeValue
::Udata(val
) => {
982 debug_assert_form
!(constants
::DW_FORM_udata
);
985 AttributeValue
::Exprloc(ref val
) => {
986 debug_assert_form
!(constants
::DW_FORM_exprloc
);
987 let size
= val
.size(unit
.encoding(), Some(offsets
));
988 uleb128_size(size
as u64) + size
990 AttributeValue
::Flag(_
) => {
991 debug_assert_form
!(constants
::DW_FORM_flag
);
994 AttributeValue
::FlagPresent
=> {
995 debug_assert_form
!(constants
::DW_FORM_flag_present
);
998 AttributeValue
::UnitRef(_
) => {
999 match unit
.format() {
1000 Format
::Dwarf32
=> debug_assert_form
!(constants
::DW_FORM_ref4
),
1001 Format
::Dwarf64
=> debug_assert_form
!(constants
::DW_FORM_ref8
),
1003 unit
.format().word_size() as usize
1005 AttributeValue
::DebugInfoRef(_
) => {
1006 debug_assert_form
!(constants
::DW_FORM_ref_addr
);
1007 if unit
.version() == 2 {
1008 unit
.address_size() as usize
1010 unit
.format().word_size() as usize
1013 AttributeValue
::DebugInfoRefSup(_
) => {
1014 match unit
.format() {
1015 Format
::Dwarf32
=> debug_assert_form
!(constants
::DW_FORM_ref_sup4
),
1016 Format
::Dwarf64
=> debug_assert_form
!(constants
::DW_FORM_ref_sup8
),
1018 unit
.format().word_size() as usize
1020 AttributeValue
::LineProgramRef
=> {
1021 if unit
.version() >= 4 {
1022 debug_assert_form
!(constants
::DW_FORM_sec_offset
);
1024 unit
.format().word_size() as usize
1026 AttributeValue
::LocationListRef(_
) => {
1027 if unit
.version() >= 4 {
1028 debug_assert_form
!(constants
::DW_FORM_sec_offset
);
1030 unit
.format().word_size() as usize
1032 AttributeValue
::DebugMacinfoRef(_
) => {
1033 if unit
.version() >= 4 {
1034 debug_assert_form
!(constants
::DW_FORM_sec_offset
);
1036 unit
.format().word_size() as usize
1038 AttributeValue
::DebugMacroRef(_
) => {
1039 if unit
.version() >= 4 {
1040 debug_assert_form
!(constants
::DW_FORM_sec_offset
);
1042 unit
.format().word_size() as usize
1044 AttributeValue
::RangeListRef(_
) => {
1045 if unit
.version() >= 4 {
1046 debug_assert_form
!(constants
::DW_FORM_sec_offset
);
1048 unit
.format().word_size() as usize
1050 AttributeValue
::DebugTypesRef(_
) => {
1051 debug_assert_form
!(constants
::DW_FORM_ref_sig8
);
1054 AttributeValue
::StringRef(_
) => {
1055 debug_assert_form
!(constants
::DW_FORM_strp
);
1056 unit
.format().word_size() as usize
1058 AttributeValue
::DebugStrRefSup(_
) => {
1059 debug_assert_form
!(constants
::DW_FORM_strp_sup
);
1060 unit
.format().word_size() as usize
1062 AttributeValue
::LineStringRef(_
) => {
1063 debug_assert_form
!(constants
::DW_FORM_line_strp
);
1064 unit
.format().word_size() as usize
1066 AttributeValue
::String(ref val
) => {
1067 debug_assert_form
!(constants
::DW_FORM_string
);
1070 AttributeValue
::Encoding(val
) => {
1071 debug_assert_form
!(constants
::DW_FORM_udata
);
1072 uleb128_size(val
.0 as u64)
1074 AttributeValue
::DecimalSign(val
) => {
1075 debug_assert_form
!(constants
::DW_FORM_udata
);
1076 uleb128_size(val
.0 as u64)
1078 AttributeValue
::Endianity(val
) => {
1079 debug_assert_form
!(constants
::DW_FORM_udata
);
1080 uleb128_size(val
.0 as u64)
1082 AttributeValue
::Accessibility(val
) => {
1083 debug_assert_form
!(constants
::DW_FORM_udata
);
1084 uleb128_size(val
.0 as u64)
1086 AttributeValue
::Visibility(val
) => {
1087 debug_assert_form
!(constants
::DW_FORM_udata
);
1088 uleb128_size(val
.0 as u64)
1090 AttributeValue
::Virtuality(val
) => {
1091 debug_assert_form
!(constants
::DW_FORM_udata
);
1092 uleb128_size(val
.0 as u64)
1094 AttributeValue
::Language(val
) => {
1095 debug_assert_form
!(constants
::DW_FORM_udata
);
1096 uleb128_size(val
.0 as u64)
1098 AttributeValue
::AddressClass(val
) => {
1099 debug_assert_form
!(constants
::DW_FORM_udata
);
1100 uleb128_size(val
.0 as u64)
1102 AttributeValue
::IdentifierCase(val
) => {
1103 debug_assert_form
!(constants
::DW_FORM_udata
);
1104 uleb128_size(val
.0 as u64)
1106 AttributeValue
::CallingConvention(val
) => {
1107 debug_assert_form
!(constants
::DW_FORM_udata
);
1108 uleb128_size(val
.0 as u64)
1110 AttributeValue
::Inline(val
) => {
1111 debug_assert_form
!(constants
::DW_FORM_udata
);
1112 uleb128_size(val
.0 as u64)
1114 AttributeValue
::Ordering(val
) => {
1115 debug_assert_form
!(constants
::DW_FORM_udata
);
1116 uleb128_size(val
.0 as u64)
1118 AttributeValue
::FileIndex(val
) => {
1119 debug_assert_form
!(constants
::DW_FORM_udata
);
1120 uleb128_size(val
.map(FileId
::raw
).unwrap_or(0))
1125 /// Write the attribute value to the given sections.
1126 #[allow(clippy::cyclomatic_complexity, clippy::too_many_arguments)]
1127 fn write
<W
: Writer
>(
1129 w
: &mut DebugInfo
<W
>,
1130 debug_info_refs
: &mut Vec
<DebugInfoReference
>,
1131 unit_refs
: &mut Vec
<(DebugInfoOffset
, UnitEntryId
)>,
1133 offsets
: &UnitOffsets
,
1134 line_program
: Option
<DebugLineOffset
>,
1135 line_strings
: &DebugLineStrOffsets
,
1136 strings
: &DebugStrOffsets
,
1137 range_lists
: &RangeListOffsets
,
1138 loc_lists
: &LocationListOffsets
,
1140 macro_rules
! debug_assert_form
{
1142 debug_assert_eq
!(self.form(unit
.encoding()).unwrap(), $form
)
1146 AttributeValue
::Address(val
) => {
1147 debug_assert_form
!(constants
::DW_FORM_addr
);
1148 w
.write_address(val
, unit
.address_size())?
;
1150 AttributeValue
::Block(ref val
) => {
1151 debug_assert_form
!(constants
::DW_FORM_block
);
1152 w
.write_uleb128(val
.len() as u64)?
;
1155 AttributeValue
::Data1(val
) => {
1156 debug_assert_form
!(constants
::DW_FORM_data1
);
1159 AttributeValue
::Data2(val
) => {
1160 debug_assert_form
!(constants
::DW_FORM_data2
);
1163 AttributeValue
::Data4(val
) => {
1164 debug_assert_form
!(constants
::DW_FORM_data4
);
1167 AttributeValue
::Data8(val
) => {
1168 debug_assert_form
!(constants
::DW_FORM_data8
);
1171 AttributeValue
::Sdata(val
) => {
1172 debug_assert_form
!(constants
::DW_FORM_sdata
);
1173 w
.write_sleb128(val
)?
;
1175 AttributeValue
::Udata(val
) => {
1176 debug_assert_form
!(constants
::DW_FORM_udata
);
1177 w
.write_uleb128(val
)?
;
1179 AttributeValue
::Exprloc(ref val
) => {
1180 debug_assert_form
!(constants
::DW_FORM_exprloc
);
1181 w
.write_uleb128(val
.size(unit
.encoding(), Some(offsets
)) as u64)?
;
1184 Some(debug_info_refs
),
1189 AttributeValue
::Flag(val
) => {
1190 debug_assert_form
!(constants
::DW_FORM_flag
);
1191 w
.write_u8(val
as u8)?
;
1193 AttributeValue
::FlagPresent
=> {
1194 debug_assert_form
!(constants
::DW_FORM_flag_present
);
1196 AttributeValue
::UnitRef(id
) => {
1197 match unit
.format() {
1198 Format
::Dwarf32
=> debug_assert_form
!(constants
::DW_FORM_ref4
),
1199 Format
::Dwarf64
=> debug_assert_form
!(constants
::DW_FORM_ref8
),
1201 unit_refs
.push((w
.offset(), id
));
1202 w
.write_udata(0, unit
.format().word_size())?
;
1204 AttributeValue
::DebugInfoRef(reference
) => {
1205 debug_assert_form
!(constants
::DW_FORM_ref_addr
);
1206 let size
= if unit
.version() == 2 {
1209 unit
.format().word_size()
1212 Reference
::Symbol(symbol
) => w
.write_reference(symbol
, size
)?
,
1213 Reference
::Entry(unit
, entry
) => {
1214 debug_info_refs
.push(DebugInfoReference
{
1220 w
.write_udata(0, size
)?
;
1224 AttributeValue
::DebugInfoRefSup(val
) => {
1225 match unit
.format() {
1226 Format
::Dwarf32
=> debug_assert_form
!(constants
::DW_FORM_ref_sup4
),
1227 Format
::Dwarf64
=> debug_assert_form
!(constants
::DW_FORM_ref_sup8
),
1229 w
.write_udata(val
.0 as u64, unit
.format().word_size())?
;
1231 AttributeValue
::LineProgramRef
=> {
1232 if unit
.version() >= 4 {
1233 debug_assert_form
!(constants
::DW_FORM_sec_offset
);
1235 match line_program
{
1236 Some(line_program
) => {
1239 SectionId
::DebugLine
,
1240 unit
.format().word_size(),
1243 None
=> return Err(Error
::InvalidAttributeValue
),
1246 AttributeValue
::LocationListRef(val
) => {
1247 if unit
.version() >= 4 {
1248 debug_assert_form
!(constants
::DW_FORM_sec_offset
);
1250 let section
= if unit
.version() <= 4 {
1253 SectionId
::DebugLocLists
1255 w
.write_offset(loc_lists
.get(val
).0, section
, unit
.format().word_size())?
;
1257 AttributeValue
::DebugMacinfoRef(val
) => {
1258 if unit
.version() >= 4 {
1259 debug_assert_form
!(constants
::DW_FORM_sec_offset
);
1261 w
.write_offset(val
.0, SectionId
::DebugMacinfo
, unit
.format().word_size())?
;
1263 AttributeValue
::DebugMacroRef(val
) => {
1264 if unit
.version() >= 4 {
1265 debug_assert_form
!(constants
::DW_FORM_sec_offset
);
1267 w
.write_offset(val
.0, SectionId
::DebugMacro
, unit
.format().word_size())?
;
1269 AttributeValue
::RangeListRef(val
) => {
1270 if unit
.version() >= 4 {
1271 debug_assert_form
!(constants
::DW_FORM_sec_offset
);
1273 let section
= if unit
.version() <= 4 {
1274 SectionId
::DebugRanges
1276 SectionId
::DebugRngLists
1278 w
.write_offset(range_lists
.get(val
).0, section
, unit
.format().word_size())?
;
1280 AttributeValue
::DebugTypesRef(val
) => {
1281 debug_assert_form
!(constants
::DW_FORM_ref_sig8
);
1282 w
.write_u64(val
.0)?
;
1284 AttributeValue
::StringRef(val
) => {
1285 debug_assert_form
!(constants
::DW_FORM_strp
);
1288 SectionId
::DebugStr
,
1289 unit
.format().word_size(),
1292 AttributeValue
::DebugStrRefSup(val
) => {
1293 debug_assert_form
!(constants
::DW_FORM_strp_sup
);
1294 w
.write_udata(val
.0 as u64, unit
.format().word_size())?
;
1296 AttributeValue
::LineStringRef(val
) => {
1297 debug_assert_form
!(constants
::DW_FORM_line_strp
);
1299 line_strings
.get(val
).0,
1300 SectionId
::DebugLineStr
,
1301 unit
.format().word_size(),
1304 AttributeValue
::String(ref val
) => {
1305 debug_assert_form
!(constants
::DW_FORM_string
);
1309 AttributeValue
::Encoding(val
) => {
1310 debug_assert_form
!(constants
::DW_FORM_udata
);
1311 w
.write_uleb128(u64::from(val
.0))?
;
1313 AttributeValue
::DecimalSign(val
) => {
1314 debug_assert_form
!(constants
::DW_FORM_udata
);
1315 w
.write_uleb128(u64::from(val
.0))?
;
1317 AttributeValue
::Endianity(val
) => {
1318 debug_assert_form
!(constants
::DW_FORM_udata
);
1319 w
.write_uleb128(u64::from(val
.0))?
;
1321 AttributeValue
::Accessibility(val
) => {
1322 debug_assert_form
!(constants
::DW_FORM_udata
);
1323 w
.write_uleb128(u64::from(val
.0))?
;
1325 AttributeValue
::Visibility(val
) => {
1326 debug_assert_form
!(constants
::DW_FORM_udata
);
1327 w
.write_uleb128(u64::from(val
.0))?
;
1329 AttributeValue
::Virtuality(val
) => {
1330 debug_assert_form
!(constants
::DW_FORM_udata
);
1331 w
.write_uleb128(u64::from(val
.0))?
;
1333 AttributeValue
::Language(val
) => {
1334 debug_assert_form
!(constants
::DW_FORM_udata
);
1335 w
.write_uleb128(u64::from(val
.0))?
;
1337 AttributeValue
::AddressClass(val
) => {
1338 debug_assert_form
!(constants
::DW_FORM_udata
);
1339 w
.write_uleb128(val
.0)?
;
1341 AttributeValue
::IdentifierCase(val
) => {
1342 debug_assert_form
!(constants
::DW_FORM_udata
);
1343 w
.write_uleb128(u64::from(val
.0))?
;
1345 AttributeValue
::CallingConvention(val
) => {
1346 debug_assert_form
!(constants
::DW_FORM_udata
);
1347 w
.write_uleb128(u64::from(val
.0))?
;
1349 AttributeValue
::Inline(val
) => {
1350 debug_assert_form
!(constants
::DW_FORM_udata
);
1351 w
.write_uleb128(u64::from(val
.0))?
;
1353 AttributeValue
::Ordering(val
) => {
1354 debug_assert_form
!(constants
::DW_FORM_udata
);
1355 w
.write_uleb128(u64::from(val
.0))?
;
1357 AttributeValue
::FileIndex(val
) => {
1358 debug_assert_form
!(constants
::DW_FORM_udata
);
1359 w
.write_uleb128(val
.map(FileId
::raw
).unwrap_or(0))?
;
1369 "A writable `.debug_info` section."
1372 /// The section offsets of all elements within a `.debug_info` section.
1373 #[derive(Debug, Default)]
1374 pub struct DebugInfoOffsets
{
1376 units
: Vec
<UnitOffsets
>,
1379 impl DebugInfoOffsets
{
1381 pub(crate) fn unit_offsets(&self, unit
: UnitId
) -> &UnitOffsets
{
1382 debug_assert_eq
!(self.base_id
, unit
.base_id
);
1383 &self.units
[unit
.index
]
1386 /// Get the `.debug_info` section offset for the given unit.
1388 pub fn unit(&self, unit
: UnitId
) -> DebugInfoOffset
{
1389 debug_assert_eq
!(self.base_id
, unit
.base_id
);
1390 self.units
[unit
.index
].unit
1393 /// Get the `.debug_info` section offset for the given entry.
1395 pub fn entry(&self, unit
: UnitId
, entry
: UnitEntryId
) -> DebugInfoOffset
{
1396 debug_assert_eq
!(self.base_id
, unit
.base_id
);
1397 self.units
[unit
.index
].debug_info_offset(entry
)
1401 /// The section offsets of all elements of a unit within a `.debug_info` section.
1403 pub(crate) struct UnitOffsets
{
1405 unit
: DebugInfoOffset
,
1406 entries
: Vec
<EntryOffset
>,
1413 base_id
: BaseId
::default(),
1414 unit
: DebugInfoOffset(0),
1415 entries
: Vec
::new(),
1419 /// Get the .debug_info offset for the given entry.
1421 pub(crate) fn debug_info_offset(&self, entry
: UnitEntryId
) -> DebugInfoOffset
{
1422 debug_assert_eq
!(self.base_id
, entry
.base_id
);
1423 let offset
= self.entries
[entry
.index
].offset
;
1424 debug_assert_ne
!(offset
.0, 0);
1428 /// Get the unit offset for the given entry.
1430 pub(crate) fn unit_offset(&self, entry
: UnitEntryId
) -> u64 {
1431 let offset
= self.debug_info_offset(entry
);
1432 (offset
.0 - self.unit
.0) as u64
1435 /// Get the abbreviation code for the given entry.
1437 pub(crate) fn abbrev(&self, entry
: UnitEntryId
) -> u64 {
1438 debug_assert_eq
!(self.base_id
, entry
.base_id
);
1439 self.entries
[entry
.index
].abbrev
1443 #[derive(Debug, Clone, Copy)]
1444 pub(crate) struct EntryOffset
{
1445 offset
: DebugInfoOffset
,
1452 offset
: DebugInfoOffset(0),
1458 /// A reference to a `.debug_info` entry that has yet to be resolved.
1459 #[derive(Debug, Clone, Copy)]
1460 pub(crate) struct DebugInfoReference
{
1461 /// The offset within the section of the reference.
1463 /// The size of the reference.
1465 /// The unit containing the entry.
1467 /// The entry being referenced.
1468 pub entry
: UnitEntryId
,
1471 #[cfg(feature = "read")]
1472 pub(crate) mod convert
{
1474 use crate::common
::UnitSectionOffset
;
1475 use crate::read
::{self, Reader}
;
1476 use crate::write
::{self, ConvertError, ConvertResult, LocationList, RangeList}
;
1477 use std
::collections
::HashMap
;
1479 pub(crate) struct ConvertUnit
<R
: Reader
<Offset
= usize>> {
1480 from_unit
: read
::Unit
<R
>,
1483 entries
: Vec
<DebuggingInformationEntry
>,
1484 entry_offsets
: Vec
<read
::UnitOffset
>,
1488 pub(crate) struct ConvertUnitContext
<'a
, R
: Reader
<Offset
= usize>> {
1489 pub dwarf
: &'a read
::Dwarf
<R
>,
1490 pub unit
: &'a read
::Unit
<R
>,
1491 pub line_strings
: &'a
mut write
::LineStringTable
,
1492 pub strings
: &'a
mut write
::StringTable
,
1493 pub ranges
: &'a
mut write
::RangeListTable
,
1494 pub locations
: &'a
mut write
::LocationListTable
,
1495 pub convert_address
: &'a
dyn Fn(u64) -> Option
<Address
>,
1496 pub base_address
: Address
,
1497 pub line_program_offset
: Option
<DebugLineOffset
>,
1498 pub line_program_files
: Vec
<FileId
>,
1499 pub entry_ids
: &'a HashMap
<UnitSectionOffset
, (UnitId
, UnitEntryId
)>,
1503 /// Create a unit table by reading the data in the given sections.
1505 /// This also updates the given tables with the values that are referenced from
1506 /// attributes in this section.
1508 /// `convert_address` is a function to convert read addresses into the `Address`
1509 /// type. For non-relocatable addresses, this function may simply return
1510 /// `Address::Constant(address)`. For relocatable addresses, it is the caller's
1511 /// responsibility to determine the symbol and addend corresponding to the address
1512 /// and return `Address::Symbol { symbol, addend }`.
1513 pub fn from
<R
: Reader
<Offset
= usize>>(
1514 dwarf
: &read
::Dwarf
<R
>,
1515 line_strings
: &mut write
::LineStringTable
,
1516 strings
: &mut write
::StringTable
,
1517 convert_address
: &dyn Fn(u64) -> Option
<Address
>,
1518 ) -> ConvertResult
<UnitTable
> {
1519 let base_id
= BaseId
::default();
1520 let mut unit_entries
= Vec
::new();
1521 let mut entry_ids
= HashMap
::new();
1523 let mut from_units
= dwarf
.units();
1524 while let Some(from_unit
) = from_units
.next()?
{
1525 let unit_id
= UnitId
::new(base_id
, unit_entries
.len());
1526 unit_entries
.push(Unit
::convert_entries(
1534 // Attributes must be converted in a separate pass so that we can handle
1535 // references to other compilation units.
1536 let mut units
= Vec
::new();
1537 for unit_entries
in unit_entries
.drain(..) {
1538 units
.push(Unit
::convert_attributes(
1548 Ok(UnitTable { base_id, units }
)
1553 /// Create a unit by reading the data in the input sections.
1555 /// Does not add entry attributes.
1556 #[allow(clippy::too_many_arguments)]
1557 pub(crate) fn convert_entries
<R
: Reader
<Offset
= usize>>(
1558 from_header
: read
::UnitHeader
<R
>,
1560 entry_ids
: &mut HashMap
<UnitSectionOffset
, (UnitId
, UnitEntryId
)>,
1561 dwarf
: &read
::Dwarf
<R
>,
1562 ) -> ConvertResult
<ConvertUnit
<R
>> {
1563 match from_header
.type_() {
1564 read
::UnitType
::Compilation
=> (),
1565 _
=> return Err(ConvertError
::UnsupportedUnitType
),
1567 let base_id
= BaseId
::default();
1569 let from_unit
= dwarf
.unit(from_header
)?
;
1570 let encoding
= from_unit
.encoding();
1572 let mut entries
= Vec
::new();
1573 let mut entry_offsets
= Vec
::new();
1575 let mut from_tree
= from_unit
.entries_tree(None
)?
;
1576 let from_root
= from_tree
.root()?
;
1577 let root
= DebuggingInformationEntry
::convert_entry(
1598 /// Create entry attributes by reading the data in the input sections.
1599 fn convert_attributes
<R
: Reader
<Offset
= usize>>(
1600 unit
: ConvertUnit
<R
>,
1601 entry_ids
: &HashMap
<UnitSectionOffset
, (UnitId
, UnitEntryId
)>,
1602 dwarf
: &read
::Dwarf
<R
>,
1603 line_strings
: &mut write
::LineStringTable
,
1604 strings
: &mut write
::StringTable
,
1605 convert_address
: &dyn Fn(u64) -> Option
<Address
>,
1606 ) -> ConvertResult
<Unit
> {
1607 let from_unit
= unit
.from_unit
;
1609 convert_address(from_unit
.low_pc
).ok_or(ConvertError
::InvalidAddress
)?
;
1611 let (line_program_offset
, line_program
, line_program_files
) =
1612 match from_unit
.line_program
{
1613 Some(ref from_program
) => {
1614 let from_program
= from_program
.clone();
1615 let line_program_offset
= from_program
.header().offset();
1616 let (line_program
, line_program_files
) = LineProgram
::from(
1623 (Some(line_program_offset
), line_program
, line_program_files
)
1625 None
=> (None
, LineProgram
::none(), Vec
::new()),
1628 let mut ranges
= RangeListTable
::default();
1629 let mut locations
= LocationListTable
::default();
1631 let mut context
= ConvertUnitContext
{
1637 ranges
: &mut ranges
,
1638 locations
: &mut locations
,
1641 line_program_offset
,
1645 let mut entries
= unit
.entries
;
1646 for entry
in &mut entries
{
1647 entry
.convert_attributes(&mut context
, &unit
.entry_offsets
)?
;
1651 base_id
: unit
.base_id
,
1652 encoding
: unit
.encoding
,
1662 impl DebuggingInformationEntry
{
1663 /// Create an entry by reading the data in the input sections.
1665 /// Does not add the entry attributes.
1666 fn convert_entry
<R
: Reader
<Offset
= usize>>(
1667 from
: read
::EntriesTreeNode
<R
>,
1668 from_unit
: &read
::Unit
<R
>,
1670 entries
: &mut Vec
<DebuggingInformationEntry
>,
1671 entry_offsets
: &mut Vec
<read
::UnitOffset
>,
1672 entry_ids
: &mut HashMap
<UnitSectionOffset
, (UnitId
, UnitEntryId
)>,
1673 parent
: Option
<UnitEntryId
>,
1675 ) -> ConvertResult
<UnitEntryId
> {
1676 let from_entry
= from
.entry();
1677 let id
= DebuggingInformationEntry
::new(base_id
, entries
, parent
, from_entry
.tag());
1678 let offset
= from_entry
.offset();
1679 entry_offsets
.push(offset
);
1680 entry_ids
.insert(offset
.to_unit_section_offset(from_unit
), (unit_id
, id
));
1682 let mut from_children
= from
.children();
1683 while let Some(from_child
) = from_children
.next()?
{
1684 DebuggingInformationEntry
::convert_entry(
1698 /// Create an entry's attributes by reading the data in the input sections.
1699 fn convert_attributes
<R
: Reader
<Offset
= usize>>(
1701 context
: &mut ConvertUnitContext
<R
>,
1702 entry_offsets
: &[read
::UnitOffset
],
1703 ) -> ConvertResult
<()> {
1704 let offset
= entry_offsets
[self.id
.index
];
1705 let from
= context
.unit
.entry(offset
)?
;
1706 let mut from_attrs
= from
.attrs();
1707 while let Some(from_attr
) = from_attrs
.next()?
{
1708 if from_attr
.name() == constants
::DW_AT_sibling
{
1709 // This may point to a null entry, so we have to treat it differently.
1710 self.set_sibling(true);
1711 } else if let Some(attr
) = Attribute
::from(context
, &from_attr
)?
{
1712 self.set(attr
.name
, attr
.value
);
1720 /// Create an attribute by reading the data in the given sections.
1721 pub(crate) fn from
<R
: Reader
<Offset
= usize>>(
1722 context
: &mut ConvertUnitContext
<R
>,
1723 from
: &read
::Attribute
<R
>,
1724 ) -> ConvertResult
<Option
<Attribute
>> {
1725 let value
= AttributeValue
::from(context
, from
.value())?
;
1726 Ok(value
.map(|value
| Attribute
{
1733 impl AttributeValue
{
1734 /// Create an attribute value by reading the data in the given sections.
1735 pub(crate) fn from
<R
: Reader
<Offset
= usize>>(
1736 context
: &mut ConvertUnitContext
<R
>,
1737 from
: read
::AttributeValue
<R
>,
1738 ) -> ConvertResult
<Option
<AttributeValue
>> {
1739 let to
= match from
{
1740 read
::AttributeValue
::Addr(val
) => match (context
.convert_address
)(val
) {
1741 Some(val
) => AttributeValue
::Address(val
),
1742 None
=> return Err(ConvertError
::InvalidAddress
),
1744 read
::AttributeValue
::Block(r
) => AttributeValue
::Block(r
.to_slice()?
.into()),
1745 read
::AttributeValue
::Data1(val
) => AttributeValue
::Data1(val
),
1746 read
::AttributeValue
::Data2(val
) => AttributeValue
::Data2(val
),
1747 read
::AttributeValue
::Data4(val
) => AttributeValue
::Data4(val
),
1748 read
::AttributeValue
::Data8(val
) => AttributeValue
::Data8(val
),
1749 read
::AttributeValue
::Sdata(val
) => AttributeValue
::Sdata(val
),
1750 read
::AttributeValue
::Udata(val
) => AttributeValue
::Udata(val
),
1751 read
::AttributeValue
::Exprloc(expression
) => {
1752 let expression
= Expression
::from(
1754 context
.unit
.encoding(),
1755 Some(context
.dwarf
),
1757 Some(context
.entry_ids
),
1758 context
.convert_address
,
1760 AttributeValue
::Exprloc(expression
)
1762 // TODO: it would be nice to preserve the flag form.
1763 read
::AttributeValue
::Flag(val
) => AttributeValue
::Flag(val
),
1764 read
::AttributeValue
::DebugAddrBase(_base
) => {
1765 // We convert all address indices to addresses,
1766 // so this is unneeded.
1769 read
::AttributeValue
::DebugAddrIndex(index
) => {
1770 let val
= context
.dwarf
.address(context
.unit
, index
)?
;
1771 match (context
.convert_address
)(val
) {
1772 Some(val
) => AttributeValue
::Address(val
),
1773 None
=> return Err(ConvertError
::InvalidAddress
),
1776 read
::AttributeValue
::UnitRef(val
) => {
1777 if !context
.unit
.header
.is_valid_offset(val
) {
1778 return Err(ConvertError
::InvalidUnitRef
);
1782 .get(&val
.to_unit_section_offset(context
.unit
))
1783 .ok_or(ConvertError
::InvalidUnitRef
)?
;
1784 AttributeValue
::UnitRef(id
.1)
1786 read
::AttributeValue
::DebugInfoRef(val
) => {
1787 // TODO: support relocation of this value
1790 .get(&UnitSectionOffset
::DebugInfoOffset(val
))
1791 .ok_or(ConvertError
::InvalidDebugInfoRef
)?
;
1792 AttributeValue
::DebugInfoRef(Reference
::Entry(id
.0, id
.1))
1794 read
::AttributeValue
::DebugInfoRefSup(val
) => AttributeValue
::DebugInfoRefSup(val
),
1795 read
::AttributeValue
::DebugLineRef(val
) => {
1796 // There should only be the line program in the CU DIE which we've already
1797 // converted, so check if it matches that.
1798 if Some(val
) == context
.line_program_offset
{
1799 AttributeValue
::LineProgramRef
1801 return Err(ConvertError
::InvalidLineRef
);
1804 read
::AttributeValue
::DebugMacinfoRef(val
) => AttributeValue
::DebugMacinfoRef(val
),
1805 read
::AttributeValue
::DebugMacroRef(val
) => AttributeValue
::DebugMacroRef(val
),
1806 read
::AttributeValue
::LocationListsRef(val
) => {
1810 .raw_locations(val
, context
.unit
.encoding())?
;
1811 let loc_list
= LocationList
::from(iter
, context
)?
;
1812 let loc_id
= context
.locations
.add(loc_list
);
1813 AttributeValue
::LocationListRef(loc_id
)
1815 read
::AttributeValue
::DebugLocListsBase(_base
) => {
1816 // We convert all location list indices to offsets,
1817 // so this is unneeded.
1820 read
::AttributeValue
::DebugLocListsIndex(index
) => {
1821 let offset
= context
.dwarf
.locations_offset(context
.unit
, index
)?
;
1825 .raw_locations(offset
, context
.unit
.encoding())?
;
1826 let loc_list
= LocationList
::from(iter
, context
)?
;
1827 let loc_id
= context
.locations
.add(loc_list
);
1828 AttributeValue
::LocationListRef(loc_id
)
1830 read
::AttributeValue
::RangeListsRef(val
) => {
1834 .raw_ranges(val
, context
.unit
.encoding())?
;
1835 let range_list
= RangeList
::from(iter
, context
)?
;
1836 let range_id
= context
.ranges
.add(range_list
);
1837 AttributeValue
::RangeListRef(range_id
)
1839 read
::AttributeValue
::DebugRngListsBase(_base
) => {
1840 // We convert all range list indices to offsets,
1841 // so this is unneeded.
1844 read
::AttributeValue
::DebugRngListsIndex(index
) => {
1845 let offset
= context
.dwarf
.ranges_offset(context
.unit
, index
)?
;
1849 .raw_ranges(offset
, context
.unit
.encoding())?
;
1850 let range_list
= RangeList
::from(iter
, context
)?
;
1851 let range_id
= context
.ranges
.add(range_list
);
1852 AttributeValue
::RangeListRef(range_id
)
1854 read
::AttributeValue
::DebugTypesRef(val
) => AttributeValue
::DebugTypesRef(val
),
1855 read
::AttributeValue
::DebugStrRef(offset
) => {
1856 let r
= context
.dwarf
.string(offset
)?
;
1857 let id
= context
.strings
.add(r
.to_slice()?
);
1858 AttributeValue
::StringRef(id
)
1860 read
::AttributeValue
::DebugStrRefSup(val
) => AttributeValue
::DebugStrRefSup(val
),
1861 read
::AttributeValue
::DebugStrOffsetsBase(_base
) => {
1862 // We convert all string offsets to `.debug_str` references,
1863 // so this is unneeded.
1866 read
::AttributeValue
::DebugStrOffsetsIndex(index
) => {
1867 let offset
= context
.dwarf
.string_offset(context
.unit
, index
)?
;
1868 let r
= context
.dwarf
.string(offset
)?
;
1869 let id
= context
.strings
.add(r
.to_slice()?
);
1870 AttributeValue
::StringRef(id
)
1872 read
::AttributeValue
::DebugLineStrRef(offset
) => {
1873 let r
= context
.dwarf
.line_string(offset
)?
;
1874 let id
= context
.line_strings
.add(r
.to_slice()?
);
1875 AttributeValue
::LineStringRef(id
)
1877 read
::AttributeValue
::String(r
) => AttributeValue
::String(r
.to_slice()?
.into()),
1878 read
::AttributeValue
::Encoding(val
) => AttributeValue
::Encoding(val
),
1879 read
::AttributeValue
::DecimalSign(val
) => AttributeValue
::DecimalSign(val
),
1880 read
::AttributeValue
::Endianity(val
) => AttributeValue
::Endianity(val
),
1881 read
::AttributeValue
::Accessibility(val
) => AttributeValue
::Accessibility(val
),
1882 read
::AttributeValue
::Visibility(val
) => AttributeValue
::Visibility(val
),
1883 read
::AttributeValue
::Virtuality(val
) => AttributeValue
::Virtuality(val
),
1884 read
::AttributeValue
::Language(val
) => AttributeValue
::Language(val
),
1885 read
::AttributeValue
::AddressClass(val
) => AttributeValue
::AddressClass(val
),
1886 read
::AttributeValue
::IdentifierCase(val
) => AttributeValue
::IdentifierCase(val
),
1887 read
::AttributeValue
::CallingConvention(val
) => {
1888 AttributeValue
::CallingConvention(val
)
1890 read
::AttributeValue
::Inline(val
) => AttributeValue
::Inline(val
),
1891 read
::AttributeValue
::Ordering(val
) => AttributeValue
::Ordering(val
),
1892 read
::AttributeValue
::FileIndex(val
) => {
1894 // 0 means not specified, even for version 5.
1895 AttributeValue
::FileIndex(None
)
1897 match context
.line_program_files
.get(val
as usize) {
1898 Some(id
) => AttributeValue
::FileIndex(Some(*id
)),
1899 None
=> return Err(ConvertError
::InvalidFileIndex
),
1903 // Should always be a more specific section reference.
1904 read
::AttributeValue
::SecOffset(_
) => {
1905 return Err(ConvertError
::InvalidAttributeValue
);
1907 read
::AttributeValue
::DwoId(DwoId(val
)) => AttributeValue
::Udata(val
),
1915 #[cfg(feature = "read")]
1918 use crate::common
::{
1919 DebugAddrBase
, DebugLocListsBase
, DebugRngListsBase
, DebugStrOffsetsBase
, LineEncoding
,
1921 use crate::constants
;
1924 DebugLine
, DebugLineStr
, DebugStr
, EndianVec
, LineString
, LineStringTable
, Location
,
1925 LocationList
, LocationListTable
, Range
, RangeList
, RangeListOffsets
, RangeListTable
,
1928 use crate::LittleEndian
;
1929 use std
::collections
::HashMap
;
1933 #[allow(clippy::cyclomatic_complexity)]
1934 fn test_unit_table() {
1935 let mut strings
= StringTable
::default();
1937 let mut units
= UnitTable
::default();
1938 let unit_id1
= units
.add(Unit
::new(
1942 format
: Format
::Dwarf32
,
1944 LineProgram
::none(),
1946 let unit2
= units
.add(Unit
::new(
1950 format
: Format
::Dwarf64
,
1952 LineProgram
::none(),
1954 let unit3
= units
.add(Unit
::new(
1958 format
: Format
::Dwarf32
,
1960 LineProgram
::none(),
1962 assert_eq
!(units
.count(), 3);
1964 let unit1
= units
.get_mut(unit_id1
);
1965 assert_eq
!(unit1
.version(), 4);
1966 assert_eq
!(unit1
.address_size(), 8);
1967 assert_eq
!(unit1
.format(), Format
::Dwarf32
);
1968 assert_eq
!(unit1
.count(), 1);
1970 let root_id
= unit1
.root();
1971 assert_eq
!(root_id
, UnitEntryId
::new(unit1
.base_id
, 0));
1973 let root
= unit1
.get_mut(root_id
);
1974 assert_eq
!(root
.id(), root_id
);
1975 assert
!(root
.parent().is_none());
1976 assert_eq
!(root
.tag(), constants
::DW_TAG_compile_unit
);
1979 assert
!(root
.get(constants
::DW_AT_producer
).is_none());
1980 assert
!(root
.get_mut(constants
::DW_AT_producer
).is_none());
1981 let mut producer
= AttributeValue
::String(b
"root"[..].into());
1982 root
.set(constants
::DW_AT_producer
, producer
.clone());
1983 assert_eq
!(root
.get(constants
::DW_AT_producer
), Some(&producer
));
1984 assert_eq
!(root
.get_mut(constants
::DW_AT_producer
), Some(&mut producer
));
1987 let mut attrs
= root
.attrs();
1988 let attr
= attrs
.next().unwrap();
1989 assert_eq
!(attr
.name(), constants
::DW_AT_producer
);
1990 assert_eq
!(attr
.get(), &producer
);
1991 assert
!(attrs
.next().is_none());
1994 let child1
= unit1
.add(root_id
, constants
::DW_TAG_subprogram
);
1995 assert_eq
!(child1
, UnitEntryId
::new(unit1
.base_id
, 1));
1997 let child1
= unit1
.get_mut(child1
);
1998 assert_eq
!(child1
.parent(), Some(root_id
));
2000 let tmp
= AttributeValue
::String(b
"tmp"[..].into());
2001 child1
.set(constants
::DW_AT_name
, tmp
.clone());
2002 assert_eq
!(child1
.get(constants
::DW_AT_name
), Some(&tmp
));
2005 let name
= AttributeValue
::StringRef(strings
.add(&b
"child1"[..]));
2007 let attr
= child1
.attrs_mut().next().unwrap();
2008 assert_eq
!(attr
.name(), constants
::DW_AT_name
);
2009 attr
.set(name
.clone());
2011 assert_eq
!(child1
.get(constants
::DW_AT_name
), Some(&name
));
2014 let child2
= unit1
.add(root_id
, constants
::DW_TAG_subprogram
);
2015 assert_eq
!(child2
, UnitEntryId
::new(unit1
.base_id
, 2));
2017 let child2
= unit1
.get_mut(child2
);
2018 assert_eq
!(child2
.parent(), Some(root_id
));
2020 let tmp
= AttributeValue
::String(b
"tmp"[..].into());
2021 child2
.set(constants
::DW_AT_name
, tmp
.clone());
2022 assert_eq
!(child2
.get(constants
::DW_AT_name
), Some(&tmp
));
2025 let name
= AttributeValue
::StringRef(strings
.add(&b
"child2"[..]));
2026 child2
.set(constants
::DW_AT_name
, name
.clone());
2027 assert_eq
!(child2
.get(constants
::DW_AT_name
), Some(&name
));
2031 let root
= unit1
.get(root_id
);
2033 root
.children().cloned().collect
::<Vec
<_
>>(),
2034 vec
![child1
, child2
]
2039 let unit2
= units
.get(unit2
);
2040 assert_eq
!(unit2
.version(), 2);
2041 assert_eq
!(unit2
.address_size(), 4);
2042 assert_eq
!(unit2
.format(), Format
::Dwarf64
);
2043 assert_eq
!(unit2
.count(), 1);
2045 let root
= unit2
.root();
2046 assert_eq
!(root
, UnitEntryId
::new(unit2
.base_id
, 0));
2047 let root
= unit2
.get(root
);
2048 assert_eq
!(root
.id(), UnitEntryId
::new(unit2
.base_id
, 0));
2049 assert
!(root
.parent().is_none());
2050 assert_eq
!(root
.tag(), constants
::DW_TAG_compile_unit
);
2053 let mut sections
= Sections
::new(EndianVec
::new(LittleEndian
));
2054 let debug_line_str_offsets
= DebugLineStrOffsets
::none();
2055 let debug_str_offsets
= strings
.write(&mut sections
.debug_str
).unwrap();
2057 .write(&mut sections
, &debug_line_str_offsets
, &debug_str_offsets
)
2060 println
!("{:?}", sections
.debug_str
);
2061 println
!("{:?}", sections
.debug_info
);
2062 println
!("{:?}", sections
.debug_abbrev
);
2064 let dwarf
= read
::Dwarf
{
2065 debug_abbrev
: read
::DebugAbbrev
::new(sections
.debug_abbrev
.slice(), LittleEndian
),
2066 debug_info
: read
::DebugInfo
::new(sections
.debug_info
.slice(), LittleEndian
),
2067 debug_str
: read
::DebugStr
::new(sections
.debug_str
.slice(), LittleEndian
),
2068 ..Default
::default()
2070 let mut read_units
= dwarf
.units();
2073 let read_unit1
= read_units
.next().unwrap().unwrap();
2074 let unit1
= units
.get(unit_id1
);
2075 assert_eq
!(unit1
.version(), read_unit1
.version());
2076 assert_eq
!(unit1
.address_size(), read_unit1
.address_size());
2077 assert_eq
!(unit1
.format(), read_unit1
.format());
2079 let read_unit1
= dwarf
.unit(read_unit1
).unwrap();
2080 let mut read_entries
= read_unit1
.entries();
2082 let root
= unit1
.get(unit1
.root());
2084 let (depth
, read_root
) = read_entries
.next_dfs().unwrap().unwrap();
2085 assert_eq
!(depth
, 0);
2086 assert_eq
!(root
.tag(), read_root
.tag());
2087 assert
!(read_root
.has_children());
2089 let producer
= match root
.get(constants
::DW_AT_producer
).unwrap() {
2090 AttributeValue
::String(ref producer
) => &**producer
,
2091 otherwise
=> panic
!("unexpected {:?}", otherwise
),
2093 assert_eq
!(producer
, b
"root");
2094 let read_producer
= read_root
2095 .attr_value(constants
::DW_AT_producer
)
2100 .attr_string(&read_unit1
, read_producer
)
2107 let mut children
= root
.children().cloned();
2110 let child
= children
.next().unwrap();
2111 assert_eq
!(child
, UnitEntryId
::new(unit1
.base_id
, 1));
2112 let child
= unit1
.get(child
);
2113 let (depth
, read_child
) = read_entries
.next_dfs().unwrap().unwrap();
2114 assert_eq
!(depth
, 1);
2115 assert_eq
!(child
.tag(), read_child
.tag());
2116 assert
!(!read_child
.has_children());
2118 let name
= match child
.get(constants
::DW_AT_name
).unwrap() {
2119 AttributeValue
::StringRef(name
) => *name
,
2120 otherwise
=> panic
!("unexpected {:?}", otherwise
),
2122 let name
= strings
.get(name
);
2123 assert_eq
!(name
, b
"child1");
2124 let read_name
= read_child
2125 .attr_value(constants
::DW_AT_name
)
2129 dwarf
.attr_string(&read_unit1
, read_name
).unwrap().slice(),
2135 let child
= children
.next().unwrap();
2136 assert_eq
!(child
, UnitEntryId
::new(unit1
.base_id
, 2));
2137 let child
= unit1
.get(child
);
2138 let (depth
, read_child
) = read_entries
.next_dfs().unwrap().unwrap();
2139 assert_eq
!(depth
, 0);
2140 assert_eq
!(child
.tag(), read_child
.tag());
2141 assert
!(!read_child
.has_children());
2143 let name
= match child
.get(constants
::DW_AT_name
).unwrap() {
2144 AttributeValue
::StringRef(name
) => *name
,
2145 otherwise
=> panic
!("unexpected {:?}", otherwise
),
2147 let name
= strings
.get(name
);
2148 assert_eq
!(name
, b
"child2");
2149 let read_name
= read_child
2150 .attr_value(constants
::DW_AT_name
)
2154 dwarf
.attr_string(&read_unit1
, read_name
).unwrap().slice(),
2159 assert
!(read_entries
.next_dfs().unwrap().is_none());
2163 let read_unit2
= read_units
.next().unwrap().unwrap();
2164 let unit2
= units
.get(unit2
);
2165 assert_eq
!(unit2
.version(), read_unit2
.version());
2166 assert_eq
!(unit2
.address_size(), read_unit2
.address_size());
2167 assert_eq
!(unit2
.format(), read_unit2
.format());
2169 let abbrevs
= dwarf
.abbreviations(&read_unit2
).unwrap();
2170 let mut read_entries
= read_unit2
.entries(&abbrevs
);
2173 let root
= unit2
.get(unit2
.root());
2174 let (depth
, read_root
) = read_entries
.next_dfs().unwrap().unwrap();
2175 assert_eq
!(depth
, 0);
2176 assert_eq
!(root
.tag(), read_root
.tag());
2177 assert
!(!read_root
.has_children());
2180 assert
!(read_entries
.next_dfs().unwrap().is_none());
2184 let read_unit3
= read_units
.next().unwrap().unwrap();
2185 let unit3
= units
.get(unit3
);
2186 assert_eq
!(unit3
.version(), read_unit3
.version());
2187 assert_eq
!(unit3
.address_size(), read_unit3
.address_size());
2188 assert_eq
!(unit3
.format(), read_unit3
.format());
2190 let abbrevs
= dwarf
.abbreviations(&read_unit3
).unwrap();
2191 let mut read_entries
= read_unit3
.entries(&abbrevs
);
2194 let root
= unit3
.get(unit3
.root());
2195 let (depth
, read_root
) = read_entries
.next_dfs().unwrap().unwrap();
2196 assert_eq
!(depth
, 0);
2197 assert_eq
!(root
.tag(), read_root
.tag());
2198 assert
!(!read_root
.has_children());
2201 assert
!(read_entries
.next_dfs().unwrap().is_none());
2204 assert
!(read_units
.next().unwrap().is_none());
2206 let mut convert_line_strings
= LineStringTable
::default();
2207 let mut convert_strings
= StringTable
::default();
2208 let convert_units
= UnitTable
::from(
2210 &mut convert_line_strings
,
2211 &mut convert_strings
,
2212 &|address
| Some(Address
::Constant(address
)),
2215 assert_eq
!(convert_units
.count(), units
.count());
2217 for i
in 0..convert_units
.count() {
2218 let unit_id
= units
.id(i
);
2219 let unit
= units
.get(unit_id
);
2220 let convert_unit_id
= convert_units
.id(i
);
2221 let convert_unit
= convert_units
.get(convert_unit_id
);
2222 assert_eq
!(convert_unit
.version(), unit
.version());
2223 assert_eq
!(convert_unit
.address_size(), unit
.address_size());
2224 assert_eq
!(convert_unit
.format(), unit
.format());
2225 assert_eq
!(convert_unit
.count(), unit
.count());
2227 let root
= unit
.get(unit
.root());
2228 let convert_root
= convert_unit
.get(convert_unit
.root());
2229 assert_eq
!(convert_root
.tag(), root
.tag());
2230 for (convert_attr
, attr
) in convert_root
.attrs().zip(root
.attrs()) {
2231 assert_eq
!(convert_attr
, attr
);
2237 fn test_attribute_value() {
2238 // Create a string table and a string with a non-zero id/offset.
2239 let mut strings
= StringTable
::default();
2240 strings
.add("string one");
2241 let string_id
= strings
.add("string two");
2242 let mut debug_str
= DebugStr
::from(EndianVec
::new(LittleEndian
));
2243 let debug_str_offsets
= strings
.write(&mut debug_str
).unwrap();
2244 let read_debug_str
= read
::DebugStr
::new(debug_str
.slice(), LittleEndian
);
2246 let mut line_strings
= LineStringTable
::default();
2247 line_strings
.add("line string one");
2248 let line_string_id
= line_strings
.add("line string two");
2249 let mut debug_line_str
= DebugLineStr
::from(EndianVec
::new(LittleEndian
));
2250 let debug_line_str_offsets
= line_strings
.write(&mut debug_line_str
).unwrap();
2251 let read_debug_line_str
=
2252 read
::DebugLineStr
::from(read
::EndianSlice
::new(debug_line_str
.slice(), LittleEndian
));
2254 let data
= vec
![1, 2, 3, 4];
2255 let read_data
= read
::EndianSlice
::new(&[1, 2, 3, 4], LittleEndian
);
2257 let mut expression
= Expression
::new();
2258 expression
.op_constu(57);
2259 let read_expression
= read
::Expression(read
::EndianSlice
::new(
2260 &[constants
::DW_OP_constu
.0, 57],
2264 let mut ranges
= RangeListTable
::default();
2265 let range_id
= ranges
.add(RangeList(vec
![Range
::StartEnd
{
2266 begin
: Address
::Constant(0x1234),
2267 end
: Address
::Constant(0x2345),
2270 let mut locations
= LocationListTable
::default();
2271 let loc_id
= locations
.add(LocationList(vec
![Location
::StartEnd
{
2272 begin
: Address
::Constant(0x1234),
2273 end
: Address
::Constant(0x2345),
2274 data
: expression
.clone(),
2277 for &version
in &[2, 3, 4, 5] {
2278 for &address_size
in &[4, 8] {
2279 for &format
in &[Format
::Dwarf32
, Format
::Dwarf64
] {
2280 let encoding
= Encoding
{
2286 let mut sections
= Sections
::new(EndianVec
::new(LittleEndian
));
2287 let range_list_offsets
= ranges
.write(&mut sections
, encoding
).unwrap();
2288 let loc_list_offsets
= locations
.write(&mut sections
, encoding
, None
).unwrap();
2290 let read_debug_ranges
=
2291 read
::DebugRanges
::new(sections
.debug_ranges
.slice(), LittleEndian
);
2292 let read_debug_rnglists
=
2293 read
::DebugRngLists
::new(sections
.debug_rnglists
.slice(), LittleEndian
);
2295 let read_debug_loc
=
2296 read
::DebugLoc
::new(sections
.debug_loc
.slice(), LittleEndian
);
2297 let read_debug_loclists
=
2298 read
::DebugLocLists
::new(sections
.debug_loclists
.slice(), LittleEndian
);
2300 let mut units
= UnitTable
::default();
2301 let unit
= units
.add(Unit
::new(encoding
, LineProgram
::none()));
2302 let unit
= units
.get(unit
);
2303 let encoding
= Encoding
{
2308 let from_unit
= read
::UnitHeader
::new(
2311 read
::UnitType
::Compilation
,
2312 DebugAbbrevOffset(0),
2313 DebugInfoOffset(0).into(),
2314 read
::EndianSlice
::new(&[], LittleEndian
),
2317 for &(ref name
, ref value
, ref expect_value
) in &[
2319 constants
::DW_AT_name
,
2320 AttributeValue
::Address(Address
::Constant(0x1234)),
2321 read
::AttributeValue
::Addr(0x1234),
2324 constants
::DW_AT_name
,
2325 AttributeValue
::Block(data
.clone()),
2326 read
::AttributeValue
::Block(read_data
),
2329 constants
::DW_AT_name
,
2330 AttributeValue
::Data1(0x12),
2331 read
::AttributeValue
::Data1(0x12),
2334 constants
::DW_AT_name
,
2335 AttributeValue
::Data2(0x1234),
2336 read
::AttributeValue
::Data2(0x1234),
2339 constants
::DW_AT_name
,
2340 AttributeValue
::Data4(0x1234),
2341 read
::AttributeValue
::Data4(0x1234),
2344 constants
::DW_AT_name
,
2345 AttributeValue
::Data8(0x1234),
2346 read
::AttributeValue
::Data8(0x1234),
2349 constants
::DW_AT_name
,
2350 AttributeValue
::Sdata(0x1234),
2351 read
::AttributeValue
::Sdata(0x1234),
2354 constants
::DW_AT_name
,
2355 AttributeValue
::Udata(0x1234),
2356 read
::AttributeValue
::Udata(0x1234),
2359 constants
::DW_AT_name
,
2360 AttributeValue
::Exprloc(expression
.clone()),
2361 read
::AttributeValue
::Exprloc(read_expression
),
2364 constants
::DW_AT_name
,
2365 AttributeValue
::Flag(false),
2366 read
::AttributeValue
::Flag(false),
2370 constants::DW_AT_name,
2371 AttributeValue::FlagPresent,
2372 read::AttributeValue::Flag(true),
2376 constants
::DW_AT_name
,
2377 AttributeValue
::DebugInfoRefSup(DebugInfoOffset(0x1234)),
2378 read
::AttributeValue
::DebugInfoRefSup(DebugInfoOffset(0x1234)),
2381 constants
::DW_AT_location
,
2382 AttributeValue
::LocationListRef(loc_id
),
2383 read
::AttributeValue
::SecOffset(loc_list_offsets
.get(loc_id
).0),
2386 constants
::DW_AT_macro_info
,
2387 AttributeValue
::DebugMacinfoRef(DebugMacinfoOffset(0x1234)),
2388 read
::AttributeValue
::SecOffset(0x1234),
2391 constants
::DW_AT_macros
,
2392 AttributeValue
::DebugMacroRef(DebugMacroOffset(0x1234)),
2393 read
::AttributeValue
::SecOffset(0x1234),
2396 constants
::DW_AT_ranges
,
2397 AttributeValue
::RangeListRef(range_id
),
2398 read
::AttributeValue
::SecOffset(range_list_offsets
.get(range_id
).0),
2401 constants
::DW_AT_name
,
2402 AttributeValue
::DebugTypesRef(DebugTypeSignature(0x1234)),
2403 read
::AttributeValue
::DebugTypesRef(DebugTypeSignature(0x1234)),
2406 constants
::DW_AT_name
,
2407 AttributeValue
::StringRef(string_id
),
2408 read
::AttributeValue
::DebugStrRef(debug_str_offsets
.get(string_id
)),
2411 constants
::DW_AT_name
,
2412 AttributeValue
::DebugStrRefSup(DebugStrOffset(0x1234)),
2413 read
::AttributeValue
::DebugStrRefSup(DebugStrOffset(0x1234)),
2416 constants
::DW_AT_name
,
2417 AttributeValue
::LineStringRef(line_string_id
),
2418 read
::AttributeValue
::DebugLineStrRef(
2419 debug_line_str_offsets
.get(line_string_id
),
2423 constants
::DW_AT_name
,
2424 AttributeValue
::String(data
.clone()),
2425 read
::AttributeValue
::String(read_data
),
2428 constants
::DW_AT_encoding
,
2429 AttributeValue
::Encoding(constants
::DwAte(0x12)),
2430 read
::AttributeValue
::Udata(0x12),
2433 constants
::DW_AT_decimal_sign
,
2434 AttributeValue
::DecimalSign(constants
::DwDs(0x12)),
2435 read
::AttributeValue
::Udata(0x12),
2438 constants
::DW_AT_endianity
,
2439 AttributeValue
::Endianity(constants
::DwEnd(0x12)),
2440 read
::AttributeValue
::Udata(0x12),
2443 constants
::DW_AT_accessibility
,
2444 AttributeValue
::Accessibility(constants
::DwAccess(0x12)),
2445 read
::AttributeValue
::Udata(0x12),
2448 constants
::DW_AT_visibility
,
2449 AttributeValue
::Visibility(constants
::DwVis(0x12)),
2450 read
::AttributeValue
::Udata(0x12),
2453 constants
::DW_AT_virtuality
,
2454 AttributeValue
::Virtuality(constants
::DwVirtuality(0x12)),
2455 read
::AttributeValue
::Udata(0x12),
2458 constants
::DW_AT_language
,
2459 AttributeValue
::Language(constants
::DwLang(0x12)),
2460 read
::AttributeValue
::Udata(0x12),
2463 constants
::DW_AT_address_class
,
2464 AttributeValue
::AddressClass(constants
::DwAddr(0x12)),
2465 read
::AttributeValue
::Udata(0x12),
2468 constants
::DW_AT_identifier_case
,
2469 AttributeValue
::IdentifierCase(constants
::DwId(0x12)),
2470 read
::AttributeValue
::Udata(0x12),
2473 constants
::DW_AT_calling_convention
,
2474 AttributeValue
::CallingConvention(constants
::DwCc(0x12)),
2475 read
::AttributeValue
::Udata(0x12),
2478 constants
::DW_AT_ordering
,
2479 AttributeValue
::Ordering(constants
::DwOrd(0x12)),
2480 read
::AttributeValue
::Udata(0x12),
2483 constants
::DW_AT_inline
,
2484 AttributeValue
::Inline(constants
::DwInl(0x12)),
2485 read
::AttributeValue
::Udata(0x12),
2489 let form
= value
.form(encoding
).unwrap();
2490 let attr
= Attribute
{
2492 value
: value
.clone(),
2495 let offsets
= UnitOffsets
::none();
2496 let line_program_offset
= None
;
2497 let mut debug_info_refs
= Vec
::new();
2498 let mut unit_refs
= Vec
::new();
2499 let mut debug_info
= DebugInfo
::from(EndianVec
::new(LittleEndian
));
2503 &mut debug_info_refs
,
2507 line_program_offset
,
2508 &debug_line_str_offsets
,
2510 &range_list_offsets
,
2515 let spec
= read
::AttributeSpecification
::new(*name
, form
, None
);
2516 let mut r
= read
::EndianSlice
::new(debug_info
.slice(), LittleEndian
);
2517 let read_attr
= read
::parse_attribute(&mut r
, encoding
, spec
).unwrap();
2518 let read_value
= &read_attr
.raw_value();
2519 // read::AttributeValue is invariant in the lifetime of R.
2520 // The lifetimes here are all okay, so transmute it.
2521 let read_value
= unsafe {
2523 &read
::AttributeValue
<read
::EndianSlice
<LittleEndian
>>,
2524 &read
::AttributeValue
<read
::EndianSlice
<LittleEndian
>>,
2527 assert_eq
!(read_value
, expect_value
);
2529 let dwarf
= read
::Dwarf
{
2530 debug_str
: read_debug_str
.clone(),
2531 debug_line_str
: read_debug_line_str
.clone(),
2532 ranges
: read
::RangeLists
::new(read_debug_ranges
, read_debug_rnglists
),
2533 locations
: read
::LocationLists
::new(
2535 read_debug_loclists
,
2537 ..Default
::default()
2540 let unit
= read
::Unit
{
2542 abbreviations
: read
::Abbreviations
::default(),
2546 str_offsets_base
: DebugStrOffsetsBase(0),
2547 addr_base
: DebugAddrBase(0),
2548 loclists_base
: DebugLocListsBase(0),
2549 rnglists_base
: DebugRngListsBase(0),
2553 let mut context
= convert
::ConvertUnitContext
{
2556 line_strings
: &mut line_strings
,
2557 strings
: &mut strings
,
2558 ranges
: &mut ranges
,
2559 locations
: &mut locations
,
2560 convert_address
: &|address
| Some(Address
::Constant(address
)),
2561 base_address
: Address
::Constant(0),
2562 line_program_offset
: None
,
2563 line_program_files
: Vec
::new(),
2564 entry_ids
: &HashMap
::new(),
2568 Attribute
::from(&mut context
, &read_attr
).unwrap().unwrap();
2569 assert_eq
!(convert_attr
, attr
);
2577 #[allow(clippy::cyclomatic_complexity)]
2578 fn test_unit_ref() {
2579 let mut units
= UnitTable
::default();
2580 let unit_id1
= units
.add(Unit
::new(
2584 format
: Format
::Dwarf32
,
2586 LineProgram
::none(),
2588 assert_eq
!(unit_id1
, units
.id(0));
2589 let unit_id2
= units
.add(Unit
::new(
2593 format
: Format
::Dwarf64
,
2595 LineProgram
::none(),
2597 assert_eq
!(unit_id2
, units
.id(1));
2598 let unit1_child1
= UnitEntryId
::new(units
.get(unit_id1
).base_id
, 1);
2599 let unit1_child2
= UnitEntryId
::new(units
.get(unit_id1
).base_id
, 2);
2600 let unit2_child1
= UnitEntryId
::new(units
.get(unit_id2
).base_id
, 1);
2601 let unit2_child2
= UnitEntryId
::new(units
.get(unit_id2
).base_id
, 2);
2603 let unit1
= units
.get_mut(unit_id1
);
2604 let root
= unit1
.root();
2605 let child_id1
= unit1
.add(root
, constants
::DW_TAG_subprogram
);
2606 assert_eq
!(child_id1
, unit1_child1
);
2607 let child_id2
= unit1
.add(root
, constants
::DW_TAG_subprogram
);
2608 assert_eq
!(child_id2
, unit1_child2
);
2610 let child1
= unit1
.get_mut(child_id1
);
2611 child1
.set(constants
::DW_AT_type
, AttributeValue
::UnitRef(child_id2
));
2614 let child2
= unit1
.get_mut(child_id2
);
2616 constants
::DW_AT_type
,
2617 AttributeValue
::DebugInfoRef(Reference
::Entry(unit_id2
, unit2_child1
)),
2622 let unit2
= units
.get_mut(unit_id2
);
2623 let root
= unit2
.root();
2624 let child_id1
= unit2
.add(root
, constants
::DW_TAG_subprogram
);
2625 assert_eq
!(child_id1
, unit2_child1
);
2626 let child_id2
= unit2
.add(root
, constants
::DW_TAG_subprogram
);
2627 assert_eq
!(child_id2
, unit2_child2
);
2629 let child1
= unit2
.get_mut(child_id1
);
2630 child1
.set(constants
::DW_AT_type
, AttributeValue
::UnitRef(child_id2
));
2633 let child2
= unit2
.get_mut(child_id2
);
2635 constants
::DW_AT_type
,
2636 AttributeValue
::DebugInfoRef(Reference
::Entry(unit_id1
, unit1_child1
)),
2641 let debug_line_str_offsets
= DebugLineStrOffsets
::none();
2642 let debug_str_offsets
= DebugStrOffsets
::none();
2643 let mut sections
= Sections
::new(EndianVec
::new(LittleEndian
));
2644 let debug_info_offsets
= units
2645 .write(&mut sections
, &debug_line_str_offsets
, &debug_str_offsets
)
2648 println
!("{:?}", sections
.debug_info
);
2649 println
!("{:?}", sections
.debug_abbrev
);
2651 let dwarf
= read
::Dwarf
{
2652 debug_abbrev
: read
::DebugAbbrev
::new(sections
.debug_abbrev
.slice(), LittleEndian
),
2653 debug_info
: read
::DebugInfo
::new(sections
.debug_info
.slice(), LittleEndian
),
2654 ..Default
::default()
2657 let mut read_units
= dwarf
.units();
2659 let read_unit1
= read_units
.next().unwrap().unwrap();
2661 read_unit1
.offset(),
2662 debug_info_offsets
.unit(unit_id1
).into()
2665 let abbrevs
= dwarf
.abbreviations(&read_unit1
).unwrap();
2666 let mut read_entries
= read_unit1
.entries(&abbrevs
);
2668 let (_
, _read_root
) = read_entries
.next_dfs().unwrap().unwrap();
2671 let (_
, read_child1
) = read_entries
.next_dfs().unwrap().unwrap();
2672 let offset
= debug_info_offsets
2673 .entry(unit_id1
, unit1_child2
)
2674 .to_unit_offset(&read_unit1
)
2677 read_child1
.attr_value(constants
::DW_AT_type
).unwrap(),
2678 Some(read
::AttributeValue
::UnitRef(offset
))
2682 let (_
, read_child2
) = read_entries
.next_dfs().unwrap().unwrap();
2683 let offset
= debug_info_offsets
.entry(unit_id2
, unit2_child1
);
2685 read_child2
.attr_value(constants
::DW_AT_type
).unwrap(),
2686 Some(read
::AttributeValue
::DebugInfoRef(offset
))
2691 let read_unit2
= read_units
.next().unwrap().unwrap();
2693 read_unit2
.offset(),
2694 debug_info_offsets
.unit(unit_id2
).into()
2697 let abbrevs
= dwarf
.abbreviations(&read_unit2
).unwrap();
2698 let mut read_entries
= read_unit2
.entries(&abbrevs
);
2700 let (_
, _read_root
) = read_entries
.next_dfs().unwrap().unwrap();
2703 let (_
, read_child1
) = read_entries
.next_dfs().unwrap().unwrap();
2704 let offset
= debug_info_offsets
2705 .entry(unit_id2
, unit2_child2
)
2706 .to_unit_offset(&read_unit2
)
2709 read_child1
.attr_value(constants
::DW_AT_type
).unwrap(),
2710 Some(read
::AttributeValue
::UnitRef(offset
))
2714 let (_
, read_child2
) = read_entries
.next_dfs().unwrap().unwrap();
2715 let offset
= debug_info_offsets
.entry(unit_id1
, unit1_child1
);
2717 read_child2
.attr_value(constants
::DW_AT_type
).unwrap(),
2718 Some(read
::AttributeValue
::DebugInfoRef(offset
))
2723 let mut convert_line_strings
= LineStringTable
::default();
2724 let mut convert_strings
= StringTable
::default();
2725 let convert_units
= UnitTable
::from(
2727 &mut convert_line_strings
,
2728 &mut convert_strings
,
2729 &|address
| Some(Address
::Constant(address
)),
2732 assert_eq
!(convert_units
.count(), units
.count());
2734 for i
in 0..convert_units
.count() {
2735 let unit
= units
.get(units
.id(i
));
2736 let convert_unit
= convert_units
.get(convert_units
.id(i
));
2737 assert_eq
!(convert_unit
.version(), unit
.version());
2738 assert_eq
!(convert_unit
.address_size(), unit
.address_size());
2739 assert_eq
!(convert_unit
.format(), unit
.format());
2740 assert_eq
!(convert_unit
.count(), unit
.count());
2742 let root
= unit
.get(unit
.root());
2743 let convert_root
= convert_unit
.get(convert_unit
.root());
2744 assert_eq
!(convert_root
.tag(), root
.tag());
2745 for (convert_attr
, attr
) in convert_root
.attrs().zip(root
.attrs()) {
2746 assert_eq
!(convert_attr
, attr
);
2749 let child1
= unit
.get(UnitEntryId
::new(unit
.base_id
, 1));
2750 let convert_child1
= convert_unit
.get(UnitEntryId
::new(convert_unit
.base_id
, 1));
2751 assert_eq
!(convert_child1
.tag(), child1
.tag());
2752 for (convert_attr
, attr
) in convert_child1
.attrs().zip(child1
.attrs()) {
2753 assert_eq
!(convert_attr
.name
, attr
.name
);
2754 match (convert_attr
.value
.clone(), attr
.value
.clone()) {
2756 AttributeValue
::DebugInfoRef(Reference
::Entry(convert_unit
, convert_entry
)),
2757 AttributeValue
::DebugInfoRef(Reference
::Entry(unit
, entry
)),
2759 assert_eq
!(convert_unit
.index
, unit
.index
);
2760 assert_eq
!(convert_entry
.index
, entry
.index
);
2762 (AttributeValue
::UnitRef(convert_id
), AttributeValue
::UnitRef(id
)) => {
2763 assert_eq
!(convert_id
.index
, id
.index
);
2765 (convert_value
, value
) => assert_eq
!(convert_value
, value
),
2769 let child2
= unit
.get(UnitEntryId
::new(unit
.base_id
, 2));
2770 let convert_child2
= convert_unit
.get(UnitEntryId
::new(convert_unit
.base_id
, 2));
2771 assert_eq
!(convert_child2
.tag(), child2
.tag());
2772 for (convert_attr
, attr
) in convert_child2
.attrs().zip(child2
.attrs()) {
2773 assert_eq
!(convert_attr
.name
, attr
.name
);
2774 match (convert_attr
.value
.clone(), attr
.value
.clone()) {
2776 AttributeValue
::DebugInfoRef(Reference
::Entry(convert_unit
, convert_entry
)),
2777 AttributeValue
::DebugInfoRef(Reference
::Entry(unit
, entry
)),
2779 assert_eq
!(convert_unit
.index
, unit
.index
);
2780 assert_eq
!(convert_entry
.index
, entry
.index
);
2782 (AttributeValue
::UnitRef(convert_id
), AttributeValue
::UnitRef(id
)) => {
2783 assert_eq
!(convert_id
.index
, id
.index
);
2785 (convert_value
, value
) => assert_eq
!(convert_value
, value
),
2795 parent
: UnitEntryId
,
2796 tag
: constants
::DwTag
,
2799 let id
= unit
.add(parent
, tag
);
2800 let child
= unit
.get_mut(id
);
2801 child
.set(constants
::DW_AT_name
, AttributeValue
::String(name
.into()));
2802 child
.set_sibling(true);
2806 fn add_children(units
: &mut UnitTable
, unit_id
: UnitId
) {
2807 let unit
= units
.get_mut(unit_id
);
2808 let root
= unit
.root();
2809 let child1
= add_child(unit
, root
, constants
::DW_TAG_subprogram
, "child1");
2810 add_child(unit
, child1
, constants
::DW_TAG_variable
, "grandchild1");
2811 add_child(unit
, root
, constants
::DW_TAG_subprogram
, "child2");
2812 add_child(unit
, root
, constants
::DW_TAG_subprogram
, "child3");
2815 fn next_child
<R
: read
::Reader
<Offset
= usize>>(
2816 entries
: &mut read
::EntriesCursor
<R
>,
2817 ) -> (read
::UnitOffset
, Option
<read
::UnitOffset
>) {
2818 let (_
, entry
) = entries
.next_dfs().unwrap().unwrap();
2819 let offset
= entry
.offset();
2822 .attr_value(constants
::DW_AT_sibling
)
2824 .map(|attr
| match attr
{
2825 read
::AttributeValue
::UnitRef(offset
) => offset
,
2826 _
=> panic
!("bad sibling value"),
2831 fn check_sibling
<R
: read
::Reader
<Offset
= usize>>(
2832 unit
: &read
::UnitHeader
<R
>,
2833 debug_abbrev
: &read
::DebugAbbrev
<R
>,
2835 let abbrevs
= unit
.abbreviations(debug_abbrev
).unwrap();
2836 let mut entries
= unit
.entries(&abbrevs
);
2838 entries
.next_dfs().unwrap().unwrap();
2840 let (_
, sibling1
) = next_child(&mut entries
);
2842 entries
.next_dfs().unwrap().unwrap();
2844 let (offset2
, sibling2
) = next_child(&mut entries
);
2846 let (_
, _
) = next_child(&mut entries
);
2847 assert_eq
!(sibling1
, Some(offset2
));
2848 assert_eq
!(sibling2
, None
);
2851 let encoding
= Encoding
{
2852 format
: Format
::Dwarf32
,
2856 let mut units
= UnitTable
::default();
2857 let unit_id1
= units
.add(Unit
::new(encoding
, LineProgram
::none()));
2858 add_children(&mut units
, unit_id1
);
2859 let unit_id2
= units
.add(Unit
::new(encoding
, LineProgram
::none()));
2860 add_children(&mut units
, unit_id2
);
2862 let debug_line_str_offsets
= DebugLineStrOffsets
::none();
2863 let debug_str_offsets
= DebugStrOffsets
::none();
2864 let mut sections
= Sections
::new(EndianVec
::new(LittleEndian
));
2866 .write(&mut sections
, &debug_line_str_offsets
, &debug_str_offsets
)
2869 println
!("{:?}", sections
.debug_info
);
2870 println
!("{:?}", sections
.debug_abbrev
);
2872 let read_debug_info
= read
::DebugInfo
::new(sections
.debug_info
.slice(), LittleEndian
);
2873 let read_debug_abbrev
= read
::DebugAbbrev
::new(sections
.debug_abbrev
.slice(), LittleEndian
);
2874 let mut read_units
= read_debug_info
.units();
2875 check_sibling(&read_units
.next().unwrap().unwrap(), &read_debug_abbrev
);
2876 check_sibling(&read_units
.next().unwrap().unwrap(), &read_debug_abbrev
);
2880 fn test_line_ref() {
2881 for &version
in &[2, 3, 4, 5] {
2882 for &address_size
in &[4, 8] {
2883 for &format
in &[Format
::Dwarf32
, Format
::Dwarf64
] {
2884 let encoding
= Encoding
{
2890 // The line program we'll be referencing.
2891 let mut line_program
= LineProgram
::new(
2893 LineEncoding
::default(),
2894 LineString
::String(b
"comp_dir".to_vec()),
2895 LineString
::String(b
"comp_name".to_vec()),
2898 let dir
= line_program
.default_directory();
2900 line_program
.add_file(LineString
::String(b
"file1".to_vec()), dir
, None
);
2902 line_program
.add_file(LineString
::String(b
"file2".to_vec()), dir
, None
);
2904 // Write, read, and convert the line program, so that we have the info
2905 // required to convert the attributes.
2906 let line_strings
= DebugLineStrOffsets
::none();
2907 let strings
= DebugStrOffsets
::none();
2908 let mut debug_line
= DebugLine
::from(EndianVec
::new(LittleEndian
));
2909 let line_program_offset
= line_program
2910 .write(&mut debug_line
, encoding
, &line_strings
, &strings
)
2912 let read_debug_line
= read
::DebugLine
::new(debug_line
.slice(), LittleEndian
);
2913 let read_line_program
= read_debug_line
2915 line_program_offset
,
2917 Some(read
::EndianSlice
::new(b
"comp_dir", LittleEndian
)),
2918 Some(read
::EndianSlice
::new(b
"comp_name", LittleEndian
)),
2921 let dwarf
= read
::Dwarf
::default();
2922 let mut convert_line_strings
= LineStringTable
::default();
2923 let mut convert_strings
= StringTable
::default();
2924 let (_
, line_program_files
) = LineProgram
::from(
2927 &mut convert_line_strings
,
2928 &mut convert_strings
,
2929 &|address
| Some(Address
::Constant(address
)),
2934 let mut units
= UnitTable
::default();
2935 let unit
= units
.add(Unit
::new(encoding
, LineProgram
::none()));
2936 let unit
= units
.get(unit
);
2937 let from_unit
= read
::UnitHeader
::new(
2940 read
::UnitType
::Compilation
,
2941 DebugAbbrevOffset(0),
2942 DebugInfoOffset(0).into(),
2943 read
::EndianSlice
::new(&[], LittleEndian
),
2946 for &(ref name
, ref value
, ref expect_value
) in &[
2948 constants
::DW_AT_stmt_list
,
2949 AttributeValue
::LineProgramRef
,
2950 read
::AttributeValue
::SecOffset(line_program_offset
.0),
2953 constants
::DW_AT_decl_file
,
2954 AttributeValue
::FileIndex(Some(file1
)),
2955 read
::AttributeValue
::Udata(file1
.raw()),
2958 constants
::DW_AT_decl_file
,
2959 AttributeValue
::FileIndex(Some(file2
)),
2960 read
::AttributeValue
::Udata(file2
.raw()),
2964 let mut ranges
= RangeListTable
::default();
2965 let mut locations
= LocationListTable
::default();
2966 let mut strings
= StringTable
::default();
2967 let mut line_strings
= LineStringTable
::default();
2969 let form
= value
.form(encoding
).unwrap();
2970 let attr
= Attribute
{
2972 value
: value
.clone(),
2975 let mut debug_info_refs
= Vec
::new();
2976 let mut unit_refs
= Vec
::new();
2977 let mut debug_info
= DebugInfo
::from(EndianVec
::new(LittleEndian
));
2978 let offsets
= UnitOffsets
::none();
2979 let debug_line_str_offsets
= DebugLineStrOffsets
::none();
2980 let debug_str_offsets
= DebugStrOffsets
::none();
2981 let range_list_offsets
= RangeListOffsets
::none();
2982 let loc_list_offsets
= LocationListOffsets
::none();
2986 &mut debug_info_refs
,
2990 Some(line_program_offset
),
2991 &debug_line_str_offsets
,
2993 &range_list_offsets
,
2998 let spec
= read
::AttributeSpecification
::new(*name
, form
, None
);
2999 let mut r
= read
::EndianSlice
::new(debug_info
.slice(), LittleEndian
);
3000 let read_attr
= read
::parse_attribute(&mut r
, encoding
, spec
).unwrap();
3001 let read_value
= &read_attr
.raw_value();
3002 // read::AttributeValue is invariant in the lifetime of R.
3003 // The lifetimes here are all okay, so transmute it.
3004 let read_value
= unsafe {
3006 &read
::AttributeValue
<read
::EndianSlice
<LittleEndian
>>,
3007 &read
::AttributeValue
<read
::EndianSlice
<LittleEndian
>>,
3010 assert_eq
!(read_value
, expect_value
);
3012 let unit
= read
::Unit
{
3014 abbreviations
: read
::Abbreviations
::default(),
3018 str_offsets_base
: DebugStrOffsetsBase(0),
3019 addr_base
: DebugAddrBase(0),
3020 loclists_base
: DebugLocListsBase(0),
3021 rnglists_base
: DebugRngListsBase(0),
3025 let mut context
= convert
::ConvertUnitContext
{
3028 line_strings
: &mut line_strings
,
3029 strings
: &mut strings
,
3030 ranges
: &mut ranges
,
3031 locations
: &mut locations
,
3032 convert_address
: &|address
| Some(Address
::Constant(address
)),
3033 base_address
: Address
::Constant(0),
3034 line_program_offset
: Some(line_program_offset
),
3035 line_program_files
: line_program_files
.clone(),
3036 entry_ids
: &HashMap
::new(),
3040 Attribute
::from(&mut context
, &read_attr
).unwrap().unwrap();
3041 assert_eq
!(convert_attr
, attr
);
3049 fn test_line_program_used() {
3050 for used
in vec
![false, true] {
3051 let encoding
= Encoding
{
3052 format
: Format
::Dwarf32
,
3057 let line_program
= LineProgram
::new(
3059 LineEncoding
::default(),
3060 LineString
::String(b
"comp_dir".to_vec()),
3061 LineString
::String(b
"comp_name".to_vec()),
3065 let mut unit
= Unit
::new(encoding
, line_program
);
3066 let file_id
= if used { Some(FileId::new(0)) }
else { None }
;
3067 let root
= unit
.root();
3068 unit
.get_mut(root
).set(
3069 constants
::DW_AT_decl_file
,
3070 AttributeValue
::FileIndex(file_id
),
3073 let mut units
= UnitTable
::default();
3076 let debug_line_str_offsets
= DebugLineStrOffsets
::none();
3077 let debug_str_offsets
= DebugStrOffsets
::none();
3078 let mut sections
= Sections
::new(EndianVec
::new(LittleEndian
));
3080 .write(&mut sections
, &debug_line_str_offsets
, &debug_str_offsets
)
3082 assert_eq
!(!used
, sections
.debug_line
.slice().is_empty());