Skip to content

Commit

Permalink
Auto merge of rust-lang#134831 - jyn514:backtrace-debuginfo, r=<try>
Browse files Browse the repository at this point in the history
[experimental] shorten backtraces using debuginfo

cc rust-lang/compiler-team#818

r? `@ghost`

`@rustbot` label S-experimental

try-job: aarch64-apple
  • Loading branch information
bors committed Dec 29, 2024
2 parents 5c0a6e6 + f1f0ee4 commit 254d2dc
Show file tree
Hide file tree
Showing 35 changed files with 901 additions and 51 deletions.
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3525,6 +3525,7 @@ dependencies = [
"bitflags",
"cc",
"either",
"gimli 0.31.1",
"itertools",
"libc",
"object 0.36.7",
Expand Down
12 changes: 11 additions & 1 deletion compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use gimli::write::{
};
use gimli::{AArch64, Encoding, Format, LineEncoding, Register, RiscV, RunTimeEndian, X86_64};
use indexmap::IndexSet;
use rustc_codegen_ssa::debuginfo::type_names;
use rustc_codegen_ssa::debuginfo::{DW_AT_short_backtrace, DW_short_backtrace_value, type_names};
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefIdMap;
use rustc_session::Session;
Expand Down Expand Up @@ -239,6 +239,16 @@ impl DebugContext {
entry.set(gimli::DW_AT_decl_file, AttributeValue::FileIndex(Some(file_id)));
entry.set(gimli::DW_AT_decl_line, AttributeValue::Udata(line));

if let Some(skip) = tcx.codegen_fn_attrs(instance.def_id()).skip_short_backtrace {
tracing::info!(
"debuginfo {:?}: skip_short_backtrace={:?}",
tcx.item_name(instance.def_id()),
skip
);
let attr = AttributeValue::Data1(DW_short_backtrace_value(skip));
entry.set(gimli::DwAt(DW_AT_short_backtrace), attr);
}

if !fn_abi.ret.is_ignore() {
let return_dw_ty = self.debug_type(tcx, type_dbg, fn_abi.ret.layout.ty);
let entry = self.dwarf.unit.get_mut(entry_id);
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_codegen_cranelift/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ extern crate rustc_metadata;
extern crate rustc_session;
extern crate rustc_span;
extern crate rustc_target;
extern crate tracing;

// This prevents duplicating functions and statics that are already part of the host rustc process.
#[allow(unused_extern_crates)]
Expand Down
14 changes: 13 additions & 1 deletion compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ use crate::common::{AsCCharPtr, CodegenCx};
use crate::llvm;
use crate::llvm::debuginfo::{
DIArray, DIBuilder, DIFile, DIFlags, DILexicalBlock, DILocation, DISPFlags, DIScope, DIType,
DIVariable,
DIVariable, ShortBacktraceKind,
};
use crate::value::Value;

Expand Down Expand Up @@ -375,6 +375,16 @@ impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
}
}

// If appropriate, mark the function as skippable in backtraces.
let skip = self.tcx.codegen_fn_attrs(instance.def_id()).skip_short_backtrace;
if let Some(s) = skip {
tracing::info!(
"generate short backtrace {s:?} for {}",
tcx.item_name(instance.def_id())
);
}
let skip = ShortBacktraceKind::from_generic(skip);

// When we're adding a method to a type DIE, we only want a DW_AT_declaration there, because
// LLVM LTO can't unify type definitions when a child DIE is a full subprogram definition.
// When we use this `decl` below, the subprogram definition gets created at the CU level
Expand All @@ -392,6 +402,7 @@ impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
function_type_metadata,
flags,
spflags & !DISPFlags::SPFlagDefinition,
skip,
template_parameters,
)
});
Expand All @@ -410,6 +421,7 @@ impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
scope_line,
flags,
spflags,
skip,
maybe_definition_llfn,
template_parameters,
decl,
Expand Down
25 changes: 25 additions & 0 deletions compiler/rustc_codegen_llvm/src/llvm/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use std::fmt::Debug;
use std::marker::PhantomData;
use std::ptr;

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

pub mod debuginfo {
use bitflags::bitflags;
use rustc_middle::middle::codegen_fn_attrs::SkipShortBacktrace;

use super::{InvariantOpaque, Metadata};

Expand Down Expand Up @@ -775,6 +777,27 @@ pub mod debuginfo {
}
}

/// LLVMRustDebugEmissionKind
#[derive(Copy, Clone, Debug)]
#[repr(C)]
pub enum ShortBacktraceKind {
SkipFrame,
StartShortBacktrace,
EndShortBacktrace,
None,
}

