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