Skip to content

Commit 254d2dc

Browse files
committed
Auto merge of rust-lang#134831 - jyn514:backtrace-debuginfo, r=<try>
[experimental] shorten backtraces using debuginfo cc rust-lang/compiler-team#818 r? `@ghost` `@rustbot` label S-experimental try-job: aarch64-apple
2 parents 5c0a6e6 + f1f0ee4 commit 254d2dc

35 files changed

+901
-51
lines changed

Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -3525,6 +3525,7 @@ dependencies = [
35253525
"bitflags",
35263526
"cc",
35273527
"either",
3528+
"gimli 0.31.1",
35283529
"itertools",
35293530
"libc",
35303531
"object 0.36.7",

compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use gimli::write::{
1515
};
1616
use gimli::{AArch64, Encoding, Format, LineEncoding, Register, RiscV, RunTimeEndian, X86_64};
1717
use indexmap::IndexSet;
18-
use rustc_codegen_ssa::debuginfo::type_names;
18+
use rustc_codegen_ssa::debuginfo::{DW_AT_short_backtrace, DW_short_backtrace_value, type_names};
1919
use rustc_hir::def::DefKind;
2020
use rustc_hir::def_id::DefIdMap;
2121
use rustc_session::Session;
@@ -239,6 +239,16 @@ impl DebugContext {
239239
entry.set(gimli::DW_AT_decl_file, AttributeValue::FileIndex(Some(file_id)));
240240
entry.set(gimli::DW_AT_decl_line, AttributeValue::Udata(line));
241241

242+
if let Some(skip) = tcx.codegen_fn_attrs(instance.def_id()).skip_short_backtrace {
243+
tracing::info!(
244+
"debuginfo {:?}: skip_short_backtrace={:?}",
245+
tcx.item_name(instance.def_id()),
246+
skip
247+
);
248+
let attr = AttributeValue::Data1(DW_short_backtrace_value(skip));
249+
entry.set(gimli::DwAt(DW_AT_short_backtrace), attr);
250+
}
251+
242252
if !fn_abi.ret.is_ignore() {
243253
let return_dw_ty = self.debug_type(tcx, type_dbg, fn_abi.ret.layout.ty);
244254
let entry = self.dwarf.unit.get_mut(entry_id);

compiler/rustc_codegen_cranelift/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ extern crate rustc_metadata;
2727
extern crate rustc_session;
2828
extern crate rustc_span;
2929
extern crate rustc_target;
30+
extern crate tracing;
3031

3132
// This prevents duplicating functions and statics that are already part of the host rustc process.
3233
#[allow(unused_extern_crates)]

compiler/rustc_codegen_llvm/src/debuginfo/mod.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ use crate::common::{AsCCharPtr, CodegenCx};
3434
use crate::llvm;
3535
use crate::llvm::debuginfo::{
3636
DIArray, DIBuilder, DIFile, DIFlags, DILexicalBlock, DILocation, DISPFlags, DIScope, DIType,
37-
DIVariable,
37+
DIVariable, ShortBacktraceKind,
3838
};
3939
use crate::value::Value;
4040

@@ -375,6 +375,16 @@ impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
375375
}
376376
}
377377

378+
// If appropriate, mark the function as skippable in backtraces.
379+
let skip = self.tcx.codegen_fn_attrs(instance.def_id()).skip_short_backtrace;
380+
if let Some(s) = skip {
381+
tracing::info!(
382+
"generate short backtrace {s:?} for {}",
383+
tcx.item_name(instance.def_id())
384+
);
385+
}
386+
let skip = ShortBacktraceKind::from_generic(skip);
387+
378388
// When we're adding a method to a type DIE, we only want a DW_AT_declaration there, because
379389
// LLVM LTO can't unify type definitions when a child DIE is a full subprogram definition.
380390
// When we use this `decl` below, the subprogram definition gets created at the CU level
@@ -392,6 +402,7 @@ impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
392402
function_type_metadata,
393403
flags,
394404
spflags & !DISPFlags::SPFlagDefinition,
405+
skip,
395406
template_parameters,
396407
)
397408
});
@@ -410,6 +421,7 @@ impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
410421
scope_line,
411422
flags,
412423
spflags,
424+
skip,
413425
maybe_definition_llfn,
414426
template_parameters,
415427
decl,