impl ShortBacktraceKind {
pub fn from_generic(opt: Option<SkipShortBacktrace>) -> Self {
match opt {
None => ShortBacktraceKind::None,
Some(SkipShortBacktrace::ThisFrameOnly) => ShortBacktraceKind::SkipFrame,
Some(SkipShortBacktrace::Start) => ShortBacktraceKind::StartShortBacktrace,
Some(SkipShortBacktrace::End) => ShortBacktraceKind::EndShortBacktrace,
}
}
}

/// LLVMRustDebugEmissionKind
#[derive(Copy, Clone)]
#[repr(C)]
Expand Down Expand Up @@ -1891,6 +1914,7 @@ unsafe extern "C" {
ScopeLine: c_uint,
Flags: DIFlags,
SPFlags: DISPFlags,
ShortBacktrace: ShortBacktraceKind,
MaybeFn: Option<&'a Value>,
TParam: &'a DIArray,
Decl: Option<&'a DIDescriptor>,
Expand All @@ -1908,6 +1932,7 @@ unsafe extern "C" {
Ty: &'a DIType,
Flags: DIFlags,
SPFlags: DISPFlags,
ShortBacktrace: ShortBacktraceKind,
TParam: &'a DIArray,
) -> &'a DISubprogram;

Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_codegen_ssa/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ bitflags = "2.4.1"
# `cc` in `rustc_llvm` if you update the `cc` here.
cc = "=1.2.6"
either = "1.5.0"
gimli = "0.31.1"
itertools = "0.12"
pathdiff = "0.2.0"
regex = "1.4"
Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_codegen_ssa/src/codegen_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
use rustc_hir::weak_lang_items::WEAK_LANG_ITEMS;
use rustc_hir::{self as hir, HirId, LangItem, lang_items};
use rustc_middle::middle::codegen_fn_attrs::{
CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry,
CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry, SkipShortBacktrace,
};
use rustc_middle::mir::mono::Linkage;
use rustc_middle::query::Providers;
Expand Down Expand Up @@ -581,6 +581,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
}
});

codegen_fn_attrs.skip_short_backtrace = SkipShortBacktrace::lookup(tcx, did);

// #73631: closures inherit `#[target_feature]` annotations
//
// If this closure is marked `#[inline(always)]`, simply skip adding `#[target_feature]`.
Expand Down Expand Up @@ -643,6 +645,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
// Additionally weak lang items have predetermined symbol names.
if WEAK_LANG_ITEMS.iter().any(|&l| tcx.lang_items().get(l) == Some(did.to_def_id())) {
codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
codegen_fn_attrs.skip_short_backtrace = Some(SkipShortBacktrace::ThisFrameOnly);
}
if let Some((name, _)) = lang_items::extract(attrs)
&& let Some(lang_item) = LangItem::from_name(name)
Expand Down
19 changes: 19 additions & 0 deletions compiler/rustc_codegen_ssa/src/debuginfo/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,25 @@ use rustc_middle::ty::{self, Ty, TyCtxt};
// FIXME(eddyb) find a place for this (or a way to replace it).
pub mod type_names;

#[allow(non_upper_case_globals)]
mod short_backtraces {
use rustc_middle::middle::codegen_fn_attrs::SkipShortBacktrace;

// This is effectively public API. Don't change it.
pub const DW_AT_short_backtrace: u16 = 0x3c00;
pub const DW_FORM_short_backtrace: u16 = gimli::constants::DW_FORM_data1.0;

#[allow(non_snake_case)]
pub fn DW_short_backtrace_value(fn_attr: SkipShortBacktrace) -> u8 {
match fn_attr {
SkipShortBacktrace::ThisFrameOnly => 0,
SkipShortBacktrace::Start => 1,
SkipShortBacktrace::End => 2,
}
}
}
pub use short_backtraces::*;

