diff --git a/src/backend.rs b/src/backend.rs index f070e95f535e..429c48ba0e38 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -1,8 +1,21 @@ -pub trait Product { +use std::collections::HashMap; + +use cranelift_module::FuncId; + +use faerie::*; +use object::{SectionKind, RelocationKind, RelocationEncoding}; +use object::write::*; +use cranelift_object::*; + +use gimli::SectionId; + +use crate::debuginfo::{DebugReloc, DebugRelocName}; + +pub trait WriteMetadata { fn add_rustc_section(&mut self, symbol_name: String, data: Vec, is_like_osx: bool); } -impl Product for faerie::Artifact { +impl WriteMetadata for faerie::Artifact { fn add_rustc_section(&mut self, symbol_name: String, data: Vec, is_like_osx: bool) { self .declare(".rustc", faerie::Decl::section(faerie::SectionKind::Data)) @@ -25,7 +38,7 @@ impl Product for faerie::Artifact { } } -impl Product for object::write::Object { +impl WriteMetadata for object::write::Object { fn add_rustc_section(&mut self, symbol_name: String, data: Vec, is_like_osx: bool) { let segment = self.segment_name(object::write::StandardSegment::Data).to_vec(); let section_id = self.add_section(segment, b".rustc".to_vec(), object::SectionKind::Data); @@ -46,3 +59,91 @@ impl Product for object::write::Object { } } } + +pub trait WriteDebugInfo { + type SectionId; + + fn add_debug_section(&mut self, name: SectionId, data: Vec) -> Self::SectionId; + fn add_debug_reloc( + &mut self, + section_map: &HashMap, + symbol_map: &indexmap::IndexSet<(String, FuncId)>, + from: &Self::SectionId, + reloc: &DebugReloc, + ); +} + +impl WriteDebugInfo for Artifact { + type SectionId = SectionId; + + fn add_debug_section(&mut self, id: SectionId, data: Vec) -> SectionId { + self.declare_with(id.name(), Decl::section(faerie::SectionKind::Debug), data).unwrap(); + id + } + + fn add_debug_reloc( + &mut self, + _section_map: &HashMap, + symbol_map: &indexmap::IndexSet<(String, FuncId)>, + from: &Self::SectionId, + reloc: &DebugReloc, + ) { + self + .link_with( + faerie::Link { + from: from.name(), + to: match reloc.name { + DebugRelocName::Section(id) => id.name(), + DebugRelocName::Symbol(index) => &symbol_map.get_index(index).unwrap().0, + }, + at: u64::from(reloc.offset), + }, + faerie::Reloc::Debug { + size: reloc.size, + addend: reloc.addend as i32, + }, + ) + .expect("faerie relocation error"); + } +} + +impl WriteDebugInfo for ObjectProduct { + type SectionId = (object::write::SectionId, object::write::SymbolId); + + fn add_debug_section( + &mut self, + id: SectionId, + data: Vec, + ) -> (object::write::SectionId, object::write::SymbolId) { + let segment = self.object.segment_name(StandardSegment::Debug).to_vec(); + let name = id.name().as_bytes().to_vec(); + let section_id = self.object.add_section(segment, name, SectionKind::Debug); + self.object.section_mut(section_id).set_data(data, 1); + let symbol_id = self.object.section_symbol(section_id); + (section_id, symbol_id) + } + + fn add_debug_reloc( + &mut self, + section_map: &HashMap, + symbol_map: &indexmap::IndexSet<(String, FuncId)>, + from: &Self::SectionId, + reloc: &DebugReloc, + ) { + let symbol = match reloc.name { + DebugRelocName::Section(id) => section_map.get(&id).unwrap().1, + DebugRelocName::Symbol(id) => { + let (_func_name, func_id) = symbol_map.get_index(id).unwrap(); + self.function_symbol(*func_id) + } + }; + self.object.add_relocation(from.0, Relocation { + offset: u64::from(reloc.offset), + symbol, + kind: RelocationKind::Absolute, + encoding: RelocationEncoding::Generic, + size: reloc.size * 8, + addend: reloc.addend, + }).unwrap(); + } +} diff --git a/src/base.rs b/src/base.rs index 81750efd169e..ef32dafb2efc 100644 --- a/src/base.rs +++ b/src/base.rs @@ -17,7 +17,7 @@ pub fn trans_fn<'clif, 'tcx, B: Backend + 'static>( let mut debug_context = cx .debug_context .as_mut() - .map(|debug_context| FunctionDebugContext::new(tcx, debug_context, mir, &name, &sig)); + .map(|debug_context| FunctionDebugContext::new(tcx, debug_context, mir, func_id, &name, &sig)); // Make FunctionBuilder let mut func = Function::with_name_signature(ExternalName::user(0, 0), sig); diff --git a/src/debuginfo.rs b/src/debuginfo.rs index 0ded96cec8a5..d2705c6a2c74 100644 --- a/src/debuginfo.rs +++ b/src/debuginfo.rs @@ -1,5 +1,7 @@ use crate::prelude::*; +use crate::backend::WriteDebugInfo; + use std::marker::PhantomData; use syntax::source_map::FileName; @@ -10,8 +12,6 @@ use gimli::write::{ }; use gimli::{Encoding, Format, LineEncoding, RunTimeEndian, SectionId}; -use faerie::*; - fn target_endian(tcx: TyCtxt) -> RunTimeEndian { use rustc::ty::layout::Endian; @@ -56,31 +56,22 @@ fn line_program_add_file( } #[derive(Clone)] -struct DebugReloc { - offset: u32, - size: u8, - name: DebugRelocName, - addend: i64, +pub struct DebugReloc { + pub offset: u32, + pub size: u8, + pub name: DebugRelocName, + pub addend: i64, } #[derive(Clone)] -enum DebugRelocName { +pub enum DebugRelocName { Section(SectionId), Symbol(usize), } -impl DebugReloc { - fn name<'a>(&self, ctx: &'a DebugContext) -> &'a str { - match self.name { - DebugRelocName::Section(id) => id.name(), - DebugRelocName::Symbol(index) => ctx.symbols.get_index(index).unwrap(), - } - } -} - pub struct DebugContext<'tcx> { endian: RunTimeEndian, - symbols: indexmap::IndexSet, + symbols: indexmap::IndexSet<(String, FuncId)>, dwarf: DwarfUnit, unit_range_list: RangeList, @@ -177,7 +168,7 @@ impl<'tcx> DebugContext<'tcx> { ); } - pub fn emit(&mut self, artifact: &mut Artifact) { + pub fn emit(&mut self, product: &mut P) { let unit_range_list_id = self.dwarf.unit.ranges.add(self.unit_range_list.clone()); let root = self.dwarf.unit.root(); let root = self.dwarf.unit.get_mut(root); @@ -189,34 +180,20 @@ impl<'tcx> DebugContext<'tcx> { let mut sections = Sections::new(WriterRelocate::new(self)); self.dwarf.write(&mut sections).unwrap(); + let mut section_map = HashMap::new(); let _: Result<()> = sections.for_each_mut(|id, section| { if !section.writer.slice().is_empty() { - artifact - .declare_with( - id.name(), - Decl::section(SectionKind::Debug), - section.writer.take(), - ) - .unwrap(); + let section_id = product.add_debug_section(id, section.writer.take()); + section_map.insert(id, section_id); } Ok(()) }); let _: Result<()> = sections.for_each(|id, section| { - for reloc in §ion.relocs { - artifact - .link_with( - faerie::Link { - from: id.name(), - to: reloc.name(self), - at: u64::from(reloc.offset), - }, - faerie::Reloc::Debug { - size: reloc.size, - addend: reloc.addend as i32, - }, - ) - .expect("faerie relocation error"); + if let Some(section_id) = section_map.get(&id) { + for reloc in §ion.relocs { + product.add_debug_reloc(§ion_map, &self.symbols, section_id, reloc); + } } Ok(()) }); @@ -235,10 +212,11 @@ impl<'a, 'tcx> FunctionDebugContext<'a, 'tcx> { tcx: TyCtxt<'tcx>, debug_context: &'a mut DebugContext<'tcx>, mir: &Body, + func_id: FuncId, name: &str, _sig: &Signature, ) -> Self { - let (symbol, _) = debug_context.symbols.insert_full(name.to_string()); + let (symbol, _) = debug_context.symbols.insert_full((name.to_string(), func_id)); // FIXME: add to appropriate scope intead of root let scope = debug_context.dwarf.unit.root(); diff --git a/src/metadata.rs b/src/metadata.rs index 76c86e73853f..f15e1682d13d 100644 --- a/src/metadata.rs +++ b/src/metadata.rs @@ -9,7 +9,7 @@ use rustc_data_structures::owning_ref::{self, OwningRef}; use rustc_data_structures::rustc_erase_owner; use rustc_target::spec::Target; -use crate::backend::Product; +use crate::backend::WriteMetadata; pub struct CraneliftMetadataLoader; @@ -53,7 +53,7 @@ impl MetadataLoader for CraneliftMetadataLoader { } // Adapted from https://github.com/rust-lang/rust/blob/da573206f87b5510de4b0ee1a9c044127e409bd3/src/librustc_codegen_llvm/base.rs#L47-L112 -pub fn write_metadata(tcx: TyCtxt<'_>, product: &mut P) -> EncodedMetadata { +pub fn write_metadata(tcx: TyCtxt<'_>, product: &mut P) -> EncodedMetadata { use flate2::write::DeflateEncoder; use flate2::Compression; use std::io::Write;