Skip to content

Commit f4323d1

Browse files
committed
Recover inlined call stack from DWARF
1 parent 909b574 commit f4323d1

4 files changed

Lines changed: 444 additions & 37 deletions

File tree

‎src/binary_analysis/build_error.rs‎

Lines changed: 64 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,11 @@ pub fn build_error_detection<'tcx, 'obj>(tcx: TyCtxt<'tcx>, file: &File<'obj>) {
4040
// We need to figure out why it is being generated.
4141

4242
// Collect all mono items, which we will use to find out which symbol is problematic.
43-
let (mono_items, usage_map) = crate::monomorphize_collector::collect_crate_mono_items(
43+
let mono_items = crate::monomorphize_collector::collect_crate_mono_items(
4444
tcx,
4545
crate::monomorphize_collector::MonoItemCollectionStrategy::Lazy,
46-
);
46+
)
47+
.0;
4748

4849
for section in file.sections() {
4950
for (offset, relocation) in section.relocations() {
@@ -82,41 +83,73 @@ pub fn build_error_detection<'tcx, 'obj>(tcx: TyCtxt<'tcx>, file: &File<'obj>) {
8283
}
8384
});
8485

85-
let reconstruct_span: Result<_, super::dwarf::Error> = try {
86-
let loader = super::dwarf::DwarfLoader::new(file)?;
87-
let loc = loader.locate(section.index(), offset)?.ok_or(
88-
super::dwarf::Error::UnexpectedDwarf("cannot find line number info"),
89-
)?;
90-
super::reconstruct::recover_span_from_line_no(tcx, &loc).ok_or(
91-
super::dwarf::Error::Other("cannot find file in compiler session"),
92-
)?
86+
let loader = super::dwarf::DwarfLoader::new(file)
87+
.expect("DWARF loader creation should not fail");
88+
let mut frame = match mono {
89+
MonoItem::Fn(instance) => Some(*instance),
90+
_ => None,
9391
};
9492

95-
match reconstruct_span {
96-
Ok(mut span) => {
97-
let mut site_recovered = false;
98-
let used_items = usage_map.used_item(*mono);
99-
for used_item in used_items {
100-
if used_item.node.symbol_name(tcx).name == "rust_build_error" {
101-
if super::reconstruct::recover_span(span, used_item.span) {
102-
span = used_item.span;
103-
site_recovered = true;
104-
break;
105-
}
106-
}
93+
let result: Result<_, super::dwarf::Error> = try {
94+
let call_stack = loader.inline_info(section.index(), offset)?;
95+
if let Some(first) = call_stack.first() {
96+
if first.caller != symbol {
97+
Err(super::dwarf::Error::UnexpectedDwarf(
98+
"root of call stack is unexpected",
99+
))?
107100
}
108-
109-
if site_recovered {
110-
diag.span_note(span, "invocation happens here");
111-
} else {
112-
diag.span_note(span, "invocation happens here, in an inlined function");
101+
}
102+
for call in call_stack {
103+
if let Some(caller) = frame.take() {
104+
if let Some((callee, span)) = super::reconstruct::recover_fn_call_span(
105+
tcx,
106+
caller,
107+
&call.callee,
108+
call.location.as_ref(),
109+
) {
110+
frame = Some(callee);
111+
diag.span_note(span, format!("which calls `{callee}`"));
112+
}
113113
}
114114
}
115-
Err(err) => {
116-
diag.note(format!(
117-
"attempt to reconstruct source information from DWARF failed: {err}"
118-
));
115+
};
116+
if let Err(err) = result {
117+
diag.note(format!(
118+
"attempt to reconstruct inline information from DWARF failed: {err}"
119+
));
120+
}
121+
122+
let result: Result<_, super::dwarf::Error> = try {
123+
let loc = loader.locate(section.index(), offset)?.ok_or(
124+
super::dwarf::Error::UnexpectedDwarf("cannot find line number info"),
125+
)?;
126+
127+
if let Some(frame) = frame
128+
&& let Some((_, span)) = super::reconstruct::recover_fn_call_span(
129+
tcx,
130+
frame,
131+
"rust_build_error",
132+
Some(&loc),
133+
)
134+
{
135+
diag.span_note(
136+
span,
137+
"which contains a `build_error` call that is not optimized out",
138+
);
139+
} else {
140+
let span = super::reconstruct::recover_span_from_line_no(tcx, &loc).ok_or(
141+
super::dwarf::Error::Other("cannot find file in compiler session"),
142+
)?;
143+
diag.span_note(
144+
span,
145+
"which contains a `build_error` reference that is not optimized out",
146+
);
119147
}
148+
};
149+
if let Err(err) = result {
150+
diag.note(format!(
151+
"attempt to reconstruct line information from DWARF failed: {err}"
152+
));
120153
}
121154

122155
diag.emit();

0 commit comments

Comments
 (0)