wasmer_compiler_cranelift/
dwarf.rs

1use gimli::write::{Address, EndianVec, Result, Writer};
2use gimli::{RunTimeEndian, SectionId};
3use wasmer_compiler::types::{
4    relocation::{Relocation, RelocationKind, RelocationTarget},
5    section::{CustomSection, CustomSectionProtection, SectionBody},
6};
7use wasmer_types::{LocalFunctionIndex, entity::EntityRef, target::Endianness};
8
9#[derive(Clone, Debug)]
10pub struct WriterRelocate {
11    pub relocs: Vec<Relocation>,
12    writer: EndianVec<RunTimeEndian>,
13}
14
15impl WriterRelocate {
16    pub const FUNCTION_SYMBOL: usize = 0;
17    pub fn new(endianness: Option<Endianness>) -> Self {
18        let endianness = match endianness {
19            Some(Endianness::Little) => RunTimeEndian::Little,
20            Some(Endianness::Big) => RunTimeEndian::Big,
21            // We autodetect it, based on the host
22            None => RunTimeEndian::default(),
23        };
24        Self {
25            relocs: Vec::new(),
26            writer: EndianVec::new(endianness),
27        }
28    }
29
30    pub fn into_section(mut self) -> CustomSection {
31        // GCC expects a terminating "empty" length, so write a 0 length at the end of the table.
32        self.writer.write_u32(0).unwrap();
33        let data = self.writer.into_vec();
34        CustomSection {
35            protection: CustomSectionProtection::Read,
36            alignment: None,
37            bytes: SectionBody::new_with_vec(data),
38            relocations: self.relocs,
39        }
40    }
41}
42
43impl Writer for WriterRelocate {
44    type Endian = RunTimeEndian;
45
46    fn endian(&self) -> Self::Endian {
47        self.writer.endian()
48    }
49
50    fn len(&self) -> usize {
51        self.writer.len()
52    }
53
54    fn write(&mut self, bytes: &[u8]) -> Result<()> {
55        self.writer.write(bytes)
56    }
57
58    fn write_at(&mut self, offset: usize, bytes: &[u8]) -> Result<()> {
59        self.writer.write_at(offset, bytes)
60    }
61
62    fn write_address(&mut self, address: Address, size: u8) -> Result<()> {
63        match address {
64            Address::Constant(val) => self.write_udata(val, size),
65            Address::Symbol { symbol, addend } => {
66                // Is a function relocation
67                if symbol == Self::FUNCTION_SYMBOL {
68                    // We use the addend to detect the function index
69                    let function_index = LocalFunctionIndex::new(addend as _);
70                    let reloc_target = RelocationTarget::LocalFunc(function_index);
71                    let offset = self.len() as u32;
72                    let kind = match size {
73                        8 => RelocationKind::Abs8,
74                        _ => unimplemented!("dwarf relocation size not yet supported: {}", size),
75                    };
76                    let addend = 0;
77                    self.relocs.push(Relocation {
78                        kind,
79                        reloc_target,
80                        offset,
81                        addend,
82                    });
83                    self.write_udata(addend as _, size)
84                } else {
85                    unreachable!("Symbol {} in DWARF not recognized", symbol);
86                }
87            }
88        }
89    }
90
91    fn write_offset(&mut self, _val: usize, _section: SectionId, _size: u8) -> Result<()> {
92        unimplemented!("write_offset not yet implemented");
93    }
94
95    fn write_offset_at(
96        &mut self,
97        _offset: usize,
98        _val: usize,
99        _section: SectionId,
100        _size: u8,
101    ) -> Result<()> {
102        unimplemented!("write_offset_at not yet implemented");
103    }
104}