Make debuginfo writing backend agnostic

This commit is contained in:
bjorn3 2019-10-16 21:21:20 +02:00
parent f9ff604d96
commit 5873127ec2
4 changed files with 126 additions and 47 deletions

View File

@ -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<u8>, 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<u8>, is_like_osx: bool) {
self
.declare(".rustc", faerie::Decl::section(faerie::SectionKind::Data))
@ -25,7 +38,7 @@ fn add_rustc_section(&mut self, symbol_name: String, data: Vec<u8>, is_like_osx:
}
}
impl Product for object::write::Object {
impl WriteMetadata for object::write::Object {
fn add_rustc_section(&mut self, symbol_name: String, data: Vec<u8>, 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 @@ fn add_rustc_section(&mut self, symbol_name: String, data: Vec<u8>, is_like_osx:
}
}
}
pub trait WriteDebugInfo {
type SectionId;
fn add_debug_section(&mut self, name: SectionId, data: Vec<u8>) -> Self::SectionId;
fn add_debug_reloc(
&mut self,
section_map: &HashMap<SectionId, Self::SectionId>,
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<u8>) -> SectionId {
self.declare_with(id.name(), Decl::section(faerie::SectionKind::Debug), data).unwrap();
id
}
fn add_debug_reloc(
&mut self,
_section_map: &HashMap<SectionId, Self::SectionId>,
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<u8>,
) -> (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<SectionId, Self::SectionId>,
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();
}
}

View File

@ -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);

View File

@ -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::{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<String>,
symbols: indexmap::IndexSet<(String, FuncId)>,
dwarf: DwarfUnit,
unit_range_list: RangeList,
@ -177,7 +168,7 @@ fn emit_location(&mut self, tcx: TyCtxt<'tcx>, entry_id: UnitEntryId, span: Span
);
}
pub fn emit(&mut self, artifact: &mut Artifact) {
pub fn emit<P: WriteDebugInfo>(&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 @@ pub fn emit(&mut self, artifact: &mut Artifact) {
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 &section.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 &section.relocs {
product.add_debug_reloc(&section_map, &self.symbols, section_id, reloc);
}
}
Ok(())
});
@ -235,10 +212,11 @@ pub fn new(
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();

View File

@ -9,7 +9,7 @@
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 @@ fn get_dylib_metadata(
}
// Adapted from https://github.com/rust-lang/rust/blob/da573206f87b5510de4b0ee1a9c044127e409bd3/src/librustc_codegen_llvm/base.rs#L47-L112
pub fn write_metadata<P: Product>(tcx: TyCtxt<'_>, product: &mut P) -> EncodedMetadata {
pub fn write_metadata<P: WriteMetadata>(tcx: TyCtxt<'_>, product: &mut P) -> EncodedMetadata {
use flate2::write::DeflateEncoder;
use flate2::Compression;
use std::io::Write;