1 use crate::common::{ 2 DebugAddrBase, DebugAddrIndex, DebugRngListsBase, DebugRngListsIndex, DwarfFileType, Encoding, 3 RangeListsOffset, SectionId, 4 }; 5 use crate::constants; 6 use crate::endianity::Endianity; 7 use crate::read::{ 8 lists::ListsHeader, DebugAddr, EndianSlice, Error, Reader, ReaderOffset, ReaderOffsetId, 9 Result, Section, 10 }; 11 12 /// The raw contents of the `.debug_ranges` section. 13 #[derive(Debug, Default, Clone, Copy)] 14 pub struct DebugRanges<R> { 15 pub(crate) section: R, 16 } 17 18 impl<'input, Endian> DebugRanges<EndianSlice<'input, Endian>> 19 where 20 Endian: Endianity, 21 { 22 /// Construct a new `DebugRanges` instance from the data in the `.debug_ranges` 23 /// section. 24 /// 25 /// It is the caller's responsibility to read the `.debug_ranges` section and 26 /// present it as a `&[u8]` slice. That means using some ELF loader on 27 /// Linux, a Mach-O loader on OSX, etc. 28 /// 29 /// ``` 30 /// use gimli::{DebugRanges, LittleEndian}; 31 /// 32 /// # let buf = [0x00, 0x01, 0x02, 0x03]; 33 /// # let read_debug_ranges_section_somehow = || &buf; 34 /// let debug_ranges = DebugRanges::new(read_debug_ranges_section_somehow(), LittleEndian); 35 /// ``` new(section: &'input [u8], endian: Endian) -> Self36 pub fn new(section: &'input [u8], endian: Endian) -> Self { 37 Self::from(EndianSlice::new(section, endian)) 38 } 39 } 40 41 impl<R> Section<R> for DebugRanges<R> { id() -> SectionId42 fn id() -> SectionId { 43 SectionId::DebugRanges 44 } 45 reader(&self) -> &R46 fn reader(&self) -> &R { 47 &self.section 48 } 49 } 50 51 impl<R> From<R> for DebugRanges<R> { from(section: R) -> Self52 fn from(section: R) -> Self { 53 DebugRanges { section } 54 } 55 } 56 57 /// The `DebugRngLists` struct represents the contents of the 58 /// `.debug_rnglists` section. 59 #[derive(Debug, Default, Clone, Copy)] 60 pub struct DebugRngLists<R> { 61 section: R, 62 } 63 64 impl<'input, Endian> DebugRngLists<EndianSlice<'input, Endian>> 65 where 66 Endian: Endianity, 67 { 68 /// Construct a new `DebugRngLists` instance from the data in the 69 /// `.debug_rnglists` section. 70 /// 71 /// It is the caller's responsibility to read the `.debug_rnglists` 72 /// section and present it as a `&[u8]` slice. That means using some ELF 73 /// loader on Linux, a Mach-O loader on OSX, etc. 74 /// 75 /// ``` 76 /// use gimli::{DebugRngLists, LittleEndian}; 77 /// 78 /// # let buf = [0x00, 0x01, 0x02, 0x03]; 79 /// # let read_debug_rnglists_section_somehow = || &buf; 80 /// let debug_rnglists = 81 /// DebugRngLists::new(read_debug_rnglists_section_somehow(), LittleEndian); 82 /// ``` new(section: &'input [u8], endian: Endian) -> Self83 pub fn new(section: &'input [u8], endian: Endian) -> Self { 84 Self::from(EndianSlice::new(section, endian)) 85 } 86 } 87 88 impl<R> Section<R> for DebugRngLists<R> { id() -> SectionId89 fn id() -> SectionId { 90 SectionId::DebugRngLists 91 } 92 reader(&self) -> &R93 fn reader(&self) -> &R { 94 &self.section 95 } 96 } 97 98 impl<R> From<R> for DebugRngLists<R> { from(section: R) -> Self99 fn from(section: R) -> Self { 100 DebugRngLists { section } 101 } 102 } 103 104 #[allow(unused)] 105 pub(crate) type RngListsHeader = ListsHeader; 106 107 impl<Offset> DebugRngListsBase<Offset> 108 where 109 Offset: ReaderOffset, 110 { 111 /// Returns a `DebugRngListsBase` with the default value of DW_AT_rnglists_base 112 /// for the given `Encoding` and `DwarfFileType`. default_for_encoding_and_file( encoding: Encoding, file_type: DwarfFileType, ) -> DebugRngListsBase<Offset>113 pub fn default_for_encoding_and_file( 114 encoding: Encoding, 115 file_type: DwarfFileType, 116 ) -> DebugRngListsBase<Offset> { 117 if encoding.version >= 5 && file_type == DwarfFileType::Dwo { 118 // In .dwo files, the compiler omits the DW_AT_rnglists_base attribute (because there is 119 // only a single unit in the file) but we must skip past the header, which the attribute 120 // would normally do for us. 121 DebugRngListsBase(Offset::from_u8(RngListsHeader::size_for_encoding(encoding))) 122 } else { 123 DebugRngListsBase(Offset::from_u8(0)) 124 } 125 } 126 } 127 128 /// The DWARF data found in `.debug_ranges` and `.debug_rnglists` sections. 129 #[derive(Debug, Default, Clone, Copy)] 130 pub struct RangeLists<R> { 131 debug_ranges: DebugRanges<R>, 132 debug_rnglists: DebugRngLists<R>, 133 } 134 135 impl<R> RangeLists<R> { 136 /// Construct a new `RangeLists` instance from the data in the `.debug_ranges` and 137 /// `.debug_rnglists` sections. new(debug_ranges: DebugRanges<R>, debug_rnglists: DebugRngLists<R>) -> RangeLists<R>138 pub fn new(debug_ranges: DebugRanges<R>, debug_rnglists: DebugRngLists<R>) -> RangeLists<R> { 139 RangeLists { 140 debug_ranges, 141 debug_rnglists, 142 } 143 } 144 145 /// Return the `.debug_ranges` section. debug_ranges(&self) -> &DebugRanges<R>146 pub fn debug_ranges(&self) -> &DebugRanges<R> { 147 &self.debug_ranges 148 } 149 150 /// Replace the `.debug_ranges` section. 151 /// 152 /// This is useful for `.dwo` files when using the GNU split-dwarf extension to DWARF 4. set_debug_ranges(&mut self, debug_ranges: DebugRanges<R>)153 pub fn set_debug_ranges(&mut self, debug_ranges: DebugRanges<R>) { 154 self.debug_ranges = debug_ranges; 155 } 156 157 /// Return the `.debug_rnglists` section. debug_rnglists(&self) -> &DebugRngLists<R>158 pub fn debug_rnglists(&self) -> &DebugRngLists<R> { 159 &self.debug_rnglists 160 } 161 } 162 163 impl<T> RangeLists<T> { 164 /// Create a `RangeLists` that references the data in `self`. 165 /// 166 /// This is useful when `R` implements `Reader` but `T` does not. 167 /// 168 /// ## Example Usage 169 /// 170 /// ```rust,no_run 171 /// # let load_section = || unimplemented!(); 172 /// // Read the DWARF section into a `Vec` with whatever object loader you're using. 173 /// let owned_section: gimli::RangeLists<Vec<u8>> = load_section(); 174 /// // Create a reference to the DWARF section. 175 /// let section = owned_section.borrow(|section| { 176 /// gimli::EndianSlice::new(§ion, gimli::LittleEndian) 177 /// }); 178 /// ``` borrow<'a, F, R>(&'a self, mut borrow: F) -> RangeLists<R> where F: FnMut(&'a T) -> R,179 pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> RangeLists<R> 180 where 181 F: FnMut(&'a T) -> R, 182 { 183 RangeLists { 184 debug_ranges: borrow(&self.debug_ranges.section).into(), 185 debug_rnglists: borrow(&self.debug_rnglists.section).into(), 186 } 187 } 188 } 189 190 impl<R: Reader> RangeLists<R> { 191 /// Iterate over the `Range` list entries starting at the given offset. 192 /// 193 /// The `unit_version` and `address_size` must match the compilation unit that the 194 /// offset was contained in. 195 /// 196 /// The `base_address` should be obtained from the `DW_AT_low_pc` attribute in the 197 /// `DW_TAG_compile_unit` entry for the compilation unit that contains this range list. 198 /// 199 /// Can be [used with 200 /// `FallibleIterator`](./index.html#using-with-fallibleiterator). ranges( &self, offset: RangeListsOffset<R::Offset>, unit_encoding: Encoding, base_address: u64, debug_addr: &DebugAddr<R>, debug_addr_base: DebugAddrBase<R::Offset>, ) -> Result<RngListIter<R>>201 pub fn ranges( 202 &self, 203 offset: RangeListsOffset<R::Offset>, 204 unit_encoding: Encoding, 205 base_address: u64, 206 debug_addr: &DebugAddr<R>, 207 debug_addr_base: DebugAddrBase<R::Offset>, 208 ) -> Result<RngListIter<R>> { 209 Ok(RngListIter::new( 210 self.raw_ranges(offset, unit_encoding)?, 211 base_address, 212 debug_addr.clone(), 213 debug_addr_base, 214 )) 215 } 216 217 /// Iterate over the `RawRngListEntry`ies starting at the given offset. 218 /// 219 /// The `unit_encoding` must match the compilation unit that the 220 /// offset was contained in. 221 /// 222 /// This iterator does not perform any processing of the range entries, 223 /// such as handling base addresses. 224 /// 225 /// Can be [used with 226 /// `FallibleIterator`](./index.html#using-with-fallibleiterator). raw_ranges( &self, offset: RangeListsOffset<R::Offset>, unit_encoding: Encoding, ) -> Result<RawRngListIter<R>>227 pub fn raw_ranges( 228 &self, 229 offset: RangeListsOffset<R::Offset>, 230 unit_encoding: Encoding, 231 ) -> Result<RawRngListIter<R>> { 232 let (mut input, format) = if unit_encoding.version <= 4 { 233 (self.debug_ranges.section.clone(), RangeListsFormat::Bare) 234 } else { 235 (self.debug_rnglists.section.clone(), RangeListsFormat::RLE) 236 }; 237 input.skip(offset.0)?; 238 Ok(RawRngListIter::new(input, unit_encoding, format)) 239 } 240 241 /// Returns the `.debug_rnglists` offset at the given `base` and `index`. 242 /// 243 /// The `base` must be the `DW_AT_rnglists_base` value from the compilation unit DIE. 244 /// This is an offset that points to the first entry following the header. 245 /// 246 /// The `index` is the value of a `DW_FORM_rnglistx` attribute. 247 /// 248 /// The `unit_encoding` must match the compilation unit that the 249 /// index was contained in. get_offset( &self, unit_encoding: Encoding, base: DebugRngListsBase<R::Offset>, index: DebugRngListsIndex<R::Offset>, ) -> Result<RangeListsOffset<R::Offset>>250 pub fn get_offset( 251 &self, 252 unit_encoding: Encoding, 253 base: DebugRngListsBase<R::Offset>, 254 index: DebugRngListsIndex<R::Offset>, 255 ) -> Result<RangeListsOffset<R::Offset>> { 256 let format = unit_encoding.format; 257 let input = &mut self.debug_rnglists.section.clone(); 258 input.skip(base.0)?; 259 input.skip(R::Offset::from_u64( 260 index.0.into_u64() * u64::from(format.word_size()), 261 )?)?; 262 input 263 .read_offset(format) 264 .map(|x| RangeListsOffset(base.0 + x)) 265 } 266 267 /// Call `Reader::lookup_offset_id` for each section, and return the first match. lookup_offset_id(&self, id: ReaderOffsetId) -> Option<(SectionId, R::Offset)>268 pub fn lookup_offset_id(&self, id: ReaderOffsetId) -> Option<(SectionId, R::Offset)> { 269 self.debug_ranges 270 .lookup_offset_id(id) 271 .or_else(|| self.debug_rnglists.lookup_offset_id(id)) 272 } 273 } 274 275 #[derive(Debug, Clone, Copy, PartialEq, Eq)] 276 enum RangeListsFormat { 277 /// The bare range list format used before DWARF 5. 278 Bare, 279 /// The DW_RLE encoded range list format used in DWARF 5. 280 RLE, 281 } 282 283 /// A raw iterator over an address range list. 284 /// 285 /// This iterator does not perform any processing of the range entries, 286 /// such as handling base addresses. 287 #[derive(Debug)] 288 pub struct RawRngListIter<R: Reader> { 289 input: R, 290 encoding: Encoding, 291 format: RangeListsFormat, 292 } 293 294 /// A raw entry in .debug_rnglists 295 #[derive(Clone, Debug)] 296 pub enum RawRngListEntry<T> { 297 /// A range from DWARF version <= 4. 298 AddressOrOffsetPair { 299 /// Start of range. May be an address or an offset. 300 begin: u64, 301 /// End of range. May be an address or an offset. 302 end: u64, 303 }, 304 /// DW_RLE_base_address 305 BaseAddress { 306 /// base address 307 addr: u64, 308 }, 309 /// DW_RLE_base_addressx 310 BaseAddressx { 311 /// base address 312 addr: DebugAddrIndex<T>, 313 }, 314 /// DW_RLE_startx_endx 315 StartxEndx { 316 /// start of range 317 begin: DebugAddrIndex<T>, 318 /// end of range 319 end: DebugAddrIndex<T>, 320 }, 321 /// DW_RLE_startx_length 322 StartxLength { 323 /// start of range 324 begin: DebugAddrIndex<T>, 325 /// length of range 326 length: u64, 327 }, 328 /// DW_RLE_offset_pair 329 OffsetPair { 330 /// start of range 331 begin: u64, 332 /// end of range 333 end: u64, 334 }, 335 /// DW_RLE_start_end 336 StartEnd { 337 /// start of range 338 begin: u64, 339 /// end of range 340 end: u64, 341 }, 342 /// DW_RLE_start_length 343 StartLength { 344 /// start of range 345 begin: u64, 346 /// length of range 347 length: u64, 348 }, 349 } 350 351 impl<T: ReaderOffset> RawRngListEntry<T> { 352 /// Parse a range entry from `.debug_rnglists` parse<R: Reader<Offset = T>>( input: &mut R, encoding: Encoding, format: RangeListsFormat, ) -> Result<Option<Self>>353 fn parse<R: Reader<Offset = T>>( 354 input: &mut R, 355 encoding: Encoding, 356 format: RangeListsFormat, 357 ) -> Result<Option<Self>> { 358 match format { 359 RangeListsFormat::Bare => { 360 let range = RawRange::parse(input, encoding.address_size)?; 361 return Ok(if range.is_end() { 362 None 363 } else if range.is_base_address(encoding.address_size) { 364 Some(RawRngListEntry::BaseAddress { addr: range.end }) 365 } else { 366 Some(RawRngListEntry::AddressOrOffsetPair { 367 begin: range.begin, 368 end: range.end, 369 }) 370 }); 371 } 372 RangeListsFormat::RLE => Ok(match constants::DwRle(input.read_u8()?) { 373 constants::DW_RLE_end_of_list => None, 374 constants::DW_RLE_base_addressx => Some(RawRngListEntry::BaseAddressx { 375 addr: DebugAddrIndex(input.read_uleb128().and_then(R::Offset::from_u64)?), 376 }), 377 constants::DW_RLE_startx_endx => Some(RawRngListEntry::StartxEndx { 378 begin: DebugAddrIndex(input.read_uleb128().and_then(R::Offset::from_u64)?), 379 end: DebugAddrIndex(input.read_uleb128().and_then(R::Offset::from_u64)?), 380 }), 381 constants::DW_RLE_startx_length => Some(RawRngListEntry::StartxLength { 382 begin: DebugAddrIndex(input.read_uleb128().and_then(R::Offset::from_u64)?), 383 length: input.read_uleb128()?, 384 }), 385 constants::DW_RLE_offset_pair => Some(RawRngListEntry::OffsetPair { 386 begin: input.read_uleb128()?, 387 end: input.read_uleb128()?, 388 }), 389 constants::DW_RLE_base_address => Some(RawRngListEntry::BaseAddress { 390 addr: input.read_address(encoding.address_size)?, 391 }), 392 constants::DW_RLE_start_end => Some(RawRngListEntry::StartEnd { 393 begin: input.read_address(encoding.address_size)?, 394 end: input.read_address(encoding.address_size)?, 395 }), 396 constants::DW_RLE_start_length => Some(RawRngListEntry::StartLength { 397 begin: input.read_address(encoding.address_size)?, 398 length: input.read_uleb128()?, 399 }), 400 _ => { 401 return Err(Error::InvalidAddressRange); 402 } 403 }), 404 } 405 } 406 } 407 408 impl<R: Reader> RawRngListIter<R> { 409 /// Construct a `RawRngListIter`. new(input: R, encoding: Encoding, format: RangeListsFormat) -> RawRngListIter<R>410 fn new(input: R, encoding: Encoding, format: RangeListsFormat) -> RawRngListIter<R> { 411 RawRngListIter { 412 input, 413 encoding, 414 format, 415 } 416 } 417 418 /// Advance the iterator to the next range. next(&mut self) -> Result<Option<RawRngListEntry<R::Offset>>>419 pub fn next(&mut self) -> Result<Option<RawRngListEntry<R::Offset>>> { 420 if self.input.is_empty() { 421 return Ok(None); 422 } 423 424 match RawRngListEntry::parse(&mut self.input, self.encoding, self.format) { 425 Ok(range) => { 426 if range.is_none() { 427 self.input.empty(); 428 } 429 Ok(range) 430 } 431 Err(e) => { 432 self.input.empty(); 433 Err(e) 434 } 435 } 436 } 437 } 438 439 #[cfg(feature = "fallible-iterator")] 440 impl<R: Reader> fallible_iterator::FallibleIterator for RawRngListIter<R> { 441 type Item = RawRngListEntry<R::Offset>; 442 type Error = Error; 443 next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error>444 fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> { 445 RawRngListIter::next(self) 446 } 447 } 448 449 /// An iterator over an address range list. 450 /// 451 /// This iterator internally handles processing of base addresses and different 452 /// entry types. Thus, it only returns range entries that are valid 453 /// and already adjusted for the base address. 454 #[derive(Debug)] 455 pub struct RngListIter<R: Reader> { 456 raw: RawRngListIter<R>, 457 base_address: u64, 458 debug_addr: DebugAddr<R>, 459 debug_addr_base: DebugAddrBase<R::Offset>, 460 } 461 462 impl<R: Reader> RngListIter<R> { 463 /// Construct a `RngListIter`. new( raw: RawRngListIter<R>, base_address: u64, debug_addr: DebugAddr<R>, debug_addr_base: DebugAddrBase<R::Offset>, ) -> RngListIter<R>464 fn new( 465 raw: RawRngListIter<R>, 466 base_address: u64, 467 debug_addr: DebugAddr<R>, 468 debug_addr_base: DebugAddrBase<R::Offset>, 469 ) -> RngListIter<R> { 470 RngListIter { 471 raw, 472 base_address, 473 debug_addr, 474 debug_addr_base, 475 } 476 } 477 478 #[inline] get_address(&self, index: DebugAddrIndex<R::Offset>) -> Result<u64>479 fn get_address(&self, index: DebugAddrIndex<R::Offset>) -> Result<u64> { 480 self.debug_addr 481 .get_address(self.raw.encoding.address_size, self.debug_addr_base, index) 482 } 483 484 /// Advance the iterator to the next range. next(&mut self) -> Result<Option<Range>>485 pub fn next(&mut self) -> Result<Option<Range>> { 486 loop { 487 let raw_range = match self.raw.next()? { 488 Some(range) => range, 489 None => return Ok(None), 490 }; 491 492 let range = match raw_range { 493 RawRngListEntry::BaseAddress { addr } => { 494 self.base_address = addr; 495 continue; 496 } 497 RawRngListEntry::BaseAddressx { addr } => { 498 self.base_address = self.get_address(addr)?; 499 continue; 500 } 501 RawRngListEntry::StartxEndx { begin, end } => { 502 let begin = self.get_address(begin)?; 503 let end = self.get_address(end)?; 504 Range { begin, end } 505 } 506 RawRngListEntry::StartxLength { begin, length } => { 507 let begin = self.get_address(begin)?; 508 let end = begin + length; 509 Range { begin, end } 510 } 511 RawRngListEntry::AddressOrOffsetPair { begin, end } 512 | RawRngListEntry::OffsetPair { begin, end } => { 513 let mut range = Range { begin, end }; 514 range.add_base_address(self.base_address, self.raw.encoding.address_size); 515 range 516 } 517 RawRngListEntry::StartEnd { begin, end } => Range { begin, end }, 518 RawRngListEntry::StartLength { begin, length } => Range { 519 begin, 520 end: begin + length, 521 }, 522 }; 523 524 if range.begin > range.end { 525 self.raw.input.empty(); 526 return Err(Error::InvalidAddressRange); 527 } 528 529 return Ok(Some(range)); 530 } 531 } 532 } 533 534 #[cfg(feature = "fallible-iterator")] 535 impl<R: Reader> fallible_iterator::FallibleIterator for RngListIter<R> { 536 type Item = Range; 537 type Error = Error; 538 next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error>539 fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> { 540 RngListIter::next(self) 541 } 542 } 543 544 /// A raw address range from the `.debug_ranges` section. 545 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 546 pub(crate) struct RawRange { 547 /// The beginning address of the range. 548 pub begin: u64, 549 550 /// The first address past the end of the range. 551 pub end: u64, 552 } 553 554 impl RawRange { 555 /// Check if this is a range end entry. 556 /// 557 /// This will only occur for raw ranges. 558 #[inline] is_end(&self) -> bool559 pub fn is_end(&self) -> bool { 560 self.begin == 0 && self.end == 0 561 } 562 563 /// Check if this is a base address selection entry. 564 /// 565 /// A base address selection entry changes the base address that subsequent 566 /// range entries are relative to. This will only occur for raw ranges. 567 #[inline] is_base_address(&self, address_size: u8) -> bool568 pub fn is_base_address(&self, address_size: u8) -> bool { 569 self.begin == !0 >> (64 - address_size * 8) 570 } 571 572 /// Parse an address range entry from `.debug_ranges` or `.debug_loc`. 573 #[doc(hidden)] 574 #[inline] parse<R: Reader>(input: &mut R, address_size: u8) -> Result<RawRange>575 pub fn parse<R: Reader>(input: &mut R, address_size: u8) -> Result<RawRange> { 576 let begin = input.read_address(address_size)?; 577 let end = input.read_address(address_size)?; 578 let range = RawRange { begin, end }; 579 Ok(range) 580 } 581 } 582 583 /// An address range from the `.debug_ranges`, `.debug_rnglists`, or `.debug_aranges` sections. 584 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 585 pub struct Range { 586 /// The beginning address of the range. 587 pub begin: u64, 588 589 /// The first address past the end of the range. 590 pub end: u64, 591 } 592 593 impl Range { 594 /// Add a base address to this range. 595 #[inline] add_base_address(&mut self, base_address: u64, address_size: u8)596 pub(crate) fn add_base_address(&mut self, base_address: u64, address_size: u8) { 597 let mask = !0 >> (64 - address_size * 8); 598 self.begin = base_address.wrapping_add(self.begin) & mask; 599 self.end = base_address.wrapping_add(self.end) & mask; 600 } 601 } 602 603 #[cfg(test)] 604 mod tests { 605 use super::*; 606 use crate::common::Format; 607 use crate::endianity::LittleEndian; 608 use crate::test_util::GimliSectionMethods; 609 use test_assembler::{Endian, Label, LabelMaker, Section}; 610 611 #[test] test_rnglists_32()612 fn test_rnglists_32() { 613 let encoding = Encoding { 614 format: Format::Dwarf32, 615 version: 5, 616 address_size: 4, 617 }; 618 let section = Section::with_endian(Endian::Little) 619 .L32(0x0300_0000) 620 .L32(0x0301_0300) 621 .L32(0x0301_0400) 622 .L32(0x0301_0500); 623 let buf = section.get_contents().unwrap(); 624 let debug_addr = &DebugAddr::from(EndianSlice::new(&buf, LittleEndian)); 625 let debug_addr_base = DebugAddrBase(0); 626 627 let start = Label::new(); 628 let first = Label::new(); 629 let size = Label::new(); 630 #[rustfmt::skip] 631 let section = Section::with_endian(Endian::Little) 632 // Header 633 .mark(&start) 634 .L32(&size) 635 .L16(encoding.version) 636 .L8(encoding.address_size) 637 .L8(0) 638 .L32(0) 639 .mark(&first) 640 // OffsetPair 641 .L8(4).uleb(0x10200).uleb(0x10300) 642 // A base address selection followed by an OffsetPair. 643 .L8(5).L32(0x0200_0000) 644 .L8(4).uleb(0x10400).uleb(0x10500) 645 // An empty OffsetPair followed by a normal OffsetPair. 646 .L8(4).uleb(0x10600).uleb(0x10600) 647 .L8(4).uleb(0x10800).uleb(0x10900) 648 // A StartEnd 649 .L8(6).L32(0x201_0a00).L32(0x201_0b00) 650 // A StartLength 651 .L8(7).L32(0x201_0c00).uleb(0x100) 652 // An OffsetPair that starts at 0. 653 .L8(4).uleb(0).uleb(1) 654 // An OffsetPair that starts and ends at 0. 655 .L8(4).uleb(0).uleb(0) 656 // An OffsetPair that ends at -1. 657 .L8(5).L32(0) 658 .L8(4).uleb(0).uleb(0xffff_ffff) 659 // A BaseAddressx + OffsetPair 660 .L8(1).uleb(0) 661 .L8(4).uleb(0x10100).uleb(0x10200) 662 // A StartxEndx 663 .L8(2).uleb(1).uleb(2) 664 // A StartxLength 665 .L8(3).uleb(3).uleb(0x100) 666 // A range end. 667 .L8(0) 668 // Some extra data. 669 .L32(0xffff_ffff); 670 size.set_const((§ion.here() - &start - 4) as u64); 671 672 let buf = section.get_contents().unwrap(); 673 let debug_ranges = DebugRanges::new(&[], LittleEndian); 674 let debug_rnglists = DebugRngLists::new(&buf, LittleEndian); 675 let rnglists = RangeLists::new(debug_ranges, debug_rnglists); 676 let offset = RangeListsOffset((&first - &start) as usize); 677 let mut ranges = rnglists 678 .ranges(offset, encoding, 0x0100_0000, debug_addr, debug_addr_base) 679 .unwrap(); 680 681 // A normal range. 682 assert_eq!( 683 ranges.next(), 684 Ok(Some(Range { 685 begin: 0x0101_0200, 686 end: 0x0101_0300, 687 })) 688 ); 689 690 // A base address selection followed by a normal range. 691 assert_eq!( 692 ranges.next(), 693 Ok(Some(Range { 694 begin: 0x0201_0400, 695 end: 0x0201_0500, 696 })) 697 ); 698 699 // An empty range followed by a normal range. 700 assert_eq!( 701 ranges.next(), 702 Ok(Some(Range { 703 begin: 0x0201_0600, 704 end: 0x0201_0600, 705 })) 706 ); 707 assert_eq!( 708 ranges.next(), 709 Ok(Some(Range { 710 begin: 0x0201_0800, 711 end: 0x0201_0900, 712 })) 713 ); 714 715 // A normal range. 716 assert_eq!( 717 ranges.next(), 718 Ok(Some(Range { 719 begin: 0x0201_0a00, 720 end: 0x0201_0b00, 721 })) 722 ); 723 724 // A normal range. 725 assert_eq!( 726 ranges.next(), 727 Ok(Some(Range { 728 begin: 0x0201_0c00, 729 end: 0x0201_0d00, 730 })) 731 ); 732 733 // A range that starts at 0. 734 assert_eq!( 735 ranges.next(), 736 Ok(Some(Range { 737 begin: 0x0200_0000, 738 end: 0x0200_0001, 739 })) 740 ); 741 742 // A range that starts and ends at 0. 743 assert_eq!( 744 ranges.next(), 745 Ok(Some(Range { 746 begin: 0x0200_0000, 747 end: 0x0200_0000, 748 })) 749 ); 750 751 // A range that ends at -1. 752 assert_eq!( 753 ranges.next(), 754 Ok(Some(Range { 755 begin: 0x0000_0000, 756 end: 0xffff_ffff, 757 })) 758 ); 759 760 // A BaseAddressx + OffsetPair 761 assert_eq!( 762 ranges.next(), 763 Ok(Some(Range { 764 begin: 0x0301_0100, 765 end: 0x0301_0200, 766 })) 767 ); 768 769 // A StartxEndx 770 assert_eq!( 771 ranges.next(), 772 Ok(Some(Range { 773 begin: 0x0301_0300, 774 end: 0x0301_0400, 775 })) 776 ); 777 778 // A StartxLength 779 assert_eq!( 780 ranges.next(), 781 Ok(Some(Range { 782 begin: 0x0301_0500, 783 end: 0x0301_0600, 784 })) 785 ); 786 787 // A range end. 788 assert_eq!(ranges.next(), Ok(None)); 789 790 // An offset at the end of buf. 791 let mut ranges = rnglists 792 .ranges( 793 RangeListsOffset(buf.len()), 794 encoding, 795 0x0100_0000, 796 debug_addr, 797 debug_addr_base, 798 ) 799 .unwrap(); 800 assert_eq!(ranges.next(), Ok(None)); 801 } 802 803 #[test] test_rnglists_64()804 fn test_rnglists_64() { 805 let encoding = Encoding { 806 format: Format::Dwarf64, 807 version: 5, 808 address_size: 8, 809 }; 810 let section = Section::with_endian(Endian::Little) 811 .L64(0x0300_0000) 812 .L64(0x0301_0300) 813 .L64(0x0301_0400) 814 .L64(0x0301_0500); 815 let buf = section.get_contents().unwrap(); 816 let debug_addr = &DebugAddr::from(EndianSlice::new(&buf, LittleEndian)); 817 let debug_addr_base = DebugAddrBase(0); 818 819 let start = Label::new(); 820 let first = Label::new(); 821 let size = Label::new(); 822 #[rustfmt::skip] 823 let section = Section::with_endian(Endian::Little) 824 // Header 825 .mark(&start) 826 .L32(0xffff_ffff) 827 .L64(&size) 828 .L16(encoding.version) 829 .L8(encoding.address_size) 830 .L8(0) 831 .L32(0) 832 .mark(&first) 833 // OffsetPair 834 .L8(4).uleb(0x10200).uleb(0x10300) 835 // A base address selection followed by an OffsetPair. 836 .L8(5).L64(0x0200_0000) 837 .L8(4).uleb(0x10400).uleb(0x10500) 838 // An empty OffsetPair followed by a normal OffsetPair. 839 .L8(4).uleb(0x10600).uleb(0x10600) 840 .L8(4).uleb(0x10800).uleb(0x10900) 841 // A StartEnd 842 .L8(6).L64(0x201_0a00).L64(0x201_0b00) 843 // A StartLength 844 .L8(7).L64(0x201_0c00).uleb(0x100) 845 // An OffsetPair that starts at 0. 846 .L8(4).uleb(0).uleb(1) 847 // An OffsetPair that starts and ends at 0. 848 .L8(4).uleb(0).uleb(0) 849 // An OffsetPair that ends at -1. 850 .L8(5).L64(0) 851 .L8(4).uleb(0).uleb(0xffff_ffff) 852 // A BaseAddressx + OffsetPair 853 .L8(1).uleb(0) 854 .L8(4).uleb(0x10100).uleb(0x10200) 855 // A StartxEndx 856 .L8(2).uleb(1).uleb(2) 857 // A StartxLength 858 .L8(3).uleb(3).uleb(0x100) 859 // A range end. 860 .L8(0) 861 // Some extra data. 862 .L32(0xffff_ffff); 863 size.set_const((§ion.here() - &start - 12) as u64); 864 865 let buf = section.get_contents().unwrap(); 866 let debug_ranges = DebugRanges::new(&[], LittleEndian); 867 let debug_rnglists = DebugRngLists::new(&buf, LittleEndian); 868 let rnglists = RangeLists::new(debug_ranges, debug_rnglists); 869 let offset = RangeListsOffset((&first - &start) as usize); 870 let mut ranges = rnglists 871 .ranges(offset, encoding, 0x0100_0000, debug_addr, debug_addr_base) 872 .unwrap(); 873 874 // A normal range. 875 assert_eq!( 876 ranges.next(), 877 Ok(Some(Range { 878 begin: 0x0101_0200, 879 end: 0x0101_0300, 880 })) 881 ); 882 883 // A base address selection followed by a normal range. 884 assert_eq!( 885 ranges.next(), 886 Ok(Some(Range { 887 begin: 0x0201_0400, 888 end: 0x0201_0500, 889 })) 890 ); 891 892 // An empty range followed by a normal range. 893 assert_eq!( 894 ranges.next(), 895 Ok(Some(Range { 896 begin: 0x0201_0600, 897 end: 0x0201_0600, 898 })) 899 ); 900 assert_eq!( 901 ranges.next(), 902 Ok(Some(Range { 903 begin: 0x0201_0800, 904 end: 0x0201_0900, 905 })) 906 ); 907 908 // A normal range. 909 assert_eq!( 910 ranges.next(), 911 Ok(Some(Range { 912 begin: 0x0201_0a00, 913 end: 0x0201_0b00, 914 })) 915 ); 916 917 // A normal range. 918 assert_eq!( 919 ranges.next(), 920 Ok(Some(Range { 921 begin: 0x0201_0c00, 922 end: 0x0201_0d00, 923 })) 924 ); 925 926 // A range that starts at 0. 927 assert_eq!( 928 ranges.next(), 929 Ok(Some(Range { 930 begin: 0x0200_0000, 931 end: 0x0200_0001, 932 })) 933 ); 934 935 // A range that starts and ends at 0. 936 assert_eq!( 937 ranges.next(), 938 Ok(Some(Range { 939 begin: 0x0200_0000, 940 end: 0x0200_0000, 941 })) 942 ); 943 944 // A range that ends at -1. 945 assert_eq!( 946 ranges.next(), 947 Ok(Some(Range { 948 begin: 0x0000_0000, 949 end: 0xffff_ffff, 950 })) 951 ); 952 953 // A BaseAddressx + OffsetPair 954 assert_eq!( 955 ranges.next(), 956 Ok(Some(Range { 957 begin: 0x0301_0100, 958 end: 0x0301_0200, 959 })) 960 ); 961 962 // A StartxEndx 963 assert_eq!( 964 ranges.next(), 965 Ok(Some(Range { 966 begin: 0x0301_0300, 967 end: 0x0301_0400, 968 })) 969 ); 970 971 // A StartxLength 972 assert_eq!( 973 ranges.next(), 974 Ok(Some(Range { 975 begin: 0x0301_0500, 976 end: 0x0301_0600, 977 })) 978 ); 979 980 // A range end. 981 assert_eq!(ranges.next(), Ok(None)); 982 983 // An offset at the end of buf. 984 let mut ranges = rnglists 985 .ranges( 986 RangeListsOffset(buf.len()), 987 encoding, 988 0x0100_0000, 989 debug_addr, 990 debug_addr_base, 991 ) 992 .unwrap(); 993 assert_eq!(ranges.next(), Ok(None)); 994 } 995 996 #[test] test_raw_range()997 fn test_raw_range() { 998 let range = RawRange { 999 begin: 0, 1000 end: 0xffff_ffff, 1001 }; 1002 assert!(!range.is_end()); 1003 assert!(!range.is_base_address(4)); 1004 assert!(!range.is_base_address(8)); 1005 1006 let range = RawRange { begin: 0, end: 0 }; 1007 assert!(range.is_end()); 1008 assert!(!range.is_base_address(4)); 1009 assert!(!range.is_base_address(8)); 1010 1011 let range = RawRange { 1012 begin: 0xffff_ffff, 1013 end: 0, 1014 }; 1015 assert!(!range.is_end()); 1016 assert!(range.is_base_address(4)); 1017 assert!(!range.is_base_address(8)); 1018 1019 let range = RawRange { 1020 begin: 0xffff_ffff_ffff_ffff, 1021 end: 0, 1022 }; 1023 assert!(!range.is_end()); 1024 assert!(!range.is_base_address(4)); 1025 assert!(range.is_base_address(8)); 1026 } 1027 1028 #[test] test_ranges_32()1029 fn test_ranges_32() { 1030 let start = Label::new(); 1031 let first = Label::new(); 1032 #[rustfmt::skip] 1033 let section = Section::with_endian(Endian::Little) 1034 // A range before the offset. 1035 .mark(&start) 1036 .L32(0x10000).L32(0x10100) 1037 .mark(&first) 1038 // A normal range. 1039 .L32(0x10200).L32(0x10300) 1040 // A base address selection followed by a normal range. 1041 .L32(0xffff_ffff).L32(0x0200_0000) 1042 .L32(0x10400).L32(0x10500) 1043 // An empty range followed by a normal range. 1044 .L32(0x10600).L32(0x10600) 1045 .L32(0x10800).L32(0x10900) 1046 // A range that starts at 0. 1047 .L32(0).L32(1) 1048 // A range that ends at -1. 1049 .L32(0xffff_ffff).L32(0x0000_0000) 1050 .L32(0).L32(0xffff_ffff) 1051 // A range end. 1052 .L32(0).L32(0) 1053 // Some extra data. 1054 .L32(0); 1055 1056 let buf = section.get_contents().unwrap(); 1057 let debug_ranges = DebugRanges::new(&buf, LittleEndian); 1058 let debug_rnglists = DebugRngLists::new(&[], LittleEndian); 1059 let rnglists = RangeLists::new(debug_ranges, debug_rnglists); 1060 let offset = RangeListsOffset((&first - &start) as usize); 1061 let debug_addr = &DebugAddr::from(EndianSlice::new(&[], LittleEndian)); 1062 let debug_addr_base = DebugAddrBase(0); 1063 let encoding = Encoding { 1064 format: Format::Dwarf32, 1065 version: 4, 1066 address_size: 4, 1067 }; 1068 let mut ranges = rnglists 1069 .ranges(offset, encoding, 0x0100_0000, debug_addr, debug_addr_base) 1070 .unwrap(); 1071 1072 // A normal range. 1073 assert_eq!( 1074 ranges.next(), 1075 Ok(Some(Range { 1076 begin: 0x0101_0200, 1077 end: 0x0101_0300, 1078 })) 1079 ); 1080 1081 // A base address selection followed by a normal range. 1082 assert_eq!( 1083 ranges.next(), 1084 Ok(Some(Range { 1085 begin: 0x0201_0400, 1086 end: 0x0201_0500, 1087 })) 1088 ); 1089 1090 // An empty range followed by a normal range. 1091 assert_eq!( 1092 ranges.next(), 1093 Ok(Some(Range { 1094 begin: 0x0201_0600, 1095 end: 0x0201_0600, 1096 })) 1097 ); 1098 assert_eq!( 1099 ranges.next(), 1100 Ok(Some(Range { 1101 begin: 0x0201_0800, 1102 end: 0x0201_0900, 1103 })) 1104 ); 1105 1106 // A range that starts at 0. 1107 assert_eq!( 1108 ranges.next(), 1109 Ok(Some(Range { 1110 begin: 0x0200_0000, 1111 end: 0x0200_0001, 1112 })) 1113 ); 1114 1115 // A range that ends at -1. 1116 assert_eq!( 1117 ranges.next(), 1118 Ok(Some(Range { 1119 begin: 0x0000_0000, 1120 end: 0xffff_ffff, 1121 })) 1122 ); 1123 1124 // A range end. 1125 assert_eq!(ranges.next(), Ok(None)); 1126 1127 // An offset at the end of buf. 1128 let mut ranges = rnglists 1129 .ranges( 1130 RangeListsOffset(buf.len()), 1131 encoding, 1132 0x0100_0000, 1133 debug_addr, 1134 debug_addr_base, 1135 ) 1136 .unwrap(); 1137 assert_eq!(ranges.next(), Ok(None)); 1138 } 1139 1140 #[test] test_ranges_64()1141 fn test_ranges_64() { 1142 let start = Label::new(); 1143 let first = Label::new(); 1144 #[rustfmt::skip] 1145 let section = Section::with_endian(Endian::Little) 1146 // A range before the offset. 1147 .mark(&start) 1148 .L64(0x10000).L64(0x10100) 1149 .mark(&first) 1150 // A normal range. 1151 .L64(0x10200).L64(0x10300) 1152 // A base address selection followed by a normal range. 1153 .L64(0xffff_ffff_ffff_ffff).L64(0x0200_0000) 1154 .L64(0x10400).L64(0x10500) 1155 // An empty range followed by a normal range. 1156 .L64(0x10600).L64(0x10600) 1157 .L64(0x10800).L64(0x10900) 1158 // A range that starts at 0. 1159 .L64(0).L64(1) 1160 // A range that ends at -1. 1161 .L64(0xffff_ffff_ffff_ffff).L64(0x0000_0000) 1162 .L64(0).L64(0xffff_ffff_ffff_ffff) 1163 // A range end. 1164 .L64(0).L64(0) 1165 // Some extra data. 1166 .L64(0); 1167 1168 let buf = section.get_contents().unwrap(); 1169 let debug_ranges = DebugRanges::new(&buf, LittleEndian); 1170 let debug_rnglists = DebugRngLists::new(&[], LittleEndian); 1171 let rnglists = RangeLists::new(debug_ranges, debug_rnglists); 1172 let offset = RangeListsOffset((&first - &start) as usize); 1173 let debug_addr = &DebugAddr::from(EndianSlice::new(&[], LittleEndian)); 1174 let debug_addr_base = DebugAddrBase(0); 1175 let encoding = Encoding { 1176 format: Format::Dwarf64, 1177 version: 4, 1178 address_size: 8, 1179 }; 1180 let mut ranges = rnglists 1181 .ranges(offset, encoding, 0x0100_0000, debug_addr, debug_addr_base) 1182 .unwrap(); 1183 1184 // A normal range. 1185 assert_eq!( 1186 ranges.next(), 1187 Ok(Some(Range { 1188 begin: 0x0101_0200, 1189 end: 0x0101_0300, 1190 })) 1191 ); 1192 1193 // A base address selection followed by a normal range. 1194 assert_eq!( 1195 ranges.next(), 1196 Ok(Some(Range { 1197 begin: 0x0201_0400, 1198 end: 0x0201_0500, 1199 })) 1200 ); 1201 1202 // An empty range followed by a normal range. 1203 assert_eq!( 1204 ranges.next(), 1205 Ok(Some(Range { 1206 begin: 0x0201_0600, 1207 end: 0x0201_0600, 1208 })) 1209 ); 1210 assert_eq!( 1211 ranges.next(), 1212 Ok(Some(Range { 1213 begin: 0x0201_0800, 1214 end: 0x0201_0900, 1215 })) 1216 ); 1217 1218 // A range that starts at 0. 1219 assert_eq!( 1220 ranges.next(), 1221 Ok(Some(Range { 1222 begin: 0x0200_0000, 1223 end: 0x0200_0001, 1224 })) 1225 ); 1226 1227 // A range that ends at -1. 1228 assert_eq!( 1229 ranges.next(), 1230 Ok(Some(Range { 1231 begin: 0x0, 1232 end: 0xffff_ffff_ffff_ffff, 1233 })) 1234 ); 1235 1236 // A range end. 1237 assert_eq!(ranges.next(), Ok(None)); 1238 1239 // An offset at the end of buf. 1240 let mut ranges = rnglists 1241 .ranges( 1242 RangeListsOffset(buf.len()), 1243 encoding, 1244 0x0100_0000, 1245 debug_addr, 1246 debug_addr_base, 1247 ) 1248 .unwrap(); 1249 assert_eq!(ranges.next(), Ok(None)); 1250 } 1251 1252 #[test] test_ranges_invalid()1253 fn test_ranges_invalid() { 1254 #[rustfmt::skip] 1255 let section = Section::with_endian(Endian::Little) 1256 // An invalid range. 1257 .L32(0x20000).L32(0x10000) 1258 // An invalid range after wrapping. 1259 .L32(0x20000).L32(0xff01_0000); 1260 1261 let buf = section.get_contents().unwrap(); 1262 let debug_ranges = DebugRanges::new(&buf, LittleEndian); 1263 let debug_rnglists = DebugRngLists::new(&[], LittleEndian); 1264 let rnglists = RangeLists::new(debug_ranges, debug_rnglists); 1265 let debug_addr = &DebugAddr::from(EndianSlice::new(&[], LittleEndian)); 1266 let debug_addr_base = DebugAddrBase(0); 1267 let encoding = Encoding { 1268 format: Format::Dwarf32, 1269 version: 4, 1270 address_size: 4, 1271 }; 1272 1273 // An invalid range. 1274 let mut ranges = rnglists 1275 .ranges( 1276 RangeListsOffset(0x0), 1277 encoding, 1278 0x0100_0000, 1279 debug_addr, 1280 debug_addr_base, 1281 ) 1282 .unwrap(); 1283 assert_eq!(ranges.next(), Err(Error::InvalidAddressRange)); 1284 1285 // An invalid range after wrapping. 1286 let mut ranges = rnglists 1287 .ranges( 1288 RangeListsOffset(0x8), 1289 encoding, 1290 0x0100_0000, 1291 debug_addr, 1292 debug_addr_base, 1293 ) 1294 .unwrap(); 1295 assert_eq!(ranges.next(), Err(Error::InvalidAddressRange)); 1296 1297 // An invalid offset. 1298 match rnglists.ranges( 1299 RangeListsOffset(buf.len() + 1), 1300 encoding, 1301 0x0100_0000, 1302 debug_addr, 1303 debug_addr_base, 1304 ) { 1305 Err(Error::UnexpectedEof(_)) => {} 1306 otherwise => panic!("Unexpected result: {:?}", otherwise), 1307 } 1308 } 1309 1310 #[test] test_get_offset()1311 fn test_get_offset() { 1312 for format in vec![Format::Dwarf32, Format::Dwarf64] { 1313 let encoding = Encoding { 1314 format, 1315 version: 5, 1316 address_size: 4, 1317 }; 1318 1319 let zero = Label::new(); 1320 let length = Label::new(); 1321 let start = Label::new(); 1322 let first = Label::new(); 1323 let end = Label::new(); 1324 let mut section = Section::with_endian(Endian::Little) 1325 .mark(&zero) 1326 .initial_length(format, &length, &start) 1327 .D16(encoding.version) 1328 .D8(encoding.address_size) 1329 .D8(0) 1330 .D32(20) 1331 .mark(&first); 1332 for i in 0..20 { 1333 section = section.word(format.word_size(), 1000 + i); 1334 } 1335 section = section.mark(&end); 1336 length.set_const((&end - &start) as u64); 1337 let section = section.get_contents().unwrap(); 1338 1339 let debug_ranges = DebugRanges::from(EndianSlice::new(&[], LittleEndian)); 1340 let debug_rnglists = DebugRngLists::from(EndianSlice::new(§ion, LittleEndian)); 1341 let ranges = RangeLists::new(debug_ranges, debug_rnglists); 1342 1343 let base = DebugRngListsBase((&first - &zero) as usize); 1344 assert_eq!( 1345 ranges.get_offset(encoding, base, DebugRngListsIndex(0)), 1346 Ok(RangeListsOffset(base.0 + 1000)) 1347 ); 1348 assert_eq!( 1349 ranges.get_offset(encoding, base, DebugRngListsIndex(19)), 1350 Ok(RangeListsOffset(base.0 + 1019)) 1351 ); 1352 } 1353 } 1354 } 1355