diff --git a/src/debuginfo/emit.rs b/src/debuginfo/emit.rs new file mode 100644 index 00000000000..2b6dc9f669f --- /dev/null +++ b/src/debuginfo/emit.rs @@ -0,0 +1,135 @@ +use std::collections::HashMap; + +use gimli::write::{Address, AttributeValue, EndianVec, Result, Sections, Writer}; +use gimli::{RunTimeEndian, SectionId}; + +use crate::backend::WriteDebugInfo; + +use super::DebugContext; + +impl DebugContext<'_> { + 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); + root.set( + gimli::DW_AT_ranges, + AttributeValue::RangeListRef(unit_range_list_id), + ); + + 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() { + 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| { + 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(()) + }); + } +} + +#[derive(Clone)] +pub struct DebugReloc { + pub offset: u32, + pub size: u8, + pub name: DebugRelocName, + pub addend: i64, +} + +#[derive(Clone)] +pub enum DebugRelocName { + Section(SectionId), + Symbol(usize), +} + +#[derive(Clone)] +struct WriterRelocate { + relocs: Vec, + writer: EndianVec, +} + +impl WriterRelocate { + fn new(ctx: &DebugContext) -> Self { + WriterRelocate { + relocs: Vec::new(), + writer: EndianVec::new(ctx.endian), + } + } +} + +impl Writer for WriterRelocate { + type Endian = RunTimeEndian; + + fn endian(&self) -> Self::Endian { + self.writer.endian() + } + + fn len(&self) -> usize { + self.writer.len() + } + + fn write(&mut self, bytes: &[u8]) -> Result<()> { + self.writer.write(bytes) + } + + fn write_at(&mut self, offset: usize, bytes: &[u8]) -> Result<()> { + self.writer.write_at(offset, bytes) + } + + fn write_address(&mut self, address: Address, size: u8) -> Result<()> { + match address { + Address::Constant(val) => self.write_udata(val, size), + Address::Symbol { symbol, addend } => { + let offset = self.len() as u64; + self.relocs.push(DebugReloc { + offset: offset as u32, + size, + name: DebugRelocName::Symbol(symbol), + addend: addend as i64, + }); + self.write_udata(0, size) + } + } + } + + // TODO: implement write_eh_pointer + + fn write_offset(&mut self, val: usize, section: SectionId, size: u8) -> Result<()> { + let offset = self.len() as u32; + self.relocs.push(DebugReloc { + offset, + size, + name: DebugRelocName::Section(section), + addend: val as i64, + }); + self.write_udata(0, size) + } + + fn write_offset_at( + &mut self, + offset: usize, + val: usize, + section: SectionId, + size: u8, + ) -> Result<()> { + self.relocs.push(DebugReloc { + offset: offset as u32, + size, + name: DebugRelocName::Section(section), + addend: val as i64, + }); + self.write_udata_at(offset, 0, size) + } +} diff --git a/src/debuginfo/mod.rs b/src/debuginfo/mod.rs index 63a95e7e0e7..3ab03a411c8 100644 --- a/src/debuginfo/mod.rs +++ b/src/debuginfo/mod.rs @@ -1,6 +1,6 @@ -use crate::prelude::*; +mod emit; -use crate::backend::WriteDebugInfo; +use crate::prelude::*; use syntax::source_map::FileName; @@ -8,11 +8,12 @@ use cranelift::codegen::ir::{StackSlots, ValueLoc}; use cranelift::codegen::isa::RegUnit; use gimli::write::{ - self, Address, AttributeValue, DwarfUnit, EndianVec, Expression, FileId, LineProgram, - LineString, LineStringTable, Location, LocationList, Range, RangeList, Result, Sections, - UnitEntryId, Writer, + self, Address, AttributeValue, DwarfUnit, Expression, FileId, LineProgram, LineString, + LineStringTable, Location, LocationList, Range, RangeList, UnitEntryId, Writer, }; -use gimli::{Encoding, Format, LineEncoding, Register, RunTimeEndian, SectionId, X86_64}; +use gimli::{Encoding, Format, LineEncoding, Register, RunTimeEndian, X86_64}; + +pub use emit::{DebugReloc, DebugRelocName}; fn target_endian(tcx: TyCtxt) -> RunTimeEndian { use rustc::ty::layout::Endian; @@ -57,20 +58,6 @@ fn line_program_add_file( } } -#[derive(Clone)] -pub struct DebugReloc { - pub offset: u32, - pub size: u8, - pub name: DebugRelocName, - pub addend: i64, -} - -#[derive(Clone)] -pub enum DebugRelocName { - Section(SectionId), - Symbol(usize), -} - pub struct DebugContext<'tcx> { tcx: TyCtxt<'tcx>, @@ -225,37 +212,6 @@ impl<'tcx> DebugContext<'tcx> { type_id } - - 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); - root.set( - gimli::DW_AT_ranges, - AttributeValue::RangeListRef(unit_range_list_id), - ); - - 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() { - 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| { - 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(()) - }); - } } pub struct FunctionDebugContext<'a, 'tcx> { @@ -449,85 +405,6 @@ impl<'a, 'tcx> FunctionDebugContext<'a, 'tcx> { } } -#[derive(Clone)] -struct WriterRelocate { - relocs: Vec, - writer: EndianVec, -} - -impl WriterRelocate { - fn new(ctx: &DebugContext) -> Self { - WriterRelocate { - relocs: Vec::new(), - writer: EndianVec::new(ctx.endian), - } - } -} - -impl Writer for WriterRelocate { - type Endian = RunTimeEndian; - - fn endian(&self) -> Self::Endian { - self.writer.endian() - } - - fn len(&self) -> usize { - self.writer.len() - } - - fn write(&mut self, bytes: &[u8]) -> Result<()> { - self.writer.write(bytes) - } - - fn write_at(&mut self, offset: usize, bytes: &[u8]) -> Result<()> { - self.writer.write_at(offset, bytes) - } - - fn write_address(&mut self, address: Address, size: u8) -> Result<()> { - match address { - Address::Constant(val) => self.write_udata(val, size), - Address::Symbol { symbol, addend } => { - let offset = self.len() as u64; - self.relocs.push(DebugReloc { - offset: offset as u32, - size, - name: DebugRelocName::Symbol(symbol), - addend: addend as i64, - }); - self.write_udata(0, size) - } - } - } - - // TODO: implement write_eh_pointer - - fn write_offset(&mut self, val: usize, section: SectionId, size: u8) -> Result<()> { - let offset = self.len() as u32; - self.relocs.push(DebugReloc { - offset, - size, - name: DebugRelocName::Section(section), - addend: val as i64, - }); - self.write_udata(0, size) - } - - fn write_offset_at( - &mut self, - offset: usize, - val: usize, - section: SectionId, - size: u8, - ) -> Result<()> { - self.relocs.push(DebugReloc { - offset: offset as u32, - size, - name: DebugRelocName::Section(section), - addend: val as i64, - }); - self.write_udata_at(offset, 0, size) - } -}