Path: blob/main/crates/cranelift/src/debug/write_debuginfo.rs
3057 views
use crate::debug::Compilation;1pub use crate::debug::transform::transform_dwarf;2use cranelift_codegen::ir::Endianness;3use cranelift_codegen::isa::{4TargetIsa,5unwind::{CfaUnwindInfo, UnwindInfo},6};7use gimli::write::{8Address, Dwarf, EndianVec, FrameTable, Result as WriteResult, Sections, Writer,9};10use gimli::{RunTimeEndian, SectionId};11use wasmtime_environ::error::Result as EnvResult;1213pub struct DwarfSection {14pub name: &'static str,15pub body: Vec<u8>,16pub relocs: Vec<DwarfSectionReloc>,17}1819#[derive(Clone)]20pub struct DwarfSectionReloc {21pub target: DwarfSectionRelocTarget,22pub offset: u32,23pub addend: i32,24pub size: u8,25}2627#[derive(Clone)]28pub enum DwarfSectionRelocTarget {29Func(usize),30Section(&'static str),31}3233fn emit_dwarf_sections(34isa: &dyn TargetIsa,35mut dwarf: Dwarf,36frames: Option<FrameTable>,37) -> EnvResult<Vec<DwarfSection>> {38let endian = match isa.endianness() {39Endianness::Little => RunTimeEndian::Little,40Endianness::Big => RunTimeEndian::Big,41};42let writer = WriterRelocate {43relocs: Vec::new(),44writer: EndianVec::new(endian),45};46let mut sections = Sections::new(writer);47dwarf.write(&mut sections)?;48if let Some(frames) = frames {49frames.write_debug_frame(&mut sections.debug_frame)?;50}5152let mut result = Vec::new();53sections.for_each_mut(|id, s| -> EnvResult<()> {54let name = id.name();55let body = s.writer.take();56if body.is_empty() {57return Ok(());58}59let mut relocs = vec![];60::std::mem::swap(&mut relocs, &mut s.relocs);61result.push(DwarfSection { name, body, relocs });62Ok(())63})?;6465Ok(result)66}6768#[derive(Clone)]69pub struct WriterRelocate {70relocs: Vec<DwarfSectionReloc>,71writer: EndianVec<RunTimeEndian>,72}7374impl Writer for WriterRelocate {75type Endian = RunTimeEndian;7677fn endian(&self) -> Self::Endian {78self.writer.endian()79}8081fn len(&self) -> usize {82self.writer.len()83}8485fn write(&mut self, bytes: &[u8]) -> WriteResult<()> {86self.writer.write(bytes)87}8889fn write_at(&mut self, offset: usize, bytes: &[u8]) -> WriteResult<()> {90self.writer.write_at(offset, bytes)91}9293fn write_address(&mut self, address: Address, size: u8) -> WriteResult<()> {94match address {95Address::Constant(val) => self.write_udata(val, size),96Address::Symbol { symbol, addend } => {97let offset = self.len() as u32;98self.relocs.push(DwarfSectionReloc {99target: DwarfSectionRelocTarget::Func(symbol),100offset,101size,102addend: addend as i32,103});104self.write_udata(addend as u64, size)105}106}107}108109fn write_offset(&mut self, val: usize, section: SectionId, size: u8) -> WriteResult<()> {110let offset = self.len() as u32;111let target = DwarfSectionRelocTarget::Section(section.name());112self.relocs.push(DwarfSectionReloc {113target,114offset,115size,116addend: val as i32,117});118self.write_udata(val as u64, size)119}120121fn write_offset_at(122&mut self,123offset: usize,124val: usize,125section: SectionId,126size: u8,127) -> WriteResult<()> {128let target = DwarfSectionRelocTarget::Section(section.name());129self.relocs.push(DwarfSectionReloc {130target,131offset: offset as u32,132size,133addend: val as i32,134});135self.write_udata_at(offset, val as u64, size)136}137}138139fn create_frame_table(140isa: &dyn TargetIsa,141compilation: &mut Compilation<'_>,142) -> Option<FrameTable> {143let mut table = FrameTable::default();144145let cie_id = table.add_cie(isa.create_systemv_cie()?);146147for (_, symbol, metadata) in compilation.functions() {148// The CFA-based unwind info will either be natively present, or we149// have generated it and placed into the "cfa_unwind_info" auxiliary150// field. We shouldn't emit both, though, it'd be wasteful.151let mut unwind_info: Option<&CfaUnwindInfo> = None;152if let Some(UnwindInfo::SystemV(info)) = &metadata.unwind_info {153debug_assert!(metadata.cfa_unwind_info.is_none());154unwind_info = Some(info);155} else if let Some(info) = &metadata.cfa_unwind_info {156unwind_info = Some(info);157}158159if let Some(info) = unwind_info {160table.add_fde(cie_id, info.to_fde(Address::Symbol { symbol, addend: 0 }));161}162}163164Some(table)165}166167pub fn emit_dwarf(168isa: &dyn TargetIsa,169compilation: &mut Compilation<'_>,170) -> EnvResult<Vec<DwarfSection>> {171let dwarf = transform_dwarf(isa, compilation)?;172let frame_table = create_frame_table(isa, compilation);173let sections = emit_dwarf_sections(isa, dwarf, frame_table)?;174Ok(sections)175}176177178