/// Returns true if we want to generate a DW_TAG_enumeration_type description for
/// this instead of a DW_TAG_struct_type with DW_TAG_variant_part.
///
Expand Down
12 changes: 12 additions & 0 deletions compiler/rustc_feature/src/builtin_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -684,6 +684,18 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
rustc_allocator_zeroed, Normal, template!(Word), WarnFollowing,
EncodeCrossCrate::No, IMPL_DETAIL
),
rustc_attr!(
rustc_skip_short_backtrace, Normal, template!(Word), WarnFollowing,
EncodeCrossCrate::No, IMPL_DETAIL,
),
rustc_attr!(
rustc_start_short_backtrace, Normal, template!(Word), WarnFollowing,
EncodeCrossCrate::No, IMPL_DETAIL,
),
rustc_attr!(
rustc_end_short_backtrace, Normal, template!(Word), WarnFollowing,
EncodeCrossCrate::No, IMPL_DETAIL,
),
gated!(
default_lib_allocator, Normal, template!(Word), WarnFollowing,
EncodeCrossCrate::No, allocator_internals, experimental!(default_lib_allocator),
Expand Down
45 changes: 43 additions & 2 deletions compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -822,6 +822,33 @@ static DISubprogram::DISPFlags fromRust(LLVMRustDISPFlags SPFlags) {
return Result;
}

#ifdef LLVM_RUSTLLVM
// These values **must** match debuginfo::ShortBacktrace! They also *happen*
// to match LLVM, but that isn't required as we do giant sets of
// matching below. The value shouldn't be directly passed to LLVM.
enum class LLVMRustShortBacktrace {
SkipFrame,
StartShortBacktrace,
EndShortBacktrace,
None,
};

static std::optional<ShortBacktraceAttr> shortBacktraceFromRust(LLVMRustShortBacktrace backtrace) {
switch (backtrace) {
case LLVMRustShortBacktrace::SkipFrame:
return ShortBacktraceAttr::SkipFrame;
case LLVMRustShortBacktrace::StartShortBacktrace:
return ShortBacktraceAttr::StartShortBacktrace;
case LLVMRustShortBacktrace::EndShortBacktrace:
return ShortBacktraceAttr::EndShortBacktrace;
case LLVMRustShortBacktrace::None:
return std::nullopt;
default:
report_fatal_error("bad ShortBacktraceAttr.");
}
}
#endif

enum class LLVMRustDebugEmissionKind {
NoDebug,
FullDebug,
Expand Down Expand Up @@ -1016,6 +1043,9 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction(
size_t NameLen, const char *LinkageName, size_t LinkageNameLen,
LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Ty,
unsigned ScopeLine, LLVMRustDIFlags Flags, LLVMRustDISPFlags SPFlags,
#ifdef LLVM_RUSTLLVM
LLVMRustShortBacktrace shortBacktrace,
#endif
LLVMValueRef MaybeFn, LLVMMetadataRef TParam, LLVMMetadataRef Decl) {
DITemplateParameterArray TParams =
DITemplateParameterArray(unwrap<MDTuple>(TParam));
Expand All @@ -1025,6 +1055,9 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction(
unwrapDI<DIScope>(Scope), StringRef(Name, NameLen),
StringRef(LinkageName, LinkageNameLen), unwrapDI<DIFile>(File), LineNo,
unwrapDI<DISubroutineType>(Ty), ScopeLine, llvmFlags, llvmSPFlags,
#ifdef LLVM_RUSTLLVM
shortBacktraceFromRust(shortBacktrace),
#endif
TParams, unwrapDIPtr<DISubprogram>(Decl));
if (MaybeFn)
unwrap<Function>(MaybeFn)->setSubprogram(Sub);
Expand All @@ -1035,7 +1068,11 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateMethod(
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
size_t NameLen, const char *LinkageName, size_t LinkageNameLen,
LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Ty,
LLVMRustDIFlags Flags, LLVMRustDISPFlags SPFlags, LLVMMetadataRef TParam) {
LLVMRustDIFlags Flags, LLVMRustDISPFlags SPFlags,
#ifdef LLVM_RUSTLLVM
LLVMRustShortBacktrace shortBacktrace,
#endif
LLVMMetadataRef TParam) {
DITemplateParameterArray TParams =
DITemplateParameterArray(unwrap<MDTuple>(TParam));
DISubprogram::DISPFlags llvmSPFlags = fromRust(SPFlags);
Expand All @@ -1045,7 +1082,11 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateMethod(
StringRef(LinkageName, LinkageNameLen), unwrapDI<DIFile>(File), LineNo,
unwrapDI<DISubroutineType>(Ty), 0, 0,
nullptr, // VTable params aren't used
llvmFlags, llvmSPFlags, TParams);
llvmFlags, llvmSPFlags,
#ifdef LLVM_RUSTLLVM
shortBacktraceFromRust(shortBacktrace),
#endif
TParams);
return wrap(Sub);
}

Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_middle/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ middle_limit_invalid =
`limit` must be a non-negative integer
.label = {$error_str}
middle_multiple_short_backtrace_attrs = multiple `#[rustc_*_short_backtrace]` attributes were used on the same item
.note = "attribute used here"
middle_opaque_hidden_type_mismatch =
concrete type differs from previous defining opaque type use
.label = expected `{$self_ty}`, got `{$other_ty}`
Expand Down
Loading

0 comments on commit 254d2dc

Please sign in to comment.