(
&self,
section_index: SectionIndex,
offset: u64,
)
| 472 | } |
| 473 | |
| 474 | pub fn inline_info<'tcx>( |
| 475 | &self, |
| 476 | section_index: SectionIndex, |
| 477 | offset: u64, |
| 478 | ) -> Result<Vec<Call>, Error> { |
| 479 | let mut iter = self.dwarf.units(); |
| 480 | let mut callstack = Vec::<Call>::new(); |
| 481 | |
| 482 | while let Some(header) = iter.next()? { |
| 483 | let unit = self.dwarf.unit(header)?; |
| 484 | |
| 485 | let mut stack = Vec::new(); |
| 486 | let mut entries = unit.entries(); |
| 487 | let mut prev_depth = 0; |
| 488 | while let Some(die) = entries.next_dfs()? { |
| 489 | for _ in die.depth()..=prev_depth { |
| 490 | stack.pop(); |
| 491 | } |
| 492 | prev_depth = die.depth; |
| 493 | |
| 494 | if matches!( |
| 495 | die.tag(), |
| 496 | gimli::DW_TAG_subprogram | gimli::DW_TAG_inlined_subroutine |
| 497 | ) { |
| 498 | stack.push(Some(self.linkage_name(&unit, die)?)); |
| 499 | } else { |
| 500 | stack.push(None); |
| 501 | } |
| 502 | |
| 503 | if die.tag() != gimli::DW_TAG_inlined_subroutine { |
| 504 | continue; |
| 505 | } |
| 506 | |
| 507 | let ranges = self.ranges(&unit, die)?; |
| 508 | if ranges.0 != section_index { |
| 509 | continue; |
| 510 | } |
| 511 | |
| 512 | if ranges |
| 513 | .1 |
| 514 | .iter() |
| 515 | .any(|range| range.contains(&(offset as i64))) |
| 516 | { |
| 517 | let callee = stack.last().unwrap().as_ref().unwrap(); |
| 518 | let caller = stack |
| 519 | .iter() |
| 520 | .rev() |
| 521 | .skip(1) |
| 522 | .find(|x| x.is_some()) |
| 523 | .and_then(|x| x.as_ref()) |
| 524 | .ok_or(Error::UnexpectedDwarf( |
| 525 | "DW_TAG_inlined_subroutine is not nested inside DW_TAG_subprogram", |
| 526 | ))?; |
| 527 | |
| 528 | // Call stack must form a chain. |
| 529 | if let Some(last_call) = callstack.last() { |
| 530 | if last_call.callee != *caller { |
| 531 | Err(Error::UnexpectedDwarf("Inlined call does not form a chain"))? |
no test coverage detected