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