Make debuginfo writing backend agnostic
This commit is contained in:
parent
f9ff604d96
commit
5873127ec2
107
src/backend.rs
107
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<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();
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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 §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 @@ 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();
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user