compiler/rustc_codegen_llvm/src/llvm/ffi.rs

+25
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use std::fmt::Debug;
55
use std::marker::PhantomData;
66
use std::ptr;
77

8+
use debuginfo::ShortBacktraceKind;
89
use libc::{c_char, c_int, c_uint, c_ulonglong, c_void, size_t};
910
use rustc_macros::TryFromU32;
1011
use rustc_target::spec::SymbolVisibility;
@@ -707,6 +708,7 @@ pub type InlineAsmDiagHandlerTy = unsafe extern "C" fn(&SMDiagnostic, *const c_v
707708

708709
pub mod debuginfo {
709710
use bitflags::bitflags;
711+
use rustc_middle::middle::codegen_fn_attrs::SkipShortBacktrace;
710712

711713
use super::{InvariantOpaque, Metadata};
712714

@@ -775,6 +777,27 @@ pub mod debuginfo {
775777
}
776778
}
777779

780+
/// LLVMRustDebugEmissionKind
781+
#[derive(Copy, Clone, Debug)]
782+
#[repr(C)]
783+
pub enum ShortBacktraceKind {
784+
SkipFrame,
785+
StartShortBacktrace,
786+
EndShortBacktrace,
787+
None,
788+
}
789+
790+
impl ShortBacktraceKind {
791+
pub fn from_generic(opt: Option<SkipShortBacktrace>) -> Self {
792+
match opt {
793+
None => ShortBacktraceKind::None,
794+
Some(SkipShortBacktrace::ThisFrameOnly) => ShortBacktraceKind::SkipFrame,
795+
Some(SkipShortBacktrace::Start) => ShortBacktraceKind::StartShortBacktrace,
796+
Some(SkipShortBacktrace::End) => ShortBacktraceKind::EndShortBacktrace,
797+
}
798+
}
799+
}
800+
778801
/// LLVMRustDebugEmissionKind
779802
#[derive(Copy, Clone)]
780803
#[repr(C)]
@@ -1891,6 +1914,7 @@ unsafe extern "C" {
18911914
ScopeLine: c_uint,
18921915
Flags: DIFlags,
18931916
SPFlags: DISPFlags,
1917+
ShortBacktrace: ShortBacktraceKind,
18941918
MaybeFn: Option<&'a Value>,
18951919
TParam: &'a DIArray,
18961920
Decl: Option<&'a DIDescriptor>,
@@ -1908,6 +1932,7 @@ unsafe extern "C" {
19081932
Ty: &'a DIType,
19091933
Flags: DIFlags,
19101934
SPFlags: DISPFlags,
1935+
ShortBacktrace: ShortBacktraceKind,
19111936
TParam: &'a DIArray,
19121937
) -> &'a DISubprogram;
19131938

compiler/rustc_codegen_ssa/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ bitflags = "2.4.1"
1212
# `cc` in `rustc_llvm` if you update the `cc` here.
1313
cc = "=1.2.6"
1414
either = "1.5.0"
15+
gimli = "0.31.1"
1516
itertools = "0.12"
1617
pathdiff = "0.2.0"
1718
regex = "1.4"

compiler/rustc_codegen_ssa/src/codegen_attrs.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
99
use rustc_hir::weak_lang_items::WEAK_LANG_ITEMS;
1010
use rustc_hir::{self as hir, HirId, LangItem, lang_items};
1111
use rustc_middle::middle::codegen_fn_attrs::{
12-
CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry,
12+
CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry, SkipShortBacktrace,
1313
};
1414
use rustc_middle::mir::mono::Linkage;
1515
use rustc_middle::query::Providers;
@@ -581,6 +581,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
581581
}
582582
});
583583

