diff options
Diffstat (limited to 'vendor/gimli/src')
-rw-r--r-- | vendor/gimli/src/common.rs | 18 | ||||
-rw-r--r-- | vendor/gimli/src/read/dwarf.rs | 37 | ||||
-rw-r--r-- | vendor/gimli/src/read/line.rs | 104 | ||||
-rw-r--r-- | vendor/gimli/src/read/mod.rs | 6 |
4 files changed, 163 insertions, 2 deletions
diff --git a/vendor/gimli/src/common.rs b/vendor/gimli/src/common.rs index 79cf76616..3c8073622 100644 --- a/vendor/gimli/src/common.rs +++ b/vendor/gimli/src/common.rs @@ -338,6 +338,24 @@ impl SectionId { _ => return None, }) } + + /// Returns the XCOFF section name for this kind. + pub fn xcoff_name(self) -> Option<&'static str> { + Some(match self { + SectionId::DebugAbbrev => ".dwabrev", + SectionId::DebugAranges => ".dwarnge", + SectionId::DebugFrame => ".dwframe", + SectionId::DebugInfo => ".dwinfo", + SectionId::DebugLine => ".dwline", + SectionId::DebugLoc => ".dwloc", + SectionId::DebugMacinfo => ".dwmac", + SectionId::DebugPubNames => ".dwpbnms", + SectionId::DebugPubTypes => ".dwpbtyp", + SectionId::DebugRanges => ".dwrnges", + SectionId::DebugStr => ".dwstr", + _ => return None, + }) + } } /// An optionally-provided implementation-defined compilation unit ID to enable diff --git a/vendor/gimli/src/read/dwarf.rs b/vendor/gimli/src/read/dwarf.rs index cce364c2b..bba0af3ef 100644 --- a/vendor/gimli/src/read/dwarf.rs +++ b/vendor/gimli/src/read/dwarf.rs @@ -571,6 +571,22 @@ impl<R: Reader> Dwarf<R> { } } +impl<R: Clone> Dwarf<R> { + /// Assuming `self` was loaded from a .dwo, take the appropriate + /// sections from `parent` (which contains the skeleton unit for this + /// dwo) such as `.debug_addr` and merge them into this `Dwarf`. + pub fn make_dwo(&mut self, parent: &Dwarf<R>) { + self.file_type = DwarfFileType::Dwo; + // These sections are always taken from the parent file and not the dwo. + self.debug_addr = parent.debug_addr.clone(); + // .debug_rnglists comes from the DWO, .debug_ranges comes from the + // parent file. + self.ranges + .set_debug_ranges(parent.ranges.debug_ranges().clone()); + self.sup = parent.sup.clone(); + } +} + /// The sections from a `.dwp` file. #[derive(Debug)] pub struct DwarfPackage<R: Reader> { @@ -787,7 +803,7 @@ impl<R: Reader> DwarfPackage<R> { locations: LocationLists::new(debug_loc, debug_loclists), ranges: RangeLists::new(debug_ranges, debug_rnglists), file_type: DwarfFileType::Dwo, - sup: None, + sup: parent.sup.clone(), abbreviations_cache: AbbreviationsCache::new(), }) } @@ -996,6 +1012,25 @@ impl<R: Reader> Unit<R> { self.rnglists_base = other.rnglists_base; } } + + /// Find the dwo name (if any) for this unit, automatically handling the differences + /// between the standardized DWARF 5 split DWARF format and the pre-DWARF 5 GNU + /// extension. + /// + /// The returned value is relative to this unit's `comp_dir`. + pub fn dwo_name(&self) -> Result<Option<AttributeValue<R>>> { + let mut entries = self.entries(); + if let None = entries.next_entry()? { + return Ok(None); + } + + let entry = entries.current().unwrap(); + if self.header.version() < 5 { + entry.attr_value(constants::DW_AT_GNU_dwo_name) + } else { + entry.attr_value(constants::DW_AT_dwo_name) + } + } } impl<T: ReaderOffset> UnitSectionOffset<T> { diff --git a/vendor/gimli/src/read/line.rs b/vendor/gimli/src/read/line.rs index f7f44b2b5..65400a99e 100644 --- a/vendor/gimli/src/read/line.rs +++ b/vendor/gimli/src/read/line.rs @@ -251,7 +251,14 @@ where Ok(None) => return Ok(None), Ok(Some(instruction)) => { if self.row.execute(instruction, &mut self.program) { - return Ok(Some((self.header(), &self.row))); + if self.row.tombstone { + // Perform any reset that was required for the tombstone row. + // Normally this is done when `next_row` is called again, but for + // tombstones we loop immediately. + self.row.reset(self.program.header()); + } else { + return Ok(Some((self.header(), &self.row))); + } } // Fall through, parse the next instruction, and see if that // yields a row. @@ -633,6 +640,7 @@ pub type LineNumberRow = LineRow; /// Each row is a copy of the registers of the state machine, as defined in section 6.2.2. #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct LineRow { + tombstone: bool, address: Wrapping<u64>, op_index: Wrapping<u64>, file: u64, @@ -653,6 +661,7 @@ impl LineRow { LineRow { // "At the beginning of each sequence within a line number program, the // state of the registers is:" -- Section 6.2.2 + tombstone: false, address: Wrapping(0), op_index: Wrapping(0), file: 1, @@ -878,6 +887,8 @@ impl LineRow { } LineInstruction::SetAddress(address) => { + let tombstone_address = !0 >> (64 - program.header().encoding.address_size * 8); + self.tombstone = address == tombstone_address; self.address.0 = address; self.op_index.0 = 0; false @@ -2831,6 +2842,19 @@ mod tests { } #[test] + fn test_exec_set_address_tombstone() { + let header = make_test_header(EndianSlice::new(&[], LittleEndian)); + let initial_registers = LineRow::new(&header); + let opcode = LineInstruction::SetAddress(!0); + + let mut expected_registers = initial_registers; + expected_registers.tombstone = true; + expected_registers.address.0 = !0; + + assert_exec_opcode(header, initial_registers, opcode, expected_registers, false); + } + + #[test] fn test_exec_define_file() { let mut program = make_test_program(EndianSlice::new(&[], LittleEndian)); let mut row = LineRow::new(program.header()); @@ -3025,4 +3049,82 @@ mod tests { assert_eq!(header.file(0), Some(&expected_file_names[0])); } } + + #[test] + fn test_sequences() { + #[rustfmt::skip] + let buf = [ + // 32-bit length + 94, 0x00, 0x00, 0x00, + // Version. + 0x04, 0x00, + // Header length = 40. + 0x28, 0x00, 0x00, 0x00, + // Minimum instruction length. + 0x01, + // Maximum operations per byte. + 0x01, + // Default is_stmt. + 0x01, + // Line base. + 0x00, + // Line range. + 0x01, + // Opcode base. + 0x03, + // Standard opcode lengths for opcodes 1 .. opcode base - 1. + 0x01, 0x02, + // Include directories = '/', 'i', 'n', 'c', '\0', '/', 'i', 'n', 'c', '2', '\0', '\0' + 0x2f, 0x69, 0x6e, 0x63, 0x00, 0x2f, 0x69, 0x6e, 0x63, 0x32, 0x00, 0x00, + // File names + // foo.rs + 0x66, 0x6f, 0x6f, 0x2e, 0x72, 0x73, 0x00, + 0x00, + 0x00, + 0x00, + // bar.h + 0x62, 0x61, 0x72, 0x2e, 0x68, 0x00, + 0x01, + 0x00, + 0x00, + // End file names. + 0x00, + + 0, 5, constants::DW_LNE_set_address.0, 1, 0, 0, 0, + constants::DW_LNS_copy.0, + constants::DW_LNS_advance_pc.0, 1, + constants::DW_LNS_copy.0, + constants::DW_LNS_advance_pc.0, 2, + 0, 1, constants::DW_LNE_end_sequence.0, + + // Tombstone + 0, 5, constants::DW_LNE_set_address.0, 0xff, 0xff, 0xff, 0xff, + constants::DW_LNS_copy.0, + constants::DW_LNS_advance_pc.0, 1, + constants::DW_LNS_copy.0, + constants::DW_LNS_advance_pc.0, 2, + 0, 1, constants::DW_LNE_end_sequence.0, + + 0, 5, constants::DW_LNE_set_address.0, 11, 0, 0, 0, + constants::DW_LNS_copy.0, + constants::DW_LNS_advance_pc.0, 1, + constants::DW_LNS_copy.0, + constants::DW_LNS_advance_pc.0, 2, + 0, 1, constants::DW_LNE_end_sequence.0, + ]; + assert_eq!(buf[0] as usize, buf.len() - 4); + + let rest = &mut EndianSlice::new(&buf, LittleEndian); + + let header = LineProgramHeader::parse(rest, DebugLineOffset(0), 4, None, None) + .expect("should parse header ok"); + let program = IncompleteLineProgram { header }; + + let sequences = program.sequences().unwrap().1; + assert_eq!(sequences.len(), 2); + assert_eq!(sequences[0].start, 1); + assert_eq!(sequences[0].end, 4); + assert_eq!(sequences[1].start, 11); + assert_eq!(sequences[1].end, 14); + } } diff --git a/vendor/gimli/src/read/mod.rs b/vendor/gimli/src/read/mod.rs index b2828d5f9..82b79502d 100644 --- a/vendor/gimli/src/read/mod.rs +++ b/vendor/gimli/src/read/mod.rs @@ -627,6 +627,12 @@ pub trait Section<R>: From<R> { Self::id().dwo_name() } + /// Returns the XCOFF section name (if any) for this type when used in a XCOFF + /// file. + fn xcoff_section_name() -> Option<&'static str> { + Self::id().xcoff_name() + } + /// Try to load the section using the given loader function. fn load<F, E>(f: F) -> core::result::Result<Self, E> where |