wasmer_compiler_cranelift/
dwarf.rs1use gimli::write::{Address, EndianVec, Result, Writer};
2use gimli::{RunTimeEndian, SectionId, constants};
3use std::collections::HashMap;
4use wasmer_compiler::types::{
5 relocation::{Relocation, RelocationKind, RelocationTarget},
6 section::{CustomSection, CustomSectionProtection, SectionBody},
7};
8use wasmer_types::{LibCall, LocalFunctionIndex, entity::EntityRef, target::Endianness};
9
10#[derive(Clone, Debug)]
11pub struct WriterRelocate {
12 pub relocs: Vec<Relocation>,
13 writer: EndianVec<RunTimeEndian>,
14 lsda_symbols: HashMap<usize, (RelocationTarget, u32)>,
15}
16
17impl WriterRelocate {
18 pub const FUNCTION_SYMBOL: usize = 0;
19 pub const PERSONALITY_SYMBOL: usize = 1;
20 pub const LSDA_SYMBOL_BASE: usize = 2;
21
22 pub fn new(endianness: Option<Endianness>) -> Self {
23 let endianness = match endianness {
24 Some(Endianness::Little) => RunTimeEndian::Little,
25 Some(Endianness::Big) => RunTimeEndian::Big,
26 None => RunTimeEndian::default(),
28 };
29 Self {
30 relocs: Vec::new(),
31 writer: EndianVec::new(endianness),
32 lsda_symbols: HashMap::new(),
33 }
34 }
35
36 pub fn register_lsda_symbol(&mut self, symbol: usize, target: RelocationTarget, offset: u32) {
37 self.lsda_symbols.insert(symbol, (target, offset));
38 }
39
40 pub fn lsda_symbol(func_index: LocalFunctionIndex) -> usize {
41 Self::LSDA_SYMBOL_BASE + func_index.index()
42 }
43
44 pub fn into_section(mut self) -> CustomSection {
45 self.writer.write_u32(0).unwrap();
47 let data = self.writer.into_vec();
48 CustomSection {
49 protection: CustomSectionProtection::Read,
50 alignment: None,
51 bytes: SectionBody::new_with_vec(data),
52 relocations: self.relocs,
53 }
54 }
55}
56
57impl Writer for WriterRelocate {
58 type Endian = RunTimeEndian;
59
60 fn endian(&self) -> Self::Endian {
61 self.writer.endian()
62 }
63
64 fn len(&self) -> usize {
65 self.writer.len()
66 }
67
68 fn write(&mut self, bytes: &[u8]) -> Result<()> {
69 self.writer.write(bytes)
70 }
71
72 fn write_at(&mut self, offset: usize, bytes: &[u8]) -> Result<()> {
73 self.writer.write_at(offset, bytes)
74 }
75
76 fn write_address(&mut self, address: Address, size: u8) -> Result<()> {
77 match address {
78 Address::Constant(val) => self.write_udata(val, size),
79 Address::Symbol { symbol, addend } => {
80 if symbol == Self::FUNCTION_SYMBOL {
82 let function_index = LocalFunctionIndex::new(addend as _);
84 let reloc_target = RelocationTarget::LocalFunc(function_index);
85 let offset = self.len() as u32;
86 let kind = match size {
87 8 => RelocationKind::Abs8,
88 _ => unimplemented!("dwarf relocation size not yet supported: {}", size),
89 };
90 let addend = 0;
91 self.relocs.push(Relocation {
92 kind,
93 reloc_target,
94 offset,
95 addend,
96 });
97 self.write_udata(addend as _, size)
98 } else if symbol == Self::PERSONALITY_SYMBOL {
99 let offset = self.len() as u32;
100 let kind = match size {
101 4 => RelocationKind::Abs4,
102 8 => RelocationKind::Abs8,
103 other => unimplemented!(
104 "dwarf relocation size for personality not supported: {}",
105 other
106 ),
107 };
108 self.relocs.push(Relocation {
109 kind,
110 reloc_target: RelocationTarget::LibCall(LibCall::EHPersonality),
111 offset,
112 addend,
113 });
114 self.write_udata(0, size)
115 } else if let Some((target, base)) = self.lsda_symbols.get(&symbol) {
116 let offset = self.len() as u32;
117 let kind = match size {
118 4 => RelocationKind::Abs4,
119 8 => RelocationKind::Abs8,
120 other => unimplemented!(
121 "dwarf relocation size for LSDA not supported: {}",
122 other
123 ),
124 };
125 self.relocs.push(Relocation {
126 kind,
127 reloc_target: *target,
128 offset,
129 addend: *base as i64 + addend,
130 });
131 self.write_udata(0, size)
132 } else {
133 unreachable!("Symbol {} in DWARF not recognized", symbol);
134 }
135 }
136 }
137 }
138
139 fn write_eh_pointer(
140 &mut self,
141 address: Address,
142 eh_pe: constants::DwEhPe,
143 size: u8,
144 ) -> Result<()> {
145 if eh_pe == constants::DW_EH_PE_absptr {
146 self.write_address(address, size)
147 } else {
148 match address {
149 Address::Constant(_) => self.writer.write_eh_pointer(address, eh_pe, size),
150 Address::Symbol { .. } => {
151 unimplemented!("eh pointer encoding {eh_pe:?} not supported for symbol targets")
152 }
153 }
154 }
155 }
156
157 fn write_offset(&mut self, _val: usize, _section: SectionId, _size: u8) -> Result<()> {
158 unimplemented!("write_offset not yet implemented");
159 }
160
161 fn write_offset_at(
162 &mut self,
163 _offset: usize,
164 _val: usize,
165 _section: SectionId,
166 _size: u8,
167 ) -> Result<()> {
168 unimplemented!("write_offset_at not yet implemented");
169 }
170}