Implement .eh_frame writing

This commit is contained in:
bjorn3 2020-04-25 18:23:31 +02:00
parent 9d6f65ea14
commit e7661d49c3
6 changed files with 62 additions and 8 deletions

View File

@ -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/" }

View File

@ -39,7 +39,7 @@ fn add_rustc_section(&mut self, symbol_name: String, data: Vec<u8>, _is_like_osx
}
pub(crate) trait WriteDebugInfo {
type SectionId;
type SectionId: Copy;
fn add_debug_section(&mut self, name: SectionId, data: Vec<u8>) -> Self::SectionId;
fn add_debug_reloc(

View File

@ -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<P: WriteDebugInfo>(&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<P: WriteDebugInfo>(&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(&section_map, &self.symbols, &section_id, reloc);
}
}
}
}

View File

@ -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<Type, UnitEntryId>,
types: FxHashMap<Ty<'tcx>, 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<SourceInfo>,
local_map: FxHashMap<mir::Local, CPlace<'tcx>>,
) {
self.create_unwind_info(context, isa);
let end = self.create_debug_lines(context, isa, source_info_set);
self.debug_context

31
src/debuginfo/unwind.rs Normal file
View File

@ -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
}
}
}
}

View File

@ -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 {