1 use core::cmp::Ordering; 2 use core::marker::PhantomData; 3 4 use crate::common::{DebugInfoOffset, Encoding, SectionId}; 5 use crate::endianity::Endianity; 6 use crate::read::lookup::{DebugLookup, LookupEntryIter, LookupParser}; 7 use crate::read::{ 8 parse_debug_info_offset, EndianSlice, Error, Reader, ReaderOffset, Result, Section, 9 }; 10 11 #[derive(Debug, Clone, PartialEq, Eq)] 12 struct ArangeHeader<T = usize> { 13 encoding: Encoding, 14 length: T, 15 offset: DebugInfoOffset<T>, 16 segment_size: u8, 17 } 18 19 /// A single parsed arange. 20 #[derive(Debug, Clone, PartialEq, Eq)] 21 pub struct ArangeEntry<T: Copy = usize> { 22 segment: Option<u64>, 23 address: u64, 24 length: u64, 25 unit_header_offset: DebugInfoOffset<T>, 26 } 27 28 impl<T: Copy> ArangeEntry<T> { 29 /// Return the segment selector of this arange. 30 #[inline] segment(&self) -> Option<u64>31 pub fn segment(&self) -> Option<u64> { 32 self.segment 33 } 34 35 /// Return the beginning address of this arange. 36 #[inline] address(&self) -> u6437 pub fn address(&self) -> u64 { 38 self.address 39 } 40 41 /// Return the length of this arange. 42 #[inline] length(&self) -> u6443 pub fn length(&self) -> u64 { 44 self.length 45 } 46 47 /// Return the offset into the .debug_info section for this arange. 48 #[inline] debug_info_offset(&self) -> DebugInfoOffset<T>49 pub fn debug_info_offset(&self) -> DebugInfoOffset<T> { 50 self.unit_header_offset 51 } 52 } 53 54 impl<T: Copy + Ord> PartialOrd for ArangeEntry<T> { partial_cmp(&self, other: &ArangeEntry<T>) -> Option<Ordering>55 fn partial_cmp(&self, other: &ArangeEntry<T>) -> Option<Ordering> { 56 Some(self.cmp(other)) 57 } 58 } 59 60 impl<T: Copy + Ord> Ord for ArangeEntry<T> { cmp(&self, other: &ArangeEntry<T>) -> Ordering61 fn cmp(&self, other: &ArangeEntry<T>) -> Ordering { 62 // The expected comparison, but ignore header. 63 self.segment 64 .cmp(&other.segment) 65 .then(self.address.cmp(&other.address)) 66 .then(self.length.cmp(&other.length)) 67 } 68 } 69 70 #[derive(Clone, Debug)] 71 struct ArangeParser<R: Reader> { 72 // This struct is never instantiated. 73 phantom: PhantomData<R>, 74 } 75 76 impl<R: Reader> LookupParser<R> for ArangeParser<R> { 77 type Header = ArangeHeader<R::Offset>; 78 type Entry = ArangeEntry<R::Offset>; 79 80 /// Parse an arange set header. Returns a tuple of the aranges to be 81 /// parsed for this set, and the newly created ArangeHeader struct. parse_header(input: &mut R) -> Result<(R, Self::Header)>82 fn parse_header(input: &mut R) -> Result<(R, Self::Header)> { 83 let (length, format) = input.read_initial_length()?; 84 let mut rest = input.split(length)?; 85 86 let version = rest.read_u16()?; 87 if version != 2 { 88 return Err(Error::UnknownVersion(u64::from(version))); 89 } 90 91 let offset = parse_debug_info_offset(&mut rest, format)?; 92 let address_size = rest.read_u8()?; 93 let segment_size = rest.read_u8()?; 94 95 // unit_length + version + offset + address_size + segment_size 96 let header_length = format.initial_length_size() + 2 + format.word_size() + 1 + 1; 97 98 // The first tuple following the header in each set begins at an offset that is 99 // a multiple of the size of a single tuple (that is, the size of a segment selector 100 // plus twice the size of an address). 101 let tuple_length = address_size 102 .checked_mul(2) 103 .and_then(|x| x.checked_add(segment_size)) 104 .ok_or(Error::InvalidAddressRange)?; 105 if tuple_length == 0 { 106 return Err(Error::InvalidAddressRange)?; 107 } 108 let padding = if header_length % tuple_length == 0 { 109 0 110 } else { 111 tuple_length - header_length % tuple_length 112 }; 113 rest.skip(R::Offset::from_u8(padding))?; 114 115 let encoding = Encoding { 116 format, 117 version, 118 address_size, 119 // TODO: segment_size 120 }; 121 Ok(( 122 rest, 123 ArangeHeader { 124 encoding, 125 length, 126 offset, 127 segment_size, 128 }, 129 )) 130 } 131 132 /// Parse a single arange. Return `None` for the null arange, `Some` for an actual arange. parse_entry(input: &mut R, header: &Self::Header) -> Result<Option<Self::Entry>>133 fn parse_entry(input: &mut R, header: &Self::Header) -> Result<Option<Self::Entry>> { 134 let address_size = header.encoding.address_size; 135 let segment_size = header.segment_size; // May be zero! 136 137 let tuple_length = R::Offset::from_u8(2 * address_size + segment_size); 138 if tuple_length > input.len() { 139 input.empty(); 140 return Ok(None); 141 } 142 143 let segment = if segment_size != 0 { 144 input.read_address(segment_size)? 145 } else { 146 0 147 }; 148 let address = input.read_address(address_size)?; 149 let length = input.read_address(address_size)?; 150 151 match (segment, address, length) { 152 // There may be multiple sets of tuples, each terminated by a zero tuple. 153 // It's not clear what purpose these zero tuples serve. For now, we 154 // simply skip them. 155 (0, 0, 0) => Self::parse_entry(input, header), 156 _ => Ok(Some(ArangeEntry { 157 segment: if segment_size != 0 { 158 Some(segment) 159 } else { 160 None 161 }, 162 address, 163 length, 164 unit_header_offset: header.offset, 165 })), 166 } 167 } 168 } 169 170 /// The `DebugAranges` struct represents the DWARF address range information 171 /// found in the `.debug_aranges` section. 172 #[derive(Debug, Clone)] 173 pub struct DebugAranges<R: Reader>(DebugLookup<R, ArangeParser<R>>); 174 175 impl<'input, Endian> DebugAranges<EndianSlice<'input, Endian>> 176 where 177 Endian: Endianity, 178 { 179 /// Construct a new `DebugAranges` instance from the data in the `.debug_aranges` 180 /// section. 181 /// 182 /// It is the caller's responsibility to read the `.debug_aranges` section and 183 /// present it as a `&[u8]` slice. That means using some ELF loader on 184 /// Linux, a Mach-O loader on OSX, etc. 185 /// 186 /// ``` 187 /// use gimli::{DebugAranges, LittleEndian}; 188 /// 189 /// # let buf = []; 190 /// # let read_debug_aranges_section = || &buf; 191 /// let debug_aranges = 192 /// DebugAranges::new(read_debug_aranges_section(), LittleEndian); 193 /// ``` new(debug_aranges_section: &'input [u8], endian: Endian) -> Self194 pub fn new(debug_aranges_section: &'input [u8], endian: Endian) -> Self { 195 Self::from(EndianSlice::new(debug_aranges_section, endian)) 196 } 197 } 198 199 impl<R: Reader> DebugAranges<R> { 200 /// Iterate the aranges in the `.debug_aranges` section. 201 /// 202 /// ``` 203 /// use gimli::{DebugAranges, EndianSlice, LittleEndian}; 204 /// 205 /// # let buf = []; 206 /// # let read_debug_aranges_section = || &buf; 207 /// let debug_aranges = DebugAranges::new(read_debug_aranges_section(), LittleEndian); 208 /// 209 /// let mut iter = debug_aranges.items(); 210 /// while let Some(arange) = iter.next().unwrap() { 211 /// println!("arange starts at {}, has length {}", arange.address(), arange.length()); 212 /// } 213 /// ``` items(&self) -> ArangeEntryIter<R>214 pub fn items(&self) -> ArangeEntryIter<R> { 215 ArangeEntryIter(self.0.items()) 216 } 217 } 218 219 impl<R: Reader> Section<R> for DebugAranges<R> { id() -> SectionId220 fn id() -> SectionId { 221 SectionId::DebugAranges 222 } 223 reader(&self) -> &R224 fn reader(&self) -> &R { 225 self.0.reader() 226 } 227 } 228 229 impl<R: Reader> From<R> for DebugAranges<R> { from(debug_aranges_section: R) -> Self230 fn from(debug_aranges_section: R) -> Self { 231 DebugAranges(DebugLookup::from(debug_aranges_section)) 232 } 233 } 234 235 /// An iterator over the aranges from a `.debug_aranges` section. 236 /// 237 /// Can be [used with 238 /// `FallibleIterator`](./index.html#using-with-fallibleiterator). 239 #[derive(Debug, Clone)] 240 pub struct ArangeEntryIter<R: Reader>(LookupEntryIter<R, ArangeParser<R>>); 241 242 impl<R: Reader> ArangeEntryIter<R> { 243 /// Advance the iterator and return the next arange. 244 /// 245 /// Returns the newly parsed arange as `Ok(Some(arange))`. Returns `Ok(None)` 246 /// when iteration is complete and all aranges have already been parsed and 247 /// yielded. If an error occurs while parsing the next arange, then this error 248 /// is returned as `Err(e)`, and all subsequent calls return `Ok(None)`. next(&mut self) -> Result<Option<ArangeEntry<R::Offset>>>249 pub fn next(&mut self) -> Result<Option<ArangeEntry<R::Offset>>> { 250 self.0.next() 251 } 252 } 253 254 #[cfg(feature = "fallible-iterator")] 255 impl<R: Reader> fallible_iterator::FallibleIterator for ArangeEntryIter<R> { 256 type Item = ArangeEntry<R::Offset>; 257 type Error = Error; 258 next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error>259 fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> { 260 self.0.next() 261 } 262 } 263 264 #[cfg(test)] 265 mod tests { 266 use super::*; 267 use crate::common::{DebugInfoOffset, Format}; 268 use crate::endianity::LittleEndian; 269 use crate::read::lookup::LookupParser; 270 use crate::read::EndianSlice; 271 272 #[test] test_parse_header_ok()273 fn test_parse_header_ok() { 274 #[rustfmt::skip] 275 let buf = [ 276 // 32-bit length = 32. 277 0x20, 0x00, 0x00, 0x00, 278 // Version. 279 0x02, 0x00, 280 // Offset. 281 0x01, 0x02, 0x03, 0x04, 282 // Address size. 283 0x08, 284 // Segment size. 285 0x04, 286 // Length to here = 12, tuple length = 20. 287 // Padding to tuple length multiple = 4. 288 0x10, 0x00, 0x00, 0x00, 289 0x00, 0x00, 0x00, 0x00, 290 291 // Dummy arange tuple data. 292 0x20, 0x00, 0x00, 0x00, 293 0x00, 0x00, 0x00, 0x00, 294 0x00, 0x00, 0x00, 0x00, 295 0x00, 0x00, 0x00, 0x00, 296 297 // Dummy next arange. 298 0x30, 0x00, 0x00, 0x00, 299 0x00, 0x00, 0x00, 0x00, 300 0x00, 0x00, 0x00, 0x00, 301 0x00, 0x00, 0x00, 0x00, 302 ]; 303 304 let rest = &mut EndianSlice::new(&buf, LittleEndian); 305 306 let (tuples, header) = ArangeParser::parse_header(rest).expect("should parse header ok"); 307 308 assert_eq!( 309 *rest, 310 EndianSlice::new(&buf[buf.len() - 16..], LittleEndian) 311 ); 312 assert_eq!( 313 tuples, 314 EndianSlice::new(&buf[buf.len() - 32..buf.len() - 16], LittleEndian) 315 ); 316 assert_eq!( 317 header, 318 ArangeHeader { 319 encoding: Encoding { 320 format: Format::Dwarf32, 321 version: 2, 322 address_size: 8, 323 }, 324 length: 0x20, 325 offset: DebugInfoOffset(0x0403_0201), 326 segment_size: 4, 327 } 328 ); 329 } 330 331 #[test] test_parse_header_overflow_error()332 fn test_parse_header_overflow_error() { 333 #[rustfmt::skip] 334 let buf = [ 335 // 32-bit length = 32. 336 0x20, 0x00, 0x00, 0x00, 337 // Version. 338 0x02, 0x00, 339 // Offset. 340 0x01, 0x02, 0x03, 0x04, 341 // Address size. 342 0xff, 343 // Segment size. 344 0xff, 345 // Length to here = 12, tuple length = 20. 346 // Padding to tuple length multiple = 4. 347 0x10, 0x00, 0x00, 0x00, 348 0x00, 0x00, 0x00, 0x00, 349 350 // Dummy arange tuple data. 351 0x20, 0x00, 0x00, 0x00, 352 0x00, 0x00, 0x00, 0x00, 353 0x00, 0x00, 0x00, 0x00, 354 0x00, 0x00, 0x00, 0x00, 355 356 // Dummy next arange. 357 0x30, 0x00, 0x00, 0x00, 358 0x00, 0x00, 0x00, 0x00, 359 0x00, 0x00, 0x00, 0x00, 360 0x00, 0x00, 0x00, 0x00, 361 ]; 362 363 let rest = &mut EndianSlice::new(&buf, LittleEndian); 364 365 let error = ArangeParser::parse_header(rest).expect_err("should fail to parse header"); 366 assert_eq!(error, Error::InvalidAddressRange); 367 } 368 369 #[test] test_parse_header_div_by_zero_error()370 fn test_parse_header_div_by_zero_error() { 371 #[rustfmt::skip] 372 let buf = [ 373 // 32-bit length = 32. 374 0x20, 0x00, 0x00, 0x00, 375 // Version. 376 0x02, 0x00, 377 // Offset. 378 0x01, 0x02, 0x03, 0x04, 379 // Address size = 0. Could cause a division by zero if we aren't 380 // careful. 381 0x00, 382 // Segment size. 383 0x00, 384 // Length to here = 12, tuple length = 20. 385 // Padding to tuple length multiple = 4. 386 0x10, 0x00, 0x00, 0x00, 387 0x00, 0x00, 0x00, 0x00, 388 389 // Dummy arange tuple data. 390 0x20, 0x00, 0x00, 0x00, 391 0x00, 0x00, 0x00, 0x00, 392 0x00, 0x00, 0x00, 0x00, 393 0x00, 0x00, 0x00, 0x00, 394 395 // Dummy next arange. 396 0x30, 0x00, 0x00, 0x00, 397 0x00, 0x00, 0x00, 0x00, 398 0x00, 0x00, 0x00, 0x00, 399 0x00, 0x00, 0x00, 0x00, 400 ]; 401 402 let rest = &mut EndianSlice::new(&buf, LittleEndian); 403 404 let error = ArangeParser::parse_header(rest).expect_err("should fail to parse header"); 405 assert_eq!(error, Error::InvalidAddressRange); 406 } 407 408 #[test] test_parse_entry_ok()409 fn test_parse_entry_ok() { 410 let header = ArangeHeader { 411 encoding: Encoding { 412 format: Format::Dwarf32, 413 version: 2, 414 address_size: 4, 415 }, 416 length: 0, 417 offset: DebugInfoOffset(0), 418 segment_size: 0, 419 }; 420 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09]; 421 let rest = &mut EndianSlice::new(&buf, LittleEndian); 422 let entry = ArangeParser::parse_entry(rest, &header).expect("should parse entry ok"); 423 assert_eq!(*rest, EndianSlice::new(&buf[buf.len() - 1..], LittleEndian)); 424 assert_eq!( 425 entry, 426 Some(ArangeEntry { 427 segment: None, 428 address: 0x0403_0201, 429 length: 0x0807_0605, 430 unit_header_offset: header.offset, 431 }) 432 ); 433 } 434 435 #[test] test_parse_entry_segment()436 fn test_parse_entry_segment() { 437 let header = ArangeHeader { 438 encoding: Encoding { 439 format: Format::Dwarf32, 440 version: 2, 441 address_size: 4, 442 }, 443 length: 0, 444 offset: DebugInfoOffset(0), 445 segment_size: 8, 446 }; 447 #[rustfmt::skip] 448 let buf = [ 449 // Segment. 450 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 451 // Address. 452 0x01, 0x02, 0x03, 0x04, 453 // Length. 454 0x05, 0x06, 0x07, 0x08, 455 // Next tuple. 456 0x09 457 ]; 458 let rest = &mut EndianSlice::new(&buf, LittleEndian); 459 let entry = ArangeParser::parse_entry(rest, &header).expect("should parse entry ok"); 460 assert_eq!(*rest, EndianSlice::new(&buf[buf.len() - 1..], LittleEndian)); 461 assert_eq!( 462 entry, 463 Some(ArangeEntry { 464 segment: Some(0x1817_1615_1413_1211), 465 address: 0x0403_0201, 466 length: 0x0807_0605, 467 unit_header_offset: header.offset, 468 }) 469 ); 470 } 471 472 #[test] test_parse_entry_zero()473 fn test_parse_entry_zero() { 474 let header = ArangeHeader { 475 encoding: Encoding { 476 format: Format::Dwarf32, 477 version: 2, 478 address_size: 4, 479 }, 480 length: 0, 481 offset: DebugInfoOffset(0), 482 segment_size: 0, 483 }; 484 #[rustfmt::skip] 485 let buf = [ 486 // Zero tuple. 487 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 488 // Address. 489 0x01, 0x02, 0x03, 0x04, 490 // Length. 491 0x05, 0x06, 0x07, 0x08, 492 // Next tuple. 493 0x09 494 ]; 495 let rest = &mut EndianSlice::new(&buf, LittleEndian); 496 let entry = ArangeParser::parse_entry(rest, &header).expect("should parse entry ok"); 497 assert_eq!(*rest, EndianSlice::new(&buf[buf.len() - 1..], LittleEndian)); 498 assert_eq!( 499 entry, 500 Some(ArangeEntry { 501 segment: None, 502 address: 0x0403_0201, 503 length: 0x0807_0605, 504 unit_header_offset: header.offset, 505 }) 506 ); 507 } 508 } 509