584+
codegen_fn_attrs.skip_short_backtrace = SkipShortBacktrace::lookup(tcx, did);
585+
584586
// #73631: closures inherit `#[target_feature]` annotations
585587
//
586588
// If this closure is marked `#[inline(always)]`, simply skip adding `#[target_feature]`.
@@ -643,6 +645,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
643645
// Additionally weak lang items have predetermined symbol names.
644646
if WEAK_LANG_ITEMS.iter().any(|&l| tcx.lang_items().get(l) == Some(did.to_def_id())) {
645647
codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
648+
codegen_fn_attrs.skip_short_backtrace = Some(SkipShortBacktrace::ThisFrameOnly);
646649
}
647650
if let Some((name, _)) = lang_items::extract(attrs)
648651
&& let Some(lang_item) = LangItem::from_name(name)

compiler/rustc_codegen_ssa/src/debuginfo/mod.rs

+19
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,25 @@ use rustc_middle::ty::{self, Ty, TyCtxt};
66
// FIXME(eddyb) find a place for this (or a way to replace it).
77
pub mod type_names;
88

9+
#[allow(non_upper_case_globals)]
10+
mod short_backtraces {
11+
use rustc_middle::middle::codegen_fn_attrs::SkipShortBacktrace;
12+
13+
// This is effectively public API. Don't change it.
14+
pub const DW_AT_short_backtrace: u16 = 0x3c00;
15+
pub const DW_FORM_short_backtrace: u16 = gimli::constants::DW_FORM_data1.0;
16+
17+
#[allow(non_snake_case)]
18+
pub fn DW_short_backtrace_value(fn_attr: SkipShortBacktrace) -> u8 {
19+
match fn_attr {
20+
SkipShortBacktrace::ThisFrameOnly => 0,
21+
SkipShortBacktrace::Start => 1,
22+
SkipShortBacktrace::End => 2,
23+
}
24+
}
25+
}
26+
pub use short_backtraces::*;
27+
928
/// Returns true if we want to generate a DW_TAG_enumeration_type description for
1029
/// this instead of a DW_TAG_struct_type with DW_TAG_variant_part.
1130
///

compiler/rustc_feature/src/builtin_attrs.rs

