Include debug info for the allocator shim

Issue Details:
In some cases it is necessary to generate an "allocator shim" to forward various Rust allocation functions (e.g., `__rust_alloc`) to an underlying function (e.g., `malloc`). However, since this allocator shim is a manually created LLVM module it is not processed via the normal module processing code and so no debug info is generated for it (if debugging info is enabled).

Fix Details:
* Modify the `debuginfo` code to allow creating debug info for a module without a `CodegenCx` (since it is difficult, and expensive, to create one just to emit some debug info).
* After creating the allocator shim add in basic debug info.
This commit is contained in:
Daniel Paoliello 2021-08-31 11:16:10 -07:00
parent 6cfa773583
commit 77a96ed564
5 changed files with 66 additions and 41 deletions

View file

@ -3,19 +3,22 @@ use libc::c_uint;
use rustc_ast::expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS}; use rustc_ast::expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS};
use rustc_middle::bug; use rustc_middle::bug;
use rustc_middle::ty::TyCtxt; use rustc_middle::ty::TyCtxt;
use rustc_session::config::DebugInfo;
use rustc_span::symbol::sym; use rustc_span::symbol::sym;
use crate::debuginfo;
use crate::llvm::{self, False, True}; use crate::llvm::{self, False, True};
use crate::ModuleLlvm; use crate::ModuleLlvm;
pub(crate) unsafe fn codegen( pub(crate) unsafe fn codegen(
tcx: TyCtxt<'_>, tcx: TyCtxt<'_>,
mods: &mut ModuleLlvm, module_llvm: &mut ModuleLlvm,
module_name: &str,
kind: AllocatorKind, kind: AllocatorKind,
has_alloc_error_handler: bool, has_alloc_error_handler: bool,
) { ) {
let llcx = &*mods.llcx; let llcx = &*module_llvm.llcx;
let llmod = mods.llmod(); let llmod = module_llvm.llmod();
let usize = match tcx.sess.target.pointer_width { let usize = match tcx.sess.target.pointer_width {
16 => llvm::LLVMInt16TypeInContext(llcx), 16 => llvm::LLVMInt16TypeInContext(llcx),
32 => llvm::LLVMInt32TypeInContext(llcx), 32 => llvm::LLVMInt32TypeInContext(llcx),
@ -132,4 +135,10 @@ pub(crate) unsafe fn codegen(
llvm::LLVMSetTailCall(ret, True); llvm::LLVMSetTailCall(ret, True);
llvm::LLVMBuildRetVoid(llbuilder); llvm::LLVMBuildRetVoid(llbuilder);
llvm::LLVMDisposeBuilder(llbuilder); llvm::LLVMDisposeBuilder(llbuilder);
if tcx.sess.opts.debuginfo != DebugInfo::None {
let dbg_cx = debuginfo::CrateDebugContext::new(llmod);
debuginfo::metadata::compile_unit_metadata(tcx, module_name, &dbg_cx);
dbg_cx.finalize(tcx.sess);
}
} }

View file

@ -29,6 +29,7 @@ use rustc_middle::ty::layout::HasTyCtxt;
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef}; use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TypeFoldable}; use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TypeFoldable};
use rustc_session::config::{self, DebugInfo}; use rustc_session::config::{self, DebugInfo};
use rustc_session::Session;
use rustc_span::symbol::Symbol; use rustc_span::symbol::Symbol;
use rustc_span::{self, BytePos, Pos, SourceFile, SourceFileAndLine, Span}; use rustc_span::{self, BytePos, Pos, SourceFile, SourceFileAndLine, Span};
use rustc_target::abi::{LayoutOf, Primitive, Size}; use rustc_target::abi::{LayoutOf, Primitive, Size};
@ -95,45 +96,52 @@ impl<'a, 'tcx> CrateDebugContext<'a, 'tcx> {
composite_types_completed: Default::default(), composite_types_completed: Default::default(),
} }
} }
pub fn finalize(&self, sess: &Session) {
unsafe {
llvm::LLVMRustDIBuilderFinalize(self.builder);
// Debuginfo generation in LLVM by default uses a higher
// version of dwarf than macOS currently understands. We can
// instruct LLVM to emit an older version of dwarf, however,
// for macOS to understand. For more info see #11352
// This can be overridden using --llvm-opts -dwarf-version,N.
// Android has the same issue (#22398)
if let Some(version) = sess.target.dwarf_version {
llvm::LLVMRustAddModuleFlag(self.llmod, "Dwarf Version\0".as_ptr().cast(), version)
}
// Indicate that we want CodeView debug information on MSVC
if sess.target.is_like_msvc {
llvm::LLVMRustAddModuleFlag(self.llmod, "CodeView\0".as_ptr().cast(), 1)
}
// Prevent bitcode readers from deleting the debug info.
let ptr = "Debug Info Version\0".as_ptr();
llvm::LLVMRustAddModuleFlag(
self.llmod,
ptr.cast(),
llvm::LLVMRustDebugMetadataVersion(),
);
}
}
} }
/// Creates any deferred debug metadata nodes /// Creates any deferred debug metadata nodes
pub fn finalize(cx: &CodegenCx<'_, '_>) { pub fn finalize(cx: &CodegenCx<'_, '_>) {
if cx.dbg_cx.is_none() { if let Some(dbg_cx) = &cx.dbg_cx {
return; debug!("finalize");
}
debug!("finalize"); if gdb::needs_gdb_debug_scripts_section(cx) {
// Add a .debug_gdb_scripts section to this compile-unit. This will
if gdb::needs_gdb_debug_scripts_section(cx) { // cause GDB to try and load the gdb_load_rust_pretty_printers.py file,
// Add a .debug_gdb_scripts section to this compile-unit. This will // which activates the Rust pretty printers for binary this section is
// cause GDB to try and load the gdb_load_rust_pretty_printers.py file, // contained in.
// which activates the Rust pretty printers for binary this section is gdb::get_or_insert_gdb_debug_scripts_section_global(cx);
// contained in.
gdb::get_or_insert_gdb_debug_scripts_section_global(cx);
}
unsafe {
llvm::LLVMRustDIBuilderFinalize(DIB(cx));
// Debuginfo generation in LLVM by default uses a higher
// version of dwarf than macOS currently understands. We can
// instruct LLVM to emit an older version of dwarf, however,
// for macOS to understand. For more info see #11352
// This can be overridden using --llvm-opts -dwarf-version,N.
// Android has the same issue (#22398)
if let Some(version) = cx.sess().target.dwarf_version {
llvm::LLVMRustAddModuleFlag(cx.llmod, "Dwarf Version\0".as_ptr().cast(), version)
} }
// Indicate that we want CodeView debug information on MSVC dbg_cx.finalize(cx.sess());
if cx.sess().target.is_like_msvc { }
llvm::LLVMRustAddModuleFlag(cx.llmod, "CodeView\0".as_ptr().cast(), 1)
}
// Prevent bitcode readers from deleting the debug info.
let ptr = "Debug Info Version\0".as_ptr();
llvm::LLVMRustAddModuleFlag(cx.llmod, ptr.cast(), llvm::LLVMRustDebugMetadataVersion());
};
} }
impl DebugInfoBuilderMethods for Builder<'a, 'll, 'tcx> { impl DebugInfoBuilderMethods for Builder<'a, 'll, 'tcx> {

View file

@ -92,11 +92,12 @@ impl ExtraBackendMethods for LlvmCodegenBackend {
fn codegen_allocator<'tcx>( fn codegen_allocator<'tcx>(
&self, &self,
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
mods: &mut ModuleLlvm, module_llvm: &mut ModuleLlvm,
module_name: &str,
kind: AllocatorKind, kind: AllocatorKind,
has_alloc_error_handler: bool, has_alloc_error_handler: bool,
) { ) {
unsafe { allocator::codegen(tcx, mods, kind, has_alloc_error_handler) } unsafe { allocator::codegen(tcx, module_llvm, module_name, kind, has_alloc_error_handler) }
} }
fn compile_codegen_unit( fn compile_codegen_unit(
&self, &self,

View file

@ -538,12 +538,18 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
} else if let Some(kind) = tcx.allocator_kind(()) { } else if let Some(kind) = tcx.allocator_kind(()) {
let llmod_id = let llmod_id =
cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], Some("allocator")).to_string(); cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], Some("allocator")).to_string();
let mut modules = backend.new_metadata(tcx, &llmod_id); let mut module_llvm = backend.new_metadata(tcx, &llmod_id);
tcx.sess.time("write_allocator_module", || { tcx.sess.time("write_allocator_module", || {
backend.codegen_allocator(tcx, &mut modules, kind, tcx.lang_items().oom().is_some()) backend.codegen_allocator(
tcx,
&mut module_llvm,
&llmod_id,
kind,
tcx.lang_items().oom().is_some(),
)
}); });
Some(ModuleCodegen { name: llmod_id, module_llvm: modules, kind: ModuleKind::Allocator }) Some(ModuleCodegen { name: llmod_id, module_llvm, kind: ModuleKind::Allocator })
} else { } else {
None None
}; };

View file

@ -120,7 +120,8 @@ pub trait ExtraBackendMethods: CodegenBackend + WriteBackendMethods + Sized + Se
fn codegen_allocator<'tcx>( fn codegen_allocator<'tcx>(
&self, &self,
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
mods: &mut Self::Module, module_llvm: &mut Self::Module,
module_name: &str,
kind: AllocatorKind, kind: AllocatorKind,
has_alloc_error_handler: bool, has_alloc_error_handler: bool,
); );