1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
pub use crate::transform::transform_dwarf; use gimli::write::{Address, Dwarf, EndianVec, FrameTable, Result, Sections, Writer}; use gimli::{RunTimeEndian, SectionId}; use wasmtime_environ::entity::EntityRef; use wasmtime_environ::isa::{unwind::UnwindInfo, TargetIsa}; use wasmtime_environ::{CompiledFunctions, DebugInfoData, ModuleMemoryOffset}; #[derive(Clone)] pub enum DwarfSectionRelocTarget { Func(usize), Section(&'static str), } #[derive(Clone)] pub struct DwarfSectionReloc { pub target: DwarfSectionRelocTarget, pub offset: u32, pub addend: i32, pub size: u8, } pub struct DwarfSection { pub name: &'static str, pub body: Vec<u8>, pub relocs: Vec<DwarfSectionReloc>, } fn emit_dwarf_sections( mut dwarf: Dwarf, frames: Option<FrameTable>, ) -> anyhow::Result<Vec<DwarfSection>> { let mut sections = Sections::new(WriterRelocate::default()); dwarf.write(&mut sections)?; if let Some(frames) = frames { frames.write_debug_frame(&mut sections.debug_frame)?; } let mut result = Vec::new(); sections.for_each_mut(|id, s| -> anyhow::Result<()> { let name = id.name(); let body = s.writer.take(); let mut relocs = vec![]; ::std::mem::swap(&mut relocs, &mut s.relocs); result.push(DwarfSection { name, body, relocs }); Ok(()) })?; Ok(result) } #[derive(Clone)] pub struct WriterRelocate { relocs: Vec<DwarfSectionReloc>, writer: EndianVec<RunTimeEndian>, } impl Default for WriterRelocate { fn default() -> Self { WriterRelocate { relocs: Vec::new(), writer: EndianVec::new(RunTimeEndian::Little), } } } 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 u32; self.relocs.push(DwarfSectionReloc { target: DwarfSectionRelocTarget::Func(symbol), offset, size, addend: addend as i32, }); self.write_udata(addend as u64, size) } } } fn write_offset(&mut self, val: usize, section: SectionId, size: u8) -> Result<()> { let offset = self.len() as u32; let target = DwarfSectionRelocTarget::Section(section.name()); self.relocs.push(DwarfSectionReloc { target, offset, size, addend: val as i32, }); self.write_udata(val as u64, size) } fn write_offset_at( &mut self, offset: usize, val: usize, section: SectionId, size: u8, ) -> Result<()> { let target = DwarfSectionRelocTarget::Section(section.name()); self.relocs.push(DwarfSectionReloc { target, offset: offset as u32, size, addend: val as i32, }); self.write_udata_at(offset, val as u64, size) } } fn create_frame_table<'a>(isa: &dyn TargetIsa, funcs: &CompiledFunctions) -> Option<FrameTable> { let mut table = FrameTable::default(); let cie_id = table.add_cie(isa.create_systemv_cie()?); for (i, f) in funcs { if let Some(UnwindInfo::SystemV(info)) = &f.unwind_info { table.add_fde( cie_id, info.to_fde(Address::Symbol { symbol: i.index(), addend: 0, }), ); } } Some(table) } pub fn emit_dwarf<'a>( isa: &dyn TargetIsa, debuginfo_data: &DebugInfoData, funcs: &CompiledFunctions, memory_offset: &ModuleMemoryOffset, ) -> anyhow::Result<Vec<DwarfSection>> { let dwarf = transform_dwarf(isa, debuginfo_data, funcs, memory_offset)?; let frame_table = create_frame_table(isa, funcs); let sections = emit_dwarf_sections(dwarf, frame_table)?; Ok(sections) }