/rust/registry/src/index.crates.io-1949cf8c6b5b557f/gimli-0.32.3/src/read/index.rs
Line | Count | Source |
1 | | use core::slice; |
2 | | |
3 | | use crate::common::SectionId; |
4 | | use crate::constants; |
5 | | use crate::endianity::Endianity; |
6 | | use crate::read::{EndianSlice, Error, Reader, ReaderOffset, Result, Section}; |
7 | | |
8 | | /// The data in the `.debug_cu_index` section of a `.dwp` file. |
9 | | /// |
10 | | /// This section contains the compilation unit index. |
11 | | #[derive(Debug, Default, Clone, Copy)] |
12 | | pub struct DebugCuIndex<R> { |
13 | | section: R, |
14 | | } |
15 | | |
16 | | impl<'input, Endian> DebugCuIndex<EndianSlice<'input, Endian>> |
17 | | where |
18 | | Endian: Endianity, |
19 | | { |
20 | | /// Construct a new `DebugCuIndex` instance from the data in the `.debug_cu_index` |
21 | | /// section. |
22 | 0 | pub fn new(section: &'input [u8], endian: Endian) -> Self { |
23 | 0 | Self::from(EndianSlice::new(section, endian)) |
24 | 0 | } |
25 | | } |
26 | | |
27 | | impl<T> DebugCuIndex<T> { |
28 | | /// Create a `DebugCuIndex` section that references the data in `self`. |
29 | | /// |
30 | | /// This is useful when `R` implements `Reader` but `T` does not. |
31 | | /// |
32 | | /// Used by `DwarfPackageSections::borrow`. |
33 | 0 | pub(crate) fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugCuIndex<R> |
34 | 0 | where |
35 | 0 | F: FnMut(&'a T) -> R, |
36 | | { |
37 | 0 | borrow(&self.section).into() |
38 | 0 | } |
39 | | } |
40 | | |
41 | | impl<R> Section<R> for DebugCuIndex<R> { |
42 | 0 | fn id() -> SectionId { |
43 | 0 | SectionId::DebugCuIndex |
44 | 0 | } Unexecuted instantiation: <gimli::read::index::DebugCuIndex<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>> as gimli::read::Section<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::id Unexecuted instantiation: <gimli::read::index::DebugCuIndex<_> as gimli::read::Section<_>>::id |
45 | | |
46 | 0 | fn reader(&self) -> &R { |
47 | 0 | &self.section |
48 | 0 | } |
49 | | } |
50 | | |
51 | | impl<R> From<R> for DebugCuIndex<R> { |
52 | 0 | fn from(section: R) -> Self { |
53 | 0 | DebugCuIndex { section } |
54 | 0 | } Unexecuted instantiation: <gimli::read::index::DebugCuIndex<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>> as core::convert::From<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::from Unexecuted instantiation: <gimli::read::index::DebugCuIndex<_> as core::convert::From<_>>::from |
55 | | } |
56 | | |
57 | | impl<R: Reader> DebugCuIndex<R> { |
58 | | /// Parse the index header. |
59 | 0 | pub fn index(self) -> Result<UnitIndex<R>> { |
60 | 0 | UnitIndex::parse(self.section) |
61 | 0 | } Unexecuted instantiation: <gimli::read::index::DebugCuIndex<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::index Unexecuted instantiation: <gimli::read::index::DebugCuIndex<_>>::index |
62 | | } |
63 | | |
64 | | /// The data in the `.debug_tu_index` section of a `.dwp` file. |
65 | | /// |
66 | | /// This section contains the type unit index. |
67 | | #[derive(Debug, Default, Clone, Copy)] |
68 | | pub struct DebugTuIndex<R> { |
69 | | section: R, |
70 | | } |
71 | | |
72 | | impl<'input, Endian> DebugTuIndex<EndianSlice<'input, Endian>> |
73 | | where |
74 | | Endian: Endianity, |
75 | | { |
76 | | /// Construct a new `DebugTuIndex` instance from the data in the `.debug_tu_index` |
77 | | /// section. |
78 | 0 | pub fn new(section: &'input [u8], endian: Endian) -> Self { |
79 | 0 | Self::from(EndianSlice::new(section, endian)) |
80 | 0 | } |
81 | | } |
82 | | |
83 | | impl<T> DebugTuIndex<T> { |
84 | | /// Create a `DebugTuIndex` section that references the data in `self`. |
85 | | /// |
86 | | /// This is useful when `R` implements `Reader` but `T` does not. |
87 | | /// |
88 | | /// Used by `DwarfPackageSections::borrow`. |
89 | 0 | pub(crate) fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugTuIndex<R> |
90 | 0 | where |
91 | 0 | F: FnMut(&'a T) -> R, |
92 | | { |
93 | 0 | borrow(&self.section).into() |
94 | 0 | } |
95 | | } |
96 | | |
97 | | impl<R> Section<R> for DebugTuIndex<R> { |
98 | 0 | fn id() -> SectionId { |
99 | 0 | SectionId::DebugTuIndex |
100 | 0 | } Unexecuted instantiation: <gimli::read::index::DebugTuIndex<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>> as gimli::read::Section<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::id Unexecuted instantiation: <gimli::read::index::DebugTuIndex<_> as gimli::read::Section<_>>::id |
101 | | |
102 | 0 | fn reader(&self) -> &R { |
103 | 0 | &self.section |
104 | 0 | } |
105 | | } |
106 | | |
107 | | impl<R> From<R> for DebugTuIndex<R> { |
108 | 0 | fn from(section: R) -> Self { |
109 | 0 | DebugTuIndex { section } |
110 | 0 | } Unexecuted instantiation: <gimli::read::index::DebugTuIndex<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>> as core::convert::From<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::from Unexecuted instantiation: <gimli::read::index::DebugTuIndex<_> as core::convert::From<_>>::from |
111 | | } |
112 | | |
113 | | impl<R: Reader> DebugTuIndex<R> { |
114 | | /// Parse the index header. |
115 | 0 | pub fn index(self) -> Result<UnitIndex<R>> { |
116 | 0 | UnitIndex::parse(self.section) |
117 | 0 | } Unexecuted instantiation: <gimli::read::index::DebugTuIndex<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::index Unexecuted instantiation: <gimli::read::index::DebugTuIndex<_>>::index |
118 | | } |
119 | | |
120 | | const SECTION_COUNT_MAX: u8 = 8; |
121 | | |
122 | | /// The partially parsed index from a `DebugCuIndex` or `DebugTuIndex`. |
123 | | #[derive(Debug, Clone)] |
124 | | pub struct UnitIndex<R: Reader> { |
125 | | version: u16, |
126 | | section_count: u32, |
127 | | unit_count: u32, |
128 | | slot_count: u32, |
129 | | hash_ids: R, |
130 | | hash_rows: R, |
131 | | // Only `section_count` values are valid. |
132 | | sections: [IndexSectionId; SECTION_COUNT_MAX as usize], |
133 | | offsets: R, |
134 | | sizes: R, |
135 | | } |
136 | | |
137 | | impl<R: Reader> UnitIndex<R> { |
138 | 0 | fn parse(mut input: R) -> Result<UnitIndex<R>> { |
139 | 0 | if input.is_empty() { |
140 | 0 | return Ok(UnitIndex { |
141 | 0 | version: 0, |
142 | 0 | section_count: 0, |
143 | 0 | unit_count: 0, |
144 | 0 | slot_count: 0, |
145 | 0 | hash_ids: input.clone(), |
146 | 0 | hash_rows: input.clone(), |
147 | 0 | sections: [IndexSectionId::DebugAbbrev; SECTION_COUNT_MAX as usize], |
148 | 0 | offsets: input.clone(), |
149 | 0 | sizes: input.clone(), |
150 | 0 | }); |
151 | 0 | } |
152 | | |
153 | | // GNU split-dwarf extension to DWARF 4 uses a 32-bit version, |
154 | | // but DWARF 5 uses a 16-bit version followed by 16-bit padding. |
155 | 0 | let mut original_input = input.clone(); |
156 | | let version; |
157 | 0 | if input.read_u32()? == 2 { |
158 | 0 | version = 2 |
159 | | } else { |
160 | 0 | version = original_input.read_u16()?; |
161 | 0 | if version != 5 { |
162 | 0 | return Err(Error::UnknownVersion(version.into())); |
163 | 0 | } |
164 | | } |
165 | | |
166 | 0 | let section_count = input.read_u32()?; |
167 | 0 | let unit_count = input.read_u32()?; |
168 | 0 | let slot_count = input.read_u32()?; |
169 | 0 | if slot_count != 0 && (slot_count & (slot_count - 1) != 0 || slot_count <= unit_count) { |
170 | 0 | return Err(Error::InvalidIndexSlotCount); |
171 | 0 | } |
172 | | |
173 | 0 | let hash_ids = input.split(R::Offset::from_u64(u64::from(slot_count) * 8)?)?; |
174 | 0 | let hash_rows = input.split(R::Offset::from_u64(u64::from(slot_count) * 4)?)?; |
175 | | |
176 | 0 | let mut sections = [IndexSectionId::DebugAbbrev; SECTION_COUNT_MAX as usize]; |
177 | 0 | if section_count > SECTION_COUNT_MAX.into() { |
178 | 0 | return Err(Error::InvalidIndexSectionCount); |
179 | 0 | } |
180 | 0 | for i in 0..section_count { |
181 | 0 | let section = input.read_u32()?; |
182 | 0 | sections[i as usize] = if version == 2 { |
183 | 0 | match constants::DwSectV2(section) { |
184 | 0 | constants::DW_SECT_V2_INFO => IndexSectionId::DebugInfo, |
185 | 0 | constants::DW_SECT_V2_TYPES => IndexSectionId::DebugTypes, |
186 | 0 | constants::DW_SECT_V2_ABBREV => IndexSectionId::DebugAbbrev, |
187 | 0 | constants::DW_SECT_V2_LINE => IndexSectionId::DebugLine, |
188 | 0 | constants::DW_SECT_V2_LOC => IndexSectionId::DebugLoc, |
189 | 0 | constants::DW_SECT_V2_STR_OFFSETS => IndexSectionId::DebugStrOffsets, |
190 | 0 | constants::DW_SECT_V2_MACINFO => IndexSectionId::DebugMacinfo, |
191 | 0 | constants::DW_SECT_V2_MACRO => IndexSectionId::DebugMacro, |
192 | 0 | section => return Err(Error::UnknownIndexSectionV2(section)), |
193 | | } |
194 | | } else { |
195 | 0 | match constants::DwSect(section) { |
196 | 0 | constants::DW_SECT_INFO => IndexSectionId::DebugInfo, |
197 | 0 | constants::DW_SECT_ABBREV => IndexSectionId::DebugAbbrev, |
198 | 0 | constants::DW_SECT_LINE => IndexSectionId::DebugLine, |
199 | 0 | constants::DW_SECT_LOCLISTS => IndexSectionId::DebugLocLists, |
200 | 0 | constants::DW_SECT_STR_OFFSETS => IndexSectionId::DebugStrOffsets, |
201 | 0 | constants::DW_SECT_MACRO => IndexSectionId::DebugMacro, |
202 | 0 | constants::DW_SECT_RNGLISTS => IndexSectionId::DebugRngLists, |
203 | 0 | section => return Err(Error::UnknownIndexSection(section)), |
204 | | } |
205 | | }; |
206 | | } |
207 | | |
208 | 0 | let offsets = input.split(R::Offset::from_u64( |
209 | 0 | u64::from(unit_count) * u64::from(section_count) * 4, |
210 | 0 | )?)?; |
211 | 0 | let sizes = input.split(R::Offset::from_u64( |
212 | 0 | u64::from(unit_count) * u64::from(section_count) * 4, |
213 | 0 | )?)?; |
214 | | |
215 | 0 | Ok(UnitIndex { |
216 | 0 | version, |
217 | 0 | section_count, |
218 | 0 | unit_count, |
219 | 0 | slot_count, |
220 | 0 | hash_ids, |
221 | 0 | hash_rows, |
222 | 0 | sections, |
223 | 0 | offsets, |
224 | 0 | sizes, |
225 | 0 | }) |
226 | 0 | } Unexecuted instantiation: <gimli::read::index::UnitIndex<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::parse Unexecuted instantiation: <gimli::read::index::UnitIndex<_>>::parse |
227 | | |
228 | | /// Find `id` in the index hash table, and return the row index. |
229 | | /// |
230 | | /// `id` may be a compilation unit ID if this index is from `.debug_cu_index`, |
231 | | /// or a type signature if this index is from `.debug_tu_index`. |
232 | 0 | pub fn find(&self, id: u64) -> Option<u32> { |
233 | 0 | if self.slot_count == 0 { |
234 | 0 | return None; |
235 | 0 | } |
236 | 0 | let mask = u64::from(self.slot_count - 1); |
237 | 0 | let mut hash1 = id & mask; |
238 | 0 | let hash2 = ((id >> 32) & mask) | 1; |
239 | 0 | for _ in 0..self.slot_count { |
240 | | // The length of these arrays was validated in `UnitIndex::parse`. |
241 | 0 | let mut hash_ids = self.hash_ids.clone(); |
242 | 0 | hash_ids.skip(R::Offset::from_u64(hash1 * 8).ok()?).ok()?; |
243 | 0 | let hash_id = hash_ids.read_u64().ok()?; |
244 | 0 | if hash_id == id { |
245 | 0 | let mut hash_rows = self.hash_rows.clone(); |
246 | 0 | hash_rows.skip(R::Offset::from_u64(hash1 * 4).ok()?).ok()?; |
247 | 0 | let hash_row = hash_rows.read_u32().ok()?; |
248 | 0 | return Some(hash_row); |
249 | 0 | } |
250 | 0 | if hash_id == 0 { |
251 | 0 | return None; |
252 | 0 | } |
253 | 0 | hash1 = (hash1 + hash2) & mask; |
254 | | } |
255 | 0 | None |
256 | 0 | } Unexecuted instantiation: <gimli::read::index::UnitIndex<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::find Unexecuted instantiation: <gimli::read::index::UnitIndex<_>>::find |
257 | | |
258 | | /// Return the section offsets and sizes for the given row index. |
259 | 0 | pub fn sections(&self, mut row: u32) -> Result<UnitIndexSectionIterator<'_, R>> { |
260 | 0 | if row == 0 { |
261 | 0 | return Err(Error::InvalidIndexRow); |
262 | 0 | } |
263 | 0 | row -= 1; |
264 | 0 | if row >= self.unit_count { |
265 | 0 | return Err(Error::InvalidIndexRow); |
266 | 0 | } |
267 | 0 | let mut offsets = self.offsets.clone(); |
268 | 0 | offsets.skip(R::Offset::from_u64( |
269 | 0 | u64::from(row) * u64::from(self.section_count) * 4, |
270 | 0 | )?)?; |
271 | 0 | let mut sizes = self.sizes.clone(); |
272 | 0 | sizes.skip(R::Offset::from_u64( |
273 | 0 | u64::from(row) * u64::from(self.section_count) * 4, |
274 | 0 | )?)?; |
275 | 0 | Ok(UnitIndexSectionIterator { |
276 | 0 | sections: self.sections[..self.section_count as usize].iter(), |
277 | 0 | offsets, |
278 | 0 | sizes, |
279 | 0 | }) |
280 | 0 | } Unexecuted instantiation: <gimli::read::index::UnitIndex<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::sections Unexecuted instantiation: <gimli::read::index::UnitIndex<_>>::sections |
281 | | |
282 | | /// Return the version. |
283 | | /// |
284 | | /// Defaults to 0 for empty sections. |
285 | 0 | pub fn version(&self) -> u16 { |
286 | 0 | self.version |
287 | 0 | } |
288 | | |
289 | | /// Return the number of sections. |
290 | 0 | pub fn section_count(&self) -> u32 { |
291 | 0 | self.section_count |
292 | 0 | } |
293 | | |
294 | | /// Return the number of units. |
295 | 0 | pub fn unit_count(&self) -> u32 { |
296 | 0 | self.unit_count |
297 | 0 | } |
298 | | |
299 | | /// Return the number of slots. |
300 | 0 | pub fn slot_count(&self) -> u32 { |
301 | 0 | self.slot_count |
302 | 0 | } |
303 | | } |
304 | | |
305 | | /// An iterator over the section offsets and sizes for a row in a `UnitIndex`. |
306 | | #[derive(Debug, Clone)] |
307 | | pub struct UnitIndexSectionIterator<'index, R: Reader> { |
308 | | sections: slice::Iter<'index, IndexSectionId>, |
309 | | offsets: R, |
310 | | sizes: R, |
311 | | } |
312 | | |
313 | | impl<'index, R: Reader> Iterator for UnitIndexSectionIterator<'index, R> { |
314 | | type Item = UnitIndexSection; |
315 | | |
316 | 0 | fn next(&mut self) -> Option<UnitIndexSection> { |
317 | 0 | let section = *self.sections.next()?; |
318 | | // The length of these arrays was validated in `UnitIndex::parse`. |
319 | 0 | let offset = self.offsets.read_u32().ok()?; |
320 | 0 | let size = self.sizes.read_u32().ok()?; |
321 | 0 | Some(UnitIndexSection { |
322 | 0 | section, |
323 | 0 | offset, |
324 | 0 | size, |
325 | 0 | }) |
326 | 0 | } Unexecuted instantiation: <gimli::read::index::UnitIndexSectionIterator<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>> as core::iter::traits::iterator::Iterator>::next Unexecuted instantiation: <gimli::read::index::UnitIndexSectionIterator<_> as core::iter::traits::iterator::Iterator>::next |
327 | | } |
328 | | |
329 | | /// Information about a unit's contribution to a section in a `.dwp` file. |
330 | | #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
331 | | pub struct UnitIndexSection { |
332 | | /// The section kind. |
333 | | pub section: IndexSectionId, |
334 | | /// The base offset of the unit's contribution to the section. |
335 | | pub offset: u32, |
336 | | /// The size of the unit's contribution to the section. |
337 | | pub size: u32, |
338 | | } |
339 | | |
340 | | /// Section kinds which are permitted in a `.dwp` index. |
341 | | #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
342 | | pub enum IndexSectionId { |
343 | | /// The `.debug_abbrev.dwo` section. |
344 | | DebugAbbrev, |
345 | | /// The `.debug_info.dwo` section. |
346 | | DebugInfo, |
347 | | /// The `.debug_line.dwo` section. |
348 | | DebugLine, |
349 | | /// The `.debug_loc.dwo` section. |
350 | | DebugLoc, |
351 | | /// The `.debug_loclists.dwo` section. |
352 | | DebugLocLists, |
353 | | /// The `.debug_macinfo.dwo` section. |
354 | | DebugMacinfo, |
355 | | /// The `.debug_macro.dwo` section. |
356 | | DebugMacro, |
357 | | /// The `.debug_rnglists.dwo` section. |
358 | | DebugRngLists, |
359 | | /// The `.debug_str_offsets.dwo` section. |
360 | | DebugStrOffsets, |
361 | | /// The `.debug_types.dwo` section. |
362 | | DebugTypes, |
363 | | } |
364 | | |
365 | | impl IndexSectionId { |
366 | | /// Returns the corresponding `SectionId`. |
367 | 0 | pub fn section_id(self) -> SectionId { |
368 | 0 | match self { |
369 | 0 | IndexSectionId::DebugAbbrev => SectionId::DebugAbbrev, |
370 | 0 | IndexSectionId::DebugInfo => SectionId::DebugInfo, |
371 | 0 | IndexSectionId::DebugLine => SectionId::DebugLine, |
372 | 0 | IndexSectionId::DebugLoc => SectionId::DebugLoc, |
373 | 0 | IndexSectionId::DebugLocLists => SectionId::DebugLocLists, |
374 | 0 | IndexSectionId::DebugMacro => SectionId::DebugMacro, |
375 | 0 | IndexSectionId::DebugMacinfo => SectionId::DebugMacinfo, |
376 | 0 | IndexSectionId::DebugRngLists => SectionId::DebugRngLists, |
377 | 0 | IndexSectionId::DebugStrOffsets => SectionId::DebugStrOffsets, |
378 | 0 | IndexSectionId::DebugTypes => SectionId::DebugTypes, |
379 | | } |
380 | 0 | } |
381 | | |
382 | | /// Returns the ELF section name for this kind, when found in a .dwo or .dwp file. |
383 | 0 | pub fn dwo_name(self) -> &'static str { |
384 | 0 | self.section_id().dwo_name().unwrap() |
385 | 0 | } |
386 | | } |
387 | | |
388 | | #[cfg(test)] |
389 | | mod tests { |
390 | | use super::*; |
391 | | use crate::endianity::BigEndian; |
392 | | use test_assembler::{Endian, Section}; |
393 | | |
394 | | #[test] |
395 | | fn test_empty() { |
396 | | let buf = EndianSlice::new(&[], BigEndian); |
397 | | let index = UnitIndex::parse(buf).unwrap(); |
398 | | assert_eq!(index.version(), 0); |
399 | | assert_eq!(index.unit_count(), 0); |
400 | | assert_eq!(index.slot_count(), 0); |
401 | | assert!(index.find(0).is_none()); |
402 | | } |
403 | | |
404 | | #[test] |
405 | | fn test_zero_slots() { |
406 | | #[rustfmt::skip] |
407 | | let section = Section::with_endian(Endian::Big) |
408 | | // Header. |
409 | | .D32(2).D32(0).D32(0).D32(0); |
410 | | let buf = section.get_contents().unwrap(); |
411 | | let buf = EndianSlice::new(&buf, BigEndian); |
412 | | let index = UnitIndex::parse(buf).unwrap(); |
413 | | assert_eq!(index.version(), 2); |
414 | | assert_eq!(index.unit_count(), 0); |
415 | | assert_eq!(index.slot_count(), 0); |
416 | | assert!(index.find(0).is_none()); |
417 | | } |
418 | | |
419 | | #[test] |
420 | | fn test_version_2() { |
421 | | #[rustfmt::skip] |
422 | | let section = Section::with_endian(Endian::Big) |
423 | | // Header. |
424 | | .D32(2).D32(0).D32(0).D32(1) |
425 | | // Slots. |
426 | | .D64(0).D32(0); |
427 | | let buf = section.get_contents().unwrap(); |
428 | | let buf = EndianSlice::new(&buf, BigEndian); |
429 | | let index = UnitIndex::parse(buf).unwrap(); |
430 | | assert_eq!(index.version, 2); |
431 | | } |
432 | | |
433 | | #[test] |
434 | | fn test_version_5() { |
435 | | #[rustfmt::skip] |
436 | | let section = Section::with_endian(Endian::Big) |
437 | | // Header. |
438 | | .D16(5).D16(0).D32(0).D32(0).D32(1) |
439 | | // Slots. |
440 | | .D64(0).D32(0); |
441 | | let buf = section.get_contents().unwrap(); |
442 | | let buf = EndianSlice::new(&buf, BigEndian); |
443 | | let index = UnitIndex::parse(buf).unwrap(); |
444 | | assert_eq!(index.version, 5); |
445 | | } |
446 | | |
447 | | #[test] |
448 | | fn test_version_5_invalid() { |
449 | | #[rustfmt::skip] |
450 | | let section = Section::with_endian(Endian::Big) |
451 | | // Header. |
452 | | .D32(5).D32(0).D32(0).D32(1) |
453 | | // Slots. |
454 | | .D64(0).D32(0); |
455 | | let buf = section.get_contents().unwrap(); |
456 | | let buf = EndianSlice::new(&buf, BigEndian); |
457 | | assert!(UnitIndex::parse(buf).is_err()); |
458 | | } |
459 | | |
460 | | #[test] |
461 | | fn test_version_2_sections() { |
462 | | #[rustfmt::skip] |
463 | | let section = Section::with_endian(Endian::Big) |
464 | | // Header. |
465 | | .D32(2).D32(8).D32(1).D32(2) |
466 | | // Slots. |
467 | | .D64(0).D64(0).D32(0).D32(0) |
468 | | // Sections. |
469 | | .D32(constants::DW_SECT_V2_INFO.0) |
470 | | .D32(constants::DW_SECT_V2_TYPES.0) |
471 | | .D32(constants::DW_SECT_V2_ABBREV.0) |
472 | | .D32(constants::DW_SECT_V2_LINE.0) |
473 | | .D32(constants::DW_SECT_V2_LOC.0) |
474 | | .D32(constants::DW_SECT_V2_STR_OFFSETS.0) |
475 | | .D32(constants::DW_SECT_V2_MACINFO.0) |
476 | | .D32(constants::DW_SECT_V2_MACRO.0) |
477 | | // Offsets. |
478 | | .D32(11).D32(12).D32(13).D32(14).D32(15).D32(16).D32(17).D32(18) |
479 | | // Sizes. |
480 | | .D32(21).D32(22).D32(23).D32(24).D32(25).D32(26).D32(27).D32(28); |
481 | | let buf = section.get_contents().unwrap(); |
482 | | let buf = EndianSlice::new(&buf, BigEndian); |
483 | | let index = UnitIndex::parse(buf).unwrap(); |
484 | | assert_eq!(index.section_count, 8); |
485 | | assert_eq!( |
486 | | index.sections, |
487 | | [ |
488 | | IndexSectionId::DebugInfo, |
489 | | IndexSectionId::DebugTypes, |
490 | | IndexSectionId::DebugAbbrev, |
491 | | IndexSectionId::DebugLine, |
492 | | IndexSectionId::DebugLoc, |
493 | | IndexSectionId::DebugStrOffsets, |
494 | | IndexSectionId::DebugMacinfo, |
495 | | IndexSectionId::DebugMacro, |
496 | | ] |
497 | | ); |
498 | | #[rustfmt::skip] |
499 | | let expect = [ |
500 | | UnitIndexSection { section: IndexSectionId::DebugInfo, offset: 11, size: 21 }, |
501 | | UnitIndexSection { section: IndexSectionId::DebugTypes, offset: 12, size: 22 }, |
502 | | UnitIndexSection { section: IndexSectionId::DebugAbbrev, offset: 13, size: 23 }, |
503 | | UnitIndexSection { section: IndexSectionId::DebugLine, offset: 14, size: 24 }, |
504 | | UnitIndexSection { section: IndexSectionId::DebugLoc, offset: 15, size: 25 }, |
505 | | UnitIndexSection { section: IndexSectionId::DebugStrOffsets, offset: 16, size: 26 }, |
506 | | UnitIndexSection { section: IndexSectionId::DebugMacinfo, offset: 17, size: 27 }, |
507 | | UnitIndexSection { section: IndexSectionId::DebugMacro, offset: 18, size: 28 }, |
508 | | ]; |
509 | | let mut sections = index.sections(1).unwrap(); |
510 | | for section in &expect { |
511 | | assert_eq!(*section, sections.next().unwrap()); |
512 | | } |
513 | | assert!(sections.next().is_none()); |
514 | | } |
515 | | |
516 | | #[test] |
517 | | fn test_version_5_sections() { |
518 | | #[rustfmt::skip] |
519 | | let section = Section::with_endian(Endian::Big) |
520 | | // Header. |
521 | | .D16(5).D16(0).D32(7).D32(1).D32(2) |
522 | | // Slots. |
523 | | .D64(0).D64(0).D32(0).D32(0) |
524 | | // Sections. |
525 | | .D32(constants::DW_SECT_INFO.0) |
526 | | .D32(constants::DW_SECT_ABBREV.0) |
527 | | .D32(constants::DW_SECT_LINE.0) |
528 | | .D32(constants::DW_SECT_LOCLISTS.0) |
529 | | .D32(constants::DW_SECT_STR_OFFSETS.0) |
530 | | .D32(constants::DW_SECT_MACRO.0) |
531 | | .D32(constants::DW_SECT_RNGLISTS.0) |
532 | | // Offsets. |
533 | | .D32(11).D32(12).D32(13).D32(14).D32(15).D32(16).D32(17) |
534 | | // Sizes. |
535 | | .D32(21).D32(22).D32(23).D32(24).D32(25).D32(26).D32(27); |
536 | | let buf = section.get_contents().unwrap(); |
537 | | let buf = EndianSlice::new(&buf, BigEndian); |
538 | | let index = UnitIndex::parse(buf).unwrap(); |
539 | | assert_eq!(index.section_count, 7); |
540 | | assert_eq!( |
541 | | index.sections[..7], |
542 | | [ |
543 | | IndexSectionId::DebugInfo, |
544 | | IndexSectionId::DebugAbbrev, |
545 | | IndexSectionId::DebugLine, |
546 | | IndexSectionId::DebugLocLists, |
547 | | IndexSectionId::DebugStrOffsets, |
548 | | IndexSectionId::DebugMacro, |
549 | | IndexSectionId::DebugRngLists, |
550 | | ] |
551 | | ); |
552 | | #[rustfmt::skip] |
553 | | let expect = [ |
554 | | UnitIndexSection { section: IndexSectionId::DebugInfo, offset: 11, size: 21 }, |
555 | | UnitIndexSection { section: IndexSectionId::DebugAbbrev, offset: 12, size: 22 }, |
556 | | UnitIndexSection { section: IndexSectionId::DebugLine, offset: 13, size: 23 }, |
557 | | UnitIndexSection { section: IndexSectionId::DebugLocLists, offset: 14, size: 24 }, |
558 | | UnitIndexSection { section: IndexSectionId::DebugStrOffsets, offset: 15, size: 25 }, |
559 | | UnitIndexSection { section: IndexSectionId::DebugMacro, offset: 16, size: 26 }, |
560 | | UnitIndexSection { section: IndexSectionId::DebugRngLists, offset: 17, size: 27 }, |
561 | | ]; |
562 | | let mut sections = index.sections(1).unwrap(); |
563 | | for section in &expect { |
564 | | assert_eq!(*section, sections.next().unwrap()); |
565 | | } |
566 | | assert!(sections.next().is_none()); |
567 | | |
568 | | assert!(index.sections(0).is_err()); |
569 | | assert!(index.sections(2).is_err()); |
570 | | } |
571 | | |
572 | | #[test] |
573 | | fn test_hash() { |
574 | | #[rustfmt::skip] |
575 | | let section = Section::with_endian(Endian::Big) |
576 | | // Header. |
577 | | .D16(5).D16(0).D32(2).D32(3).D32(4) |
578 | | // Slots. |
579 | | .D64(0xffff_fff2_ffff_fff1) |
580 | | .D64(0xffff_fff0_ffff_fff1) |
581 | | .D64(0xffff_fff1_ffff_fff1) |
582 | | .D64(0) |
583 | | .D32(3).D32(1).D32(2).D32(0) |
584 | | // Sections. |
585 | | .D32(constants::DW_SECT_INFO.0) |
586 | | .D32(constants::DW_SECT_ABBREV.0) |
587 | | // Offsets. |
588 | | .D32(0).D32(0).D32(0).D32(0).D32(0).D32(0) |
589 | | // Sizes. |
590 | | .D32(0).D32(0).D32(0).D32(0).D32(0).D32(0); |
591 | | let buf = section.get_contents().unwrap(); |
592 | | let buf = EndianSlice::new(&buf, BigEndian); |
593 | | let index = UnitIndex::parse(buf).unwrap(); |
594 | | assert_eq!(index.version(), 5); |
595 | | assert_eq!(index.slot_count(), 4); |
596 | | assert_eq!(index.unit_count(), 3); |
597 | | assert_eq!(index.section_count(), 2); |
598 | | assert_eq!(index.find(0xffff_fff0_ffff_fff1), Some(1)); |
599 | | assert_eq!(index.find(0xffff_fff1_ffff_fff1), Some(2)); |
600 | | assert_eq!(index.find(0xffff_fff2_ffff_fff1), Some(3)); |
601 | | assert_eq!(index.find(0xffff_fff3_ffff_fff1), None); |
602 | | } |
603 | | |
604 | | #[test] |
605 | | fn test_cu_index() { |
606 | | #[rustfmt::skip] |
607 | | let section = Section::with_endian(Endian::Big) |
608 | | // Header. |
609 | | .D16(5).D16(0).D32(0).D32(0).D32(1) |
610 | | // Slots. |
611 | | .D64(0).D32(0); |
612 | | let buf = section.get_contents().unwrap(); |
613 | | let cu_index = DebugCuIndex::new(&buf, BigEndian); |
614 | | let index = cu_index.index().unwrap(); |
615 | | assert_eq!(index.version, 5); |
616 | | } |
617 | | |
618 | | #[test] |
619 | | fn test_tu_index() { |
620 | | #[rustfmt::skip] |
621 | | let section = Section::with_endian(Endian::Big) |
622 | | // Header. |
623 | | .D16(5).D16(0).D32(0).D32(0).D32(1) |
624 | | // Slots. |
625 | | .D64(0).D32(0); |
626 | | let buf = section.get_contents().unwrap(); |
627 | | let tu_index = DebugTuIndex::new(&buf, BigEndian); |
628 | | let index = tu_index.index().unwrap(); |
629 | | assert_eq!(index.version, 5); |
630 | | } |
631 | | } |