+12
Original file line numberDiff line numberDiff line change
@@ -684,6 +684,18 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
684684
rustc_allocator_zeroed, Normal, template!(Word), WarnFollowing,
685685
EncodeCrossCrate::No, IMPL_DETAIL
686686
),
687+
rustc_attr!(
688+
rustc_skip_short_backtrace, Normal, template!(Word), WarnFollowing,
689+
EncodeCrossCrate::No, IMPL_DETAIL,
690+
),
691+
rustc_attr!(
692+
rustc_start_short_backtrace, Normal, template!(Word), WarnFollowing,
693+
EncodeCrossCrate::No, IMPL_DETAIL,
694+
),
695+
rustc_attr!(
696+
rustc_end_short_backtrace, Normal, template!(Word), WarnFollowing,
697+
EncodeCrossCrate::No, IMPL_DETAIL,
698+
),
687699
gated!(
688700
default_lib_allocator, Normal, template!(Word), WarnFollowing,
689701
EncodeCrossCrate::No, allocator_internals, experimental!(default_lib_allocator),

compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp

+43-2
Original file line numberDiff line numberDiff line change
@@ -822,6 +822,33 @@ static DISubprogram::DISPFlags fromRust(LLVMRustDISPFlags SPFlags) {
822822
return Result;
823823
}
824824

825+
#ifdef LLVM_RUSTLLVM
826+
// These values **must** match debuginfo::ShortBacktrace! They also *happen*
827+
// to match LLVM, but that isn't required as we do giant sets of
828+
// matching below. The value shouldn't be directly passed to LLVM.
829+
enum class LLVMRustShortBacktrace {
830+
SkipFrame,
831+
StartShortBacktrace,
832+
EndShortBacktrace,
833+
None,
834+
};
835+
836+
static std::optional<ShortBacktraceAttr> shortBacktraceFromRust(LLVMRustShortBacktrace backtrace) {
837+
switch (backtrace) {
838+
case LLVMRustShortBacktrace::SkipFrame:
839+
return ShortBacktraceAttr::SkipFrame;
840+
case LLVMRustShortBacktrace::StartShortBacktrace:
841+
return ShortBacktraceAttr::StartShortBacktrace;
842+
case LLVMRustShortBacktrace::EndShortBacktrace:
843+
return ShortBacktraceAttr::EndShortBacktrace;
844+
case LLVMRustShortBacktrace::None:
845+
return std::nullopt;
846+
default:
847+
report_fatal_error("bad ShortBacktraceAttr.");
848+
}
849+
}
850+
#endif
851+
825852
enum class LLVMRustDebugEmissionKind {
826853
NoDebug,
827854
FullDebug,
@@ -1016,6 +1043,9 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction(
10161043
size_t NameLen, const char *LinkageName, size_t LinkageNameLen,
10171044
LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Ty,
10181045
unsigned ScopeLine, LLVMRustDIFlags Flags, LLVMRustDISPFlags SPFlags,
1046+
#ifdef LLVM_RUSTLLVM
1047+
LLVMRustShortBacktrace shortBacktrace,
1048+
#endif
10191049
LLVMValueRef MaybeFn, LLVMMetadataRef TParam, LLVMMetadataRef Decl) {
10201050
DITemplateParameterArray TParams =
10211051
DITemplateParameterArray(unwrap<MDTuple>(TParam));
@@ -1025,6 +1055,9 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction(
10251055
unwrapDI<DIScope>(Scope), StringRef(Name, NameLen),
10261056
StringRef(LinkageName, LinkageNameLen), unwrapDI<DIFile>(File), LineNo,
10271057
unwrapDI<DISubroutineType>(Ty), ScopeLine, llvmFlags, llvmSPFlags,
1058+
#ifdef LLVM_RUSTLLVM
1059+
shortBacktraceFromRust(shortBacktrace),
1060+
#endif
10281061
TParams, unwrapDIPtr<DISubprogram>(Decl));
10291062
if (MaybeFn)
10301063
unwrap<Function>(MaybeFn)->setSubprogram(Sub);
@@ -1035,7 +1068,11 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateMethod(
10351068
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
10361069
size_t NameLen, const char *LinkageName, size_t LinkageNameLen,
10371070
LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Ty,
1038-
LLVMRustDIFlags Flags, LLVMRustDISPFlags SPFlags, LLVMMetadataRef TParam) {
1071+
LLVMRustDIFlags Flags, LLVMRustDISPFlags SPFlags,
1072+
#ifdef LLVM_RUSTLLVM
1073+
LLVMRustShortBacktrace shortBacktrace,
1074+
#endif
1075+
LLVMMetadataRef TParam) {
10391076
DITemplateParameterArray TParams =
10401077
DITemplateParameterArray(unwrap<MDTuple>(TParam));
10411078
DISubprogram::DISPFlags llvmSPFlags = fromRust(SPFlags);
@@ -1045,7 +1082,11 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateMethod(
10451082
StringRef(LinkageName, LinkageNameLen), unwrapDI<DIFile>(File), LineNo,
10461083
unwrapDI<DISubroutineType>(Ty), 0, 0,
10471084
nullptr, // VTable params aren't used
1048-
llvmFlags, llvmSPFlags, TParams);
1085+
llvmFlags, llvmSPFlags,
1086+
#ifdef LLVM_RUSTLLVM
1087+
shortBacktraceFromRust(shortBacktrace),
1088+
#endif
1089+
TParams);
10491090
return wrap(Sub);
10501091
}
10511092

compiler/rustc_middle/messages.ftl

+3
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,9 @@ middle_limit_invalid =
8383
`limit` must be a non-negative integer
8484
.label = {$error_str}
8585
86+
middle_multiple_short_backtrace_attrs = multiple `#[rustc_*_short_backtrace]` attributes were used on the same item
87+
.note = "attribute used here"
88+
8689
middle_opaque_hidden_type_mismatch =
8790
concrete type differs from previous defining opaque type use
8891
.label = expected `{$self_ty}`, got `{$other_ty}`

0 commit comments

Comments
 (0)