(cx: &AnalysisCtxt<'tcx>, file: &File<'obj>)
| 34 | struct BuildErrorReferenced; |
| 35 | |
| 36 | pub fn build_error_detection<'tcx, 'obj>(cx: &AnalysisCtxt<'tcx>, file: &File<'obj>) { |
| 37 | let Some(build_error) = cx.get_klint_diagnostic_item(crate::symbol::build_error) else { |
| 38 | return; |
| 39 | }; |
| 40 | let build_error_symbol_name = cx.symbol_name(Instance::mono(cx.tcx, build_error)).name; |
| 41 | |
| 42 | let Some(build_error_symbol) = file.symbol_by_name(build_error_symbol_name) else { |
| 43 | // This object file contains no reference to `build_error`, all good! |
| 44 | return; |
| 45 | }; |
| 46 | |
| 47 | // This object file defines this symbol; in which case we're codegenning for `build_error` crate. |
| 48 | // Nothing to do. |
| 49 | if !build_error_symbol.is_undefined() { |
| 50 | return; |
| 51 | } |
| 52 | |
| 53 | let relo_target_needle = RelocationTarget::Symbol(build_error_symbol.index()); |
| 54 | |
| 55 | // Now this file contains reference to `build_error`, this is not expected. |
| 56 | // We need to figure out why it is being generated. |
| 57 | |
| 58 | for section in file.sections() { |
| 59 | for (offset, relocation) in section.relocations() { |
| 60 | if relocation.target() == relo_target_needle { |
| 61 | // Found a relocation that points to `build_error`. Emit an error. |
| 62 | let Some((symbol, _)) = |
| 63 | super::find_symbol_from_section_offset(file, §ion, offset) |
| 64 | else { |
| 65 | cx.dcx().emit_err(BuildErrorReferencedWithoutSymbol); |
| 66 | continue; |
| 67 | }; |
| 68 | |
| 69 | let Some(mono) = cx.symbol_name_to_mono(symbol) else { |
| 70 | cx.dcx() |
| 71 | .emit_err(BuildErrorReferencedWithoutInstance { symbol }); |
| 72 | continue; |
| 73 | }; |
| 74 | |
| 75 | let loader = super::dwarf::DwarfLoader::new(file) |
| 76 | .expect("DWARF loader creation should not fail"); |
| 77 | |
| 78 | let mut diag = cx.dcx().create_err(BuildErrorReferenced); |
| 79 | let mut frame = match mono { |
| 80 | MonoItem::Fn(instance) => instance, |
| 81 | MonoItem::Static(def_id) => Instance::mono(cx.tcx, def_id), |
| 82 | MonoItem::GlobalAsm(_) => bug!(), |
| 83 | }; |
| 84 | |
| 85 | let mut recovered_call_stack = Vec::new(); |
| 86 | let result: Result<_, super::dwarf::Error> = try { |
| 87 | let call_stack = loader.inline_info(section.index(), offset)?; |
| 88 | if let Some(first) = call_stack.first() { |
| 89 | if first.caller != symbol { |
| 90 | Err(super::dwarf::Error::UnexpectedDwarf( |
| 91 | "root of call stack is unexpected", |
| 92 | ))? |
| 93 | } |
no test coverage detected