diff options
Diffstat (limited to 'vendor/gimli-0.25.0/tests')
-rw-r--r-- | vendor/gimli-0.25.0/tests/convert_self.rs | 158 | ||||
-rwxr-xr-x | vendor/gimli-0.25.0/tests/parse_self.rs | 431 |
2 files changed, 589 insertions, 0 deletions
diff --git a/vendor/gimli-0.25.0/tests/convert_self.rs b/vendor/gimli-0.25.0/tests/convert_self.rs new file mode 100644 index 000000000..ec8b592d3 --- /dev/null +++ b/vendor/gimli-0.25.0/tests/convert_self.rs @@ -0,0 +1,158 @@ +#![cfg(all(feature = "read", feature = "write"))] + +use std::env; +use std::fs::File; +use std::io::Read; +use std::path::PathBuf; + +use gimli::read; +use gimli::write::{self, Address, EndianVec}; +use gimli::LittleEndian; + +fn read_section(section: &str) -> Vec<u8> { + let mut path = PathBuf::new(); + if let Ok(dir) = env::var("CARGO_MANIFEST_DIR") { + path.push(dir); + } + path.push("fixtures/self"); + path.push(section); + + println!("Reading section \"{}\" at path {:?}", section, path); + assert!(path.is_file()); + let mut file = File::open(path).unwrap(); + + let mut buf = Vec::new(); + file.read_to_end(&mut buf).unwrap(); + buf +} + +#[test] +fn test_convert_debug_info() { + // Convert existing sections + let debug_abbrev = read_section("debug_abbrev"); + let debug_abbrev = read::DebugAbbrev::new(&debug_abbrev, LittleEndian); + + let debug_info = read_section("debug_info"); + let debug_info = read::DebugInfo::new(&debug_info, LittleEndian); + + let debug_line = read_section("debug_line"); + let debug_line = read::DebugLine::new(&debug_line, LittleEndian); + + let debug_str = read_section("debug_str"); + let debug_str = read::DebugStr::new(&debug_str, LittleEndian); + + let debug_ranges = read_section("debug_ranges"); + let debug_ranges = read::DebugRanges::new(&debug_ranges, LittleEndian); + + let debug_rnglists = read::DebugRngLists::new(&[], LittleEndian); + + let ranges = gimli::RangeLists::new(debug_ranges, debug_rnglists); + + let debug_loc = read_section("debug_loc"); + let debug_loc = read::DebugLoc::new(&debug_loc, LittleEndian); + + let debug_loclists = read::DebugLocLists::new(&[], LittleEndian); + + let locations = gimli::LocationLists::new(debug_loc, debug_loclists); + + let dwarf = read::Dwarf { + debug_abbrev, + debug_info, + debug_line, + debug_str, + ranges, + locations, + ..Default::default() + }; + + let mut dwarf = write::Dwarf::from(&dwarf, &|address| Some(Address::Constant(address))) + .expect("Should convert DWARF information"); + + assert_eq!(dwarf.units.count(), 23); + let entries: usize = (0..dwarf.units.count()) + .map(|i| dwarf.units.get(dwarf.units.id(i)).count()) + .sum(); + assert_eq!(entries, 29_560); + assert_eq!(dwarf.line_strings.count(), 0); + assert_eq!(dwarf.strings.count(), 3921); + + // Write to new sections + let mut write_sections = write::Sections::new(EndianVec::new(LittleEndian)); + dwarf + .write(&mut write_sections) + .expect("Should write DWARF information"); + let debug_info_data = write_sections.debug_info.slice(); + let debug_abbrev_data = write_sections.debug_abbrev.slice(); + let debug_line_data = write_sections.debug_line.slice(); + let debug_ranges_data = write_sections.debug_ranges.slice(); + let debug_loc_data = write_sections.debug_loc.slice(); + let debug_str_data = write_sections.debug_str.slice(); + assert_eq!(debug_info_data.len(), 394_930); + assert_eq!(debug_abbrev_data.len(), 9701); + assert_eq!(debug_line_data.len(), 105_797); + assert_eq!(debug_ranges_data.len(), 155_712); + assert_eq!(debug_loc_data.len(), 245_168); + assert_eq!(debug_str_data.len(), 144_731); + + // Convert new sections + let debug_abbrev = read::DebugAbbrev::new(debug_abbrev_data, LittleEndian); + let debug_info = read::DebugInfo::new(debug_info_data, LittleEndian); + let debug_line = read::DebugLine::new(debug_line_data, LittleEndian); + let debug_str = read::DebugStr::new(debug_str_data, LittleEndian); + let debug_ranges = read::DebugRanges::new(debug_ranges_data, LittleEndian); + let debug_rnglists = read::DebugRngLists::new(&[], LittleEndian); + let debug_loc = read::DebugLoc::new(debug_loc_data, LittleEndian); + let debug_loclists = read::DebugLocLists::new(&[], LittleEndian); + + let ranges = gimli::RangeLists::new(debug_ranges, debug_rnglists); + let locations = gimli::LocationLists::new(debug_loc, debug_loclists); + + let dwarf = read::Dwarf { + debug_abbrev, + debug_info, + debug_line, + debug_str, + ranges, + locations, + ..Default::default() + }; + + let dwarf = write::Dwarf::from(&dwarf, &|address| Some(Address::Constant(address))) + .expect("Should convert DWARF information"); + + assert_eq!(dwarf.units.count(), 23); + let entries: usize = (0..dwarf.units.count()) + .map(|i| dwarf.units.get(dwarf.units.id(i)).count()) + .sum(); + assert_eq!(entries, 29_560); + assert_eq!(dwarf.strings.count(), 3921); +} + +#[test] +fn test_convert_eh_frame() { + // Convert existing section + let eh_frame = read_section("eh_frame"); + let mut eh_frame = read::EhFrame::new(&eh_frame, LittleEndian); + // The `.eh_frame` fixture data was created on a 64-bit machine. + eh_frame.set_address_size(8); + let frames = write::FrameTable::from(&eh_frame, &|address| Some(Address::Constant(address))) + .expect("Should convert eh_frame information"); + assert_eq!(frames.cie_count(), 2); + assert_eq!(frames.fde_count(), 3482); + + // Write to new section + let mut write_eh_frame = write::EhFrame(EndianVec::new(LittleEndian)); + frames + .write_eh_frame(&mut write_eh_frame) + .expect("Should write eh_frame information"); + let eh_frame = write_eh_frame.slice(); + assert_eq!(eh_frame.len(), 147152); + + // Convert new section + let mut eh_frame = read::EhFrame::new(&eh_frame, LittleEndian); + eh_frame.set_address_size(8); + let frames = write::FrameTable::from(&eh_frame, &|address| Some(Address::Constant(address))) + .expect("Should convert eh_frame information"); + assert_eq!(frames.cie_count(), 2); + assert_eq!(frames.fde_count(), 3482); +} diff --git a/vendor/gimli-0.25.0/tests/parse_self.rs b/vendor/gimli-0.25.0/tests/parse_self.rs new file mode 100755 index 000000000..fb316314e --- /dev/null +++ b/vendor/gimli-0.25.0/tests/parse_self.rs @@ -0,0 +1,431 @@ +#![cfg(all(feature = "read", feature = "std", feature = "endian-reader"))] + +use gimli::{ + AttributeValue, DebugAbbrev, DebugAddr, DebugAddrBase, DebugAranges, DebugInfo, DebugLine, + DebugLoc, DebugLocLists, DebugPubNames, DebugPubTypes, DebugRanges, DebugRngLists, DebugStr, + Encoding, EndianSlice, Expression, LittleEndian, LocationLists, Operation, RangeLists, + RangeListsOffset, Reader, +}; +use std::collections::hash_map::HashMap; +use std::env; +use std::fs::File; +use std::io::Read; +use std::path::PathBuf; +use std::rc::Rc; + +fn read_section(section: &str) -> Vec<u8> { + let mut path = PathBuf::new(); + if let Ok(dir) = env::var("CARGO_MANIFEST_DIR") { + path.push(dir); + } + path.push("fixtures/self"); + path.push(section); + + println!("Reading section \"{}\" at path {:?}", section, path); + assert!(path.is_file()); + let mut file = File::open(path).unwrap(); + + let mut buf = Vec::new(); + file.read_to_end(&mut buf).unwrap(); + buf +} + +fn parse_expression<R: Reader>(expr: Expression<R>, encoding: Encoding) { + let mut pc = expr.0.clone(); + while !pc.is_empty() { + Operation::parse(&mut pc, encoding).expect("Should parse operation"); + } + + // Also attempt to evaluate some of it. + let mut eval = expr.evaluation(encoding); + eval.set_initial_value(0); + eval.evaluate().expect("Should evaluate expression"); +} + +fn impl_parse_self_debug_info<R: gimli::Reader>( + debug_info: &DebugInfo<R>, + debug_abbrev: &DebugAbbrev<R>, +) { + let mut iter = debug_info.units(); + while let Some(unit) = iter.next().expect("Should parse compilation unit") { + let abbrevs = unit + .abbreviations(&debug_abbrev) + .expect("Should parse abbreviations"); + + let mut cursor = unit.entries(&abbrevs); + + while cursor.next_dfs().expect("Should parse next dfs").is_some() { + let entry = cursor.current().expect("Should have a current entry"); + + let mut attrs = entry.attrs(); + while let Some(attr) = attrs.next().expect("Should parse entry's attribute") { + if let AttributeValue::Exprloc(expression) = attr.value() { + parse_expression(expression, unit.encoding()); + } + } + } + } +} + +#[test] +fn test_parse_self_debug_info() { + let debug_info = read_section("debug_info"); + let debug_info = DebugInfo::new(&debug_info, LittleEndian); + + let debug_abbrev = read_section("debug_abbrev"); + let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian); + + impl_parse_self_debug_info(&debug_info, &debug_abbrev); +} + +#[test] +fn test_parse_self_debug_info_with_endian_rc_slice() { + let debug_info = read_section("debug_info"); + let debug_info = Rc::from(&debug_info[..]); + let debug_info = gimli::EndianRcSlice::new(debug_info, LittleEndian); + let debug_info = DebugInfo::from(debug_info); + + let debug_abbrev = read_section("debug_abbrev"); + let debug_abbrev = Rc::from(&debug_abbrev[..]); + let debug_abbrev = gimli::EndianRcSlice::new(debug_abbrev, LittleEndian); + let debug_abbrev = DebugAbbrev::from(debug_abbrev); + + impl_parse_self_debug_info(&debug_info, &debug_abbrev); +} + +#[test] +fn test_parse_self_debug_line() { + let debug_info = read_section("debug_info"); + let debug_info = DebugInfo::new(&debug_info, LittleEndian); + + let debug_abbrev = read_section("debug_abbrev"); + let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian); + + let debug_line = read_section("debug_line"); + let debug_line = DebugLine::new(&debug_line, LittleEndian); + + let debug_str = read_section("debug_str"); + let debug_str = DebugStr::new(&debug_str, LittleEndian); + + let mut iter = debug_info.units(); + while let Some(unit) = iter.next().expect("Should parse compilation unit") { + let abbrevs = unit + .abbreviations(&debug_abbrev) + .expect("Should parse abbreviations"); + + let mut cursor = unit.entries(&abbrevs); + cursor.next_dfs().expect("Should parse next dfs"); + + let unit_entry = cursor.current().expect("Should have a root entry"); + + let comp_dir = unit_entry + .attr_value(gimli::DW_AT_comp_dir) + .expect("Should parse comp_dir attribute") + .and_then(|val| val.string_value(&debug_str)); + let comp_name = unit_entry + .attr_value(gimli::DW_AT_name) + .expect("Should parse name attribute") + .and_then(|val| val.string_value(&debug_str)); + + if let Some(AttributeValue::DebugLineRef(offset)) = unit_entry + .attr_value(gimli::DW_AT_stmt_list) + .expect("Should parse stmt_list") + { + let program = debug_line + .program(offset, unit.address_size(), comp_dir, comp_name) + .expect("should parse line number program header"); + + let mut results = Vec::new(); + let mut rows = program.rows(); + while let Some((_, row)) = rows + .next_row() + .expect("Should parse and execute all rows in the line number program") + { + results.push(*row); + } + results.reverse(); + + let program = debug_line + .program(offset, unit.address_size(), comp_dir, comp_name) + .expect("should parse line number program header"); + let (program, sequences) = program + .sequences() + .expect("should parse and execute the entire line number program"); + assert!(!sequences.is_empty()); // Should be at least one sequence. + for sequence in sequences { + let mut rows = program.resume_from(&sequence); + while let Some((_, row)) = rows + .next_row() + .expect("Should parse and execute all rows after resuming") + { + let other_row = results.pop().unwrap(); + assert!(row.address() >= sequence.start); + assert!(row.address() <= sequence.end); + assert_eq!(row.address(), other_row.address()); + assert_eq!(row.line(), other_row.line()); + } + } + assert!(results.is_empty()); + } + } +} + +#[test] +fn test_parse_self_debug_loc() { + let debug_info = read_section("debug_info"); + let debug_info = DebugInfo::new(&debug_info, LittleEndian); + + let debug_abbrev = read_section("debug_abbrev"); + let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian); + + let debug_addr = DebugAddr::from(EndianSlice::new(&[], LittleEndian)); + let debug_addr_base = DebugAddrBase(0); + + let debug_loc = read_section("debug_loc"); + let debug_loc = DebugLoc::new(&debug_loc, LittleEndian); + let debug_loclists = DebugLocLists::new(&[], LittleEndian); + let loclists = LocationLists::new(debug_loc, debug_loclists); + + let mut iter = debug_info.units(); + while let Some(unit) = iter.next().expect("Should parse compilation unit") { + let abbrevs = unit + .abbreviations(&debug_abbrev) + .expect("Should parse abbreviations"); + + let mut cursor = unit.entries(&abbrevs); + cursor.next_dfs().expect("Should parse next dfs"); + + let mut low_pc = 0; + + { + let unit_entry = cursor.current().expect("Should have a root entry"); + let low_pc_attr = unit_entry + .attr_value(gimli::DW_AT_low_pc) + .expect("Should parse low_pc"); + if let Some(gimli::AttributeValue::Addr(address)) = low_pc_attr { + low_pc = address; + } + } + + while cursor.next_dfs().expect("Should parse next dfs").is_some() { + let entry = cursor.current().expect("Should have a current entry"); + let mut attrs = entry.attrs(); + while let Some(attr) = attrs.next().expect("Should parse entry's attribute") { + if let AttributeValue::LocationListsRef(offset) = attr.value() { + let mut locs = loclists + .locations( + offset, + unit.encoding(), + low_pc, + &debug_addr, + debug_addr_base, + ) + .expect("Should parse locations OK"); + while let Some(loc) = locs.next().expect("Should parse next location") { + assert!(loc.range.begin <= loc.range.end); + parse_expression(loc.data, unit.encoding()); + } + } + } + } + } +} + +#[test] +fn test_parse_self_debug_ranges() { + let debug_info = read_section("debug_info"); + let debug_info = DebugInfo::new(&debug_info, LittleEndian); + + let debug_abbrev = read_section("debug_abbrev"); + let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian); + + let debug_addr = DebugAddr::from(EndianSlice::new(&[], LittleEndian)); + let debug_addr_base = DebugAddrBase(0); + + let debug_ranges = read_section("debug_ranges"); + let debug_ranges = DebugRanges::new(&debug_ranges, LittleEndian); + let debug_rnglists = DebugRngLists::new(&[], LittleEndian); + let rnglists = RangeLists::new(debug_ranges, debug_rnglists); + + let mut iter = debug_info.units(); + while let Some(unit) = iter.next().expect("Should parse compilation unit") { + let abbrevs = unit + .abbreviations(&debug_abbrev) + .expect("Should parse abbreviations"); + + let mut cursor = unit.entries(&abbrevs); + cursor.next_dfs().expect("Should parse next dfs"); + + let mut low_pc = 0; + + { + let unit_entry = cursor.current().expect("Should have a root entry"); + let low_pc_attr = unit_entry + .attr_value(gimli::DW_AT_low_pc) + .expect("Should parse low_pc"); + if let Some(gimli::AttributeValue::Addr(address)) = low_pc_attr { + low_pc = address; + } + } + + while cursor.next_dfs().expect("Should parse next dfs").is_some() { + let entry = cursor.current().expect("Should have a current entry"); + let mut attrs = entry.attrs(); + while let Some(attr) = attrs.next().expect("Should parse entry's attribute") { + if let AttributeValue::RangeListsRef(offset) = attr.value() { + let mut ranges = rnglists + .ranges( + RangeListsOffset(offset.0), + unit.encoding(), + low_pc, + &debug_addr, + debug_addr_base, + ) + .expect("Should parse ranges OK"); + while let Some(range) = ranges.next().expect("Should parse next range") { + assert!(range.begin <= range.end); + } + } + } + } + } +} + +#[test] +fn test_parse_self_debug_aranges() { + let debug_aranges = read_section("debug_aranges"); + let debug_aranges = DebugAranges::new(&debug_aranges, LittleEndian); + + let mut headers = debug_aranges.headers(); + while let Some(header) = headers.next().expect("Should parse arange header OK") { + let mut entries = header.entries(); + while let Some(_) = entries.next().expect("Should parse arange entry OK") { + // Not really anything else we can check right now. + } + } +} + +#[test] +fn test_parse_self_debug_pubnames() { + let debug_info = read_section("debug_info"); + let debug_info = DebugInfo::new(&debug_info, LittleEndian); + + let debug_abbrev = read_section("debug_abbrev"); + let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian); + + let debug_pubnames = read_section("debug_pubnames"); + let debug_pubnames = DebugPubNames::new(&debug_pubnames, LittleEndian); + + let mut units = HashMap::new(); + let mut abbrevs = HashMap::new(); + let mut pubnames = debug_pubnames.items(); + while let Some(entry) = pubnames.next().expect("Should parse pubname OK") { + let unit_offset = entry.unit_header_offset(); + let unit = units.entry(unit_offset).or_insert_with(|| { + debug_info + .header_from_offset(unit_offset) + .expect("Should parse unit header OK") + }); + let abbrev_offset = unit.debug_abbrev_offset(); + let abbrevs = abbrevs.entry(abbrev_offset).or_insert_with(|| { + debug_abbrev + .abbreviations(abbrev_offset) + .expect("Should parse abbreviations OK") + }); + let mut cursor = unit + .entries_at_offset(abbrevs, entry.die_offset()) + .expect("DIE offset should be valid"); + assert!(cursor.next_dfs().expect("Should parse DIE").is_some()); + } +} + +#[test] +fn test_parse_self_debug_pubtypes() { + let debug_info = read_section("debug_info"); + let debug_info = DebugInfo::new(&debug_info, LittleEndian); + + let debug_abbrev = read_section("debug_abbrev"); + let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian); + + let debug_pubtypes = read_section("debug_pubtypes"); + let debug_pubtypes = DebugPubTypes::new(&debug_pubtypes, LittleEndian); + + let mut units = HashMap::new(); + let mut abbrevs = HashMap::new(); + let mut pubtypes = debug_pubtypes.items(); + while let Some(entry) = pubtypes.next().expect("Should parse pubtype OK") { + let unit_offset = entry.unit_header_offset(); + let unit = units.entry(unit_offset).or_insert_with(|| { + debug_info + .header_from_offset(unit_offset) + .expect("Should parse unit header OK") + }); + let abbrev_offset = unit.debug_abbrev_offset(); + let abbrevs = abbrevs.entry(abbrev_offset).or_insert_with(|| { + debug_abbrev + .abbreviations(abbrev_offset) + .expect("Should parse abbreviations OK") + }); + let mut cursor = unit + .entries_at_offset(abbrevs, entry.die_offset()) + .expect("DIE offset should be valid"); + assert!(cursor.next_dfs().expect("Should parse DIE").is_some()); + } +} + +#[test] +fn test_parse_self_eh_frame() { + use gimli::{BaseAddresses, CieOrFde, EhFrame, UnwindSection}; + + let eh_frame = read_section("eh_frame"); + let mut eh_frame = EhFrame::new(&eh_frame, LittleEndian); + // The `.eh_frame` fixture data was created on a 64-bit machine. + eh_frame.set_address_size(8); + + let bases = BaseAddresses::default() + .set_eh_frame(0) + .set_text(0) + .set_got(0); + let mut entries = eh_frame.entries(&bases); + while let Some(entry) = entries.next().expect("Should parse CFI entry OK") { + match entry { + CieOrFde::Cie(cie) => { + let mut instrs = cie.instructions(&eh_frame, &bases); + while let Some(_) = instrs.next().expect("Can parse next CFI instruction OK") { + // TODO FITZGEN + } + } + CieOrFde::Fde(partial) => { + let fde = partial + .parse(UnwindSection::cie_from_offset) + .expect("Should be able to get CIE for FDE"); + + let mut instrs = fde.instructions(&eh_frame, &bases); + while let Some(_) = instrs.next().expect("Can parse next CFI instruction OK") { + // TODO FITZGEN + } + } + } + } +} + +#[test] +fn test_parse_self_eh_frame_hdr() { + use gimli::{BaseAddresses, EhFrameHdr}; + + let eh_frame_hdr = read_section("eh_frame_hdr"); + let eh_frame_hdr = EhFrameHdr::new(&eh_frame_hdr, LittleEndian); + + let bases = BaseAddresses::default() + .set_eh_frame(0) + .set_eh_frame_hdr(0) + .set_text(0) + .set_got(0); + + // `.eh_frame_hdr` was generated on a 64 bit machine. + let address_size = 8; + + let _parsed_header = eh_frame_hdr + .parse(&bases, address_size) + .expect("we can parse the `.eh_frame_hdr` section OK"); +} |