diff --git a/Cargo.toml b/Cargo.toml index 81c2a8d5c03..90f5429bb0e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ crate-type = ["dylib"] [dependencies] # These have to be in sync with each other -cranelift-codegen = { git = "https://github.com/bytecodealliance/wasmtime/" } +cranelift-codegen = { git = "https://github.com/bytecodealliance/wasmtime/", features = ["unwind"] } cranelift-frontend = { git = "https://github.com/bytecodealliance/wasmtime/" } cranelift-module = { git = "https://github.com/bytecodealliance/wasmtime/" } cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime/" } diff --git a/src/backend.rs b/src/backend.rs index 319183729d1..bfc9e2d4367 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -39,7 +39,7 @@ fn add_rustc_section(&mut self, symbol_name: String, data: Vec, _is_like_osx } pub(crate) trait WriteDebugInfo { - type SectionId; + type SectionId: Copy; fn add_debug_section(&mut self, name: SectionId, data: Vec) -> Self::SectionId; fn add_debug_reloc( diff --git a/src/debuginfo/emit.rs b/src/debuginfo/emit.rs index 0c24fe359df..e49e13a5be5 100644 --- a/src/debuginfo/emit.rs +++ b/src/debuginfo/emit.rs @@ -1,6 +1,6 @@ use rustc_data_structures::fx::FxHashMap; -use gimli::write::{Address, AttributeValue, EndianVec, Result, Sections, Writer}; +use gimli::write::{Address, AttributeValue, EhFrame, EndianVec, Result, Sections, Writer, Section}; use gimli::{RunTimeEndian, SectionId}; use crate::backend::WriteDebugInfo; @@ -20,6 +20,9 @@ pub(crate) fn emit(&mut self, product: &mut P) { let mut sections = Sections::new(WriterRelocate::new(self)); self.dwarf.write(&mut sections).unwrap(); + let mut eh_frame = EhFrame::from(WriterRelocate::new(self)); + self.frame_table.write_eh_frame(&mut eh_frame).unwrap(); + let mut section_map = FxHashMap::default(); let _: Result<()> = sections.for_each_mut(|id, section| { if !section.writer.slice().is_empty() { @@ -37,6 +40,16 @@ pub(crate) fn emit(&mut self, product: &mut P) { } Ok(()) }); + + if !eh_frame.0.writer.slice().is_empty() { + let id = eh_frame.id(); + let section_id = product.add_debug_section(id, eh_frame.0.writer.into_vec()); + section_map.insert(id, section_id); + + for reloc in &eh_frame.0.relocs { + product.add_debug_reloc(§ion_map, &self.symbols, §ion_id, reloc); + } + } } } diff --git a/src/debuginfo/mod.rs b/src/debuginfo/mod.rs index fb0a8b006c1..fdc6cc911c7 100644 --- a/src/debuginfo/mod.rs +++ b/src/debuginfo/mod.rs @@ -1,5 +1,6 @@ mod emit; mod line_info; +mod unwind; use crate::prelude::*; @@ -10,8 +11,8 @@ use cranelift_codegen::ValueLocRange; use gimli::write::{ - self, Address, AttributeValue, DwarfUnit, Expression, LineProgram, LineString, Location, - LocationList, Range, RangeList, UnitEntryId, Writer, + self, Address, AttributeValue, CieId, DwarfUnit, Expression, FrameTable, LineProgram, + LineString, Location, LocationList, Range, RangeList, UnitEntryId, Writer, }; use gimli::{Encoding, Format, LineEncoding, RunTimeEndian, X86_64}; @@ -34,13 +35,15 @@ pub(crate) struct DebugContext<'tcx> { dwarf: DwarfUnit, unit_range_list: RangeList, + frame_table: FrameTable, + cie: CieId, clif_types: FxHashMap, types: FxHashMap, UnitEntryId>, } impl<'tcx> DebugContext<'tcx> { - pub(crate) fn new(tcx: TyCtxt<'tcx>, address_size: u8) -> Self { + pub(crate) fn new(tcx: TyCtxt<'tcx>, isa: &dyn TargetIsa) -> Self { let encoding = Encoding { format: Format::Dwarf32, // TODO: this should be configurable @@ -53,7 +56,7 @@ pub(crate) fn new(tcx: TyCtxt<'tcx>, address_size: u8) -> Self { // support it. 4 }, - address_size, + address_size: isa.frontend_config().pointer_bytes(), }; let mut dwarf = DwarfUnit::new(encoding); @@ -108,6 +111,9 @@ pub(crate) fn new(tcx: TyCtxt<'tcx>, address_size: u8) -> Self { ); } + let mut frame_table = FrameTable::default(); + let cie = frame_table.add_cie(isa.create_systemv_cie().expect("SystemV unwind info CIE")); + DebugContext { tcx, @@ -116,7 +122,9 @@ pub(crate) fn new(tcx: TyCtxt<'tcx>, address_size: u8) -> Self { dwarf, unit_range_list: RangeList(Vec::new()), + frame_table, + cie, clif_types: FxHashMap::default(), types: FxHashMap::default(), } @@ -312,6 +320,8 @@ pub(crate) fn define( source_info_set: &indexmap::IndexSet, local_map: FxHashMap>, ) { + self.create_unwind_info(context, isa); + let end = self.create_debug_lines(context, isa, source_info_set); self.debug_context diff --git a/src/debuginfo/unwind.rs b/src/debuginfo/unwind.rs new file mode 100644 index 00000000000..c0d4eb5c0ed --- /dev/null +++ b/src/debuginfo/unwind.rs @@ -0,0 +1,31 @@ +use crate::prelude::*; + +use cranelift_codegen::isa::unwind::UnwindInfo; + +use gimli::write::Address; + +impl<'a, 'tcx> FunctionDebugContext<'a, 'tcx> { + pub(super) fn create_unwind_info( + &mut self, + context: &Context, + isa: &dyn cranelift_codegen::isa::TargetIsa, + ) { + let unwind_info = if let Some(unwind_info) = context.create_unwind_info(isa).unwrap() { + unwind_info + } else { + return; + }; + + match unwind_info { + UnwindInfo::SystemV(unwind_info) => { + self.debug_context.frame_table.add_fde(self.debug_context.cie, unwind_info.to_fde(Address::Symbol { + symbol: self.symbol, + addend: 0, + })); + }, + UnwindInfo::WindowsX64(_) => { + // FIXME implement this + } + } + } +} diff --git a/src/driver/aot.rs b/src/driver/aot.rs index b74608974b7..6ab5b40d3ce 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -120,7 +120,7 @@ fn module_codegen(tcx: TyCtxt<'_>, cgu_name: rustc_span::Symbol) -> ModuleCodege let mut debug = if tcx.sess.opts.debuginfo != DebugInfo::None { let debug = DebugContext::new( tcx, - module.target_config().pointer_type().bytes() as u8, + module.isa(), ); Some(debug) } else {