1 #![cfg(all(feature = "read", feature = "write"))]
2 
3 use std::env;
4 use std::fs::File;
5 use std::io::Read;
6 use std::path::PathBuf;
7 
8 use gimli::read;
9 use gimli::write::{self, Address, EndianVec};
10 use gimli::LittleEndian;
11 
read_section(section: &str) -> Vec<u8>12 fn read_section(section: &str) -> Vec<u8> {
13     let mut path = PathBuf::new();
14     if let Ok(dir) = env::var("CARGO_MANIFEST_DIR") {
15         path.push(dir);
16     }
17     path.push("fixtures/self");
18     path.push(section);
19 
20     println!("Reading section \"{}\" at path {:?}", section, path);
21     assert!(path.is_file());
22     let mut file = File::open(path).unwrap();
23 
24     let mut buf = Vec::new();
25     file.read_to_end(&mut buf).unwrap();
26     buf
27 }
28 
29 #[test]
test_convert_debug_info()30 fn test_convert_debug_info() {
31     // Convert existing sections
32     let debug_abbrev = read_section("debug_abbrev");
33     let debug_abbrev = read::DebugAbbrev::new(&debug_abbrev, LittleEndian);
34 
35     let debug_info = read_section("debug_info");
36     let debug_info = read::DebugInfo::new(&debug_info, LittleEndian);
37 
38     let debug_line = read_section("debug_line");
39     let debug_line = read::DebugLine::new(&debug_line, LittleEndian);
40 
41     let debug_str = read_section("debug_str");
42     let debug_str = read::DebugStr::new(&debug_str, LittleEndian);
43 
44     let debug_ranges = read_section("debug_ranges");
45     let debug_ranges = read::DebugRanges::new(&debug_ranges, LittleEndian);
46 
47     let debug_rnglists = read::DebugRngLists::new(&[], LittleEndian);
48 
49     let ranges = gimli::RangeLists::new(debug_ranges, debug_rnglists);
50 
51     let debug_loc = read_section("debug_loc");
52     let debug_loc = read::DebugLoc::new(&debug_loc, LittleEndian);
53 
54     let debug_loclists = read::DebugLocLists::new(&[], LittleEndian);
55 
56     let locations = gimli::LocationLists::new(debug_loc, debug_loclists);
57 
58     let dwarf = read::Dwarf {
59         debug_abbrev,
60         debug_info,
61         debug_line,
62         debug_str,
63         ranges,
64         locations,
65         ..Default::default()
66     };
67 
68     let mut dwarf = write::Dwarf::from(&dwarf, &|address| Some(Address::Constant(address)))
69         .expect("Should convert DWARF information");
70 
71     assert_eq!(dwarf.units.count(), 23);
72     let entries: usize = (0..dwarf.units.count())
73         .map(|i| dwarf.units.get(dwarf.units.id(i)).count())
74         .sum();
75     assert_eq!(entries, 29_560);
76     assert_eq!(dwarf.line_strings.count(), 0);
77     assert_eq!(dwarf.strings.count(), 3921);
78 
79     // Write to new sections
80     let mut write_sections = write::Sections::new(EndianVec::new(LittleEndian));
81     dwarf
82         .write(&mut write_sections)
83         .expect("Should write DWARF information");
84     let debug_info_data = write_sections.debug_info.slice();
85     let debug_abbrev_data = write_sections.debug_abbrev.slice();
86     let debug_line_data = write_sections.debug_line.slice();
87     let debug_ranges_data = write_sections.debug_ranges.slice();
88     let debug_loc_data = write_sections.debug_loc.slice();
89     let debug_str_data = write_sections.debug_str.slice();
90     assert_eq!(debug_info_data.len(), 394_930);
91     assert_eq!(debug_abbrev_data.len(), 9701);
92     assert_eq!(debug_line_data.len(), 105_797);
93     assert_eq!(debug_ranges_data.len(), 155_712);
94     assert_eq!(debug_loc_data.len(), 245_168);
95     assert_eq!(debug_str_data.len(), 144_731);
96 
97     // Convert new sections
98     let debug_abbrev = read::DebugAbbrev::new(debug_abbrev_data, LittleEndian);
99     let debug_info = read::DebugInfo::new(debug_info_data, LittleEndian);
100     let debug_line = read::DebugLine::new(debug_line_data, LittleEndian);
101     let debug_str = read::DebugStr::new(debug_str_data, LittleEndian);
102     let debug_ranges = read::DebugRanges::new(debug_ranges_data, LittleEndian);
103     let debug_rnglists = read::DebugRngLists::new(&[], LittleEndian);
104     let debug_loc = read::DebugLoc::new(debug_loc_data, LittleEndian);
105     let debug_loclists = read::DebugLocLists::new(&[], LittleEndian);
106 
107     let ranges = gimli::RangeLists::new(debug_ranges, debug_rnglists);
108     let locations = gimli::LocationLists::new(debug_loc, debug_loclists);
109 
110     let dwarf = read::Dwarf {
111         debug_abbrev,
112         debug_info,
113         debug_line,
114         debug_str,
115         ranges,
116         locations,
117         ..Default::default()
118     };
119 
120     let dwarf = write::Dwarf::from(&dwarf, &|address| Some(Address::Constant(address)))
121         .expect("Should convert DWARF information");
122 
123     assert_eq!(dwarf.units.count(), 23);
124     let entries: usize = (0..dwarf.units.count())
125         .map(|i| dwarf.units.get(dwarf.units.id(i)).count())
126         .sum();
127     assert_eq!(entries, 29_560);
128     assert_eq!(dwarf.strings.count(), 3921);
129 }
130 
131 #[test]
test_convert_eh_frame()132 fn test_convert_eh_frame() {
133     // Convert existing section
134     let eh_frame = read_section("eh_frame");
135     let mut eh_frame = read::EhFrame::new(&eh_frame, LittleEndian);
136     // The `.eh_frame` fixture data was created on a 64-bit machine.
137     eh_frame.set_address_size(8);
138     let frames = write::FrameTable::from(&eh_frame, &|address| Some(Address::Constant(address)))
139         .expect("Should convert eh_frame information");
140     assert_eq!(frames.cie_count(), 2);
141     assert_eq!(frames.fde_count(), 3482);
142 
143     // Write to new section
144     let mut write_eh_frame = write::EhFrame(EndianVec::new(LittleEndian));
145     frames
146         .write_eh_frame(&mut write_eh_frame)
147         .expect("Should write eh_frame information");
148     let eh_frame = write_eh_frame.slice();
149     assert_eq!(eh_frame.len(), 147152);
150 
151     // Convert new section
152     let mut eh_frame = read::EhFrame::new(&eh_frame, LittleEndian);
153     eh_frame.set_address_size(8);
154     let frames = write::FrameTable::from(&eh_frame, &|address| Some(Address::Constant(address)))
155         .expect("Should convert eh_frame information");
156     assert_eq!(frames.cie_count(), 2);
157     assert_eq!(frames.fde_count(), 3482);
158 }
159