Coverage Report

Created: 2026-02-14 07:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/gimli-0.32.3/src/write/cfi.rs
Line
Count
Source
1
use alloc::vec::Vec;
2
use indexmap::IndexSet;
3
use std::ops::{Deref, DerefMut};
4
5
use crate::common::{DebugFrameOffset, EhFrameOffset, Encoding, Format, Register, SectionId};
6
use crate::constants;
7
use crate::write::{Address, BaseId, Error, Expression, Result, Section, Writer};
8
9
define_section!(
10
    DebugFrame,
11
    DebugFrameOffset,
12
    "A writable `.debug_frame` section."
13
);
14
15
define_section!(EhFrame, EhFrameOffset, "A writable `.eh_frame` section.");
16
17
define_id!(CieId, "An identifier for a CIE in a `FrameTable`.");
18
19
/// A table of frame description entries.
20
#[derive(Debug, Default)]
21
pub struct FrameTable {
22
    /// Base id for CIEs.
23
    base_id: BaseId,
24
    /// The common information entries.
25
    cies: IndexSet<CommonInformationEntry>,
26
    /// The frame description entries.
27
    fdes: Vec<(CieId, FrameDescriptionEntry)>,
28
}
29
30
impl FrameTable {
31
    /// Add a CIE and return its id.
32
    ///
33
    /// If the CIE already exists, then return the id of the existing CIE.
34
27.6k
    pub fn add_cie(&mut self, cie: CommonInformationEntry) -> CieId {
35
27.6k
        let (index, _) = self.cies.insert_full(cie);
36
27.6k
        CieId::new(self.base_id, index)
37
27.6k
    }
38
39
    /// The number of CIEs.
40
0
    pub fn cie_count(&self) -> usize {
41
0
        self.cies.len()
42
0
    }
43
44
    /// Add a FDE.
45
    ///
46
    /// Does not check for duplicates.
47
    ///
48
    /// # Panics
49
    ///
50
    /// Panics if the CIE id is invalid.
51
276k
    pub fn add_fde(&mut self, cie: CieId, fde: FrameDescriptionEntry) {
52
276k
        debug_assert_eq!(self.base_id, cie.base_id);
53
276k
        self.fdes.push((cie, fde));
54
276k
    }
55
56
    /// The number of FDEs.
57
0
    pub fn fde_count(&self) -> usize {
58
0
        self.fdes.len()
59
0
    }
60
61
    /// Write the frame table entries to the given `.debug_frame` section.
62
0
    pub fn write_debug_frame<W: Writer>(&self, w: &mut DebugFrame<W>) -> Result<()> {
63
0
        self.write(&mut w.0, false)
64
0
    }
65
66
    /// Write the frame table entries to the given `.eh_frame` section.
67
27.6k
    pub fn write_eh_frame<W: Writer>(&self, w: &mut EhFrame<W>) -> Result<()> {
68
27.6k
        self.write(&mut w.0, true)
69
27.6k
    }
<gimli::write::cfi::FrameTable>::write_eh_frame::<wasmer_compiler_cranelift::dwarf::WriterRelocate>
Line
Count
Source
67
7.79k
    pub fn write_eh_frame<W: Writer>(&self, w: &mut EhFrame<W>) -> Result<()> {
68
7.79k
        self.write(&mut w.0, true)
69
7.79k
    }
Unexecuted instantiation: <gimli::write::cfi::FrameTable>::write_eh_frame::<_>
<gimli::write::cfi::FrameTable>::write_eh_frame::<wasmer_compiler_singlepass::dwarf::WriterRelocate>
Line
Count
Source
67
67
    pub fn write_eh_frame<W: Writer>(&self, w: &mut EhFrame<W>) -> Result<()> {
68
67
        self.write(&mut w.0, true)
69
67
    }
<gimli::write::cfi::FrameTable>::write_eh_frame::<wasmer_compiler_cranelift::dwarf::WriterRelocate>
Line
Count
Source
67
11.9k
    pub fn write_eh_frame<W: Writer>(&self, w: &mut EhFrame<W>) -> Result<()> {
68
11.9k
        self.write(&mut w.0, true)
69
11.9k
    }
<gimli::write::cfi::FrameTable>::write_eh_frame::<wasmer_compiler_singlepass::dwarf::WriterRelocate>
Line
Count
Source
67
7.79k
    pub fn write_eh_frame<W: Writer>(&self, w: &mut EhFrame<W>) -> Result<()> {
68
7.79k
        self.write(&mut w.0, true)
69
7.79k
    }
70
71
27.6k
    fn write<W: Writer>(&self, w: &mut W, eh_frame: bool) -> Result<()> {
72
27.6k
        let mut cie_offsets = vec![None; self.cies.len()];
73
276k
        for (cie_id, fde) in &self.fdes {
74
276k
            let cie_index = cie_id.index;
75
276k
            let cie = self.cies.get_index(cie_index).unwrap();
76
276k
            let cie_offset = match cie_offsets[cie_index] {
77
249k
                Some(offset) => offset,
78
                None => {
79
                    // Only write CIEs as they are referenced.
80
27.6k
                    let offset = cie.write(w, eh_frame)?;
81
27.6k
                    cie_offsets[cie_index] = Some(offset);
82
27.6k
                    offset
83
                }
84
            };
85
86
276k
            fde.write(w, eh_frame, cie_offset, cie)?;
87
        }
88
        // TODO: write length 0 terminator for eh_frame?
89
27.6k
        Ok(())
90
27.6k
    }
<gimli::write::cfi::FrameTable>::write::<wasmer_compiler_cranelift::dwarf::WriterRelocate>
Line
Count
Source
71
7.79k
    fn write<W: Writer>(&self, w: &mut W, eh_frame: bool) -> Result<()> {
72
7.79k
        let mut cie_offsets = vec![None; self.cies.len()];
73
35.6k
        for (cie_id, fde) in &self.fdes {
74
35.6k
            let cie_index = cie_id.index;
75
35.6k
            let cie = self.cies.get_index(cie_index).unwrap();
76
35.6k
            let cie_offset = match cie_offsets[cie_index] {
77
27.8k
                Some(offset) => offset,
78
                None => {
79
                    // Only write CIEs as they are referenced.
80
7.79k
                    let offset = cie.write(w, eh_frame)?;
81
7.79k
                    cie_offsets[cie_index] = Some(offset);
82
7.79k
                    offset
83
                }
84
            };
85
86
35.6k
            fde.write(w, eh_frame, cie_offset, cie)?;
87
        }
88
        // TODO: write length 0 terminator for eh_frame?
89
7.79k
        Ok(())
90
7.79k
    }
Unexecuted instantiation: <gimli::write::cfi::FrameTable>::write::<_>
<gimli::write::cfi::FrameTable>::write::<wasmer_compiler_singlepass::dwarf::WriterRelocate>
Line
Count
Source
71
67
    fn write<W: Writer>(&self, w: &mut W, eh_frame: bool) -> Result<()> {
72
67
        let mut cie_offsets = vec![None; self.cies.len()];
73
10.1k
        for (cie_id, fde) in &self.fdes {
74
10.1k
            let cie_index = cie_id.index;
75
10.1k
            let cie = self.cies.get_index(cie_index).unwrap();
76
10.1k
            let cie_offset = match cie_offsets[cie_index] {
77
10.0k
                Some(offset) => offset,
78
                None => {
79
                    // Only write CIEs as they are referenced.
80
67
                    let offset = cie.write(w, eh_frame)?;
81
67
                    cie_offsets[cie_index] = Some(offset);
82
67
                    offset
83
                }
84
            };
85
86
10.1k
            fde.write(w, eh_frame, cie_offset, cie)?;
87
        }
88
        // TODO: write length 0 terminator for eh_frame?
89
67
        Ok(())
90
67
    }
<gimli::write::cfi::FrameTable>::write::<wasmer_compiler_cranelift::dwarf::WriterRelocate>
Line
Count
Source
71
11.9k
    fn write<W: Writer>(&self, w: &mut W, eh_frame: bool) -> Result<()> {
72
11.9k
        let mut cie_offsets = vec![None; self.cies.len()];
73
195k
        for (cie_id, fde) in &self.fdes {
74
195k
            let cie_index = cie_id.index;
75
195k
            let cie = self.cies.get_index(cie_index).unwrap();
76
195k
            let cie_offset = match cie_offsets[cie_index] {
77
183k
                Some(offset) => offset,
78
                None => {
79
                    // Only write CIEs as they are referenced.
80
11.9k
                    let offset = cie.write(w, eh_frame)?;
81
11.9k
                    cie_offsets[cie_index] = Some(offset);
82
11.9k
                    offset
83
                }
84
            };
85
86
195k
            fde.write(w, eh_frame, cie_offset, cie)?;
87
        }
88
        // TODO: write length 0 terminator for eh_frame?
89
11.9k
        Ok(())
90
11.9k
    }
<gimli::write::cfi::FrameTable>::write::<wasmer_compiler_singlepass::dwarf::WriterRelocate>
Line
Count
Source
71
7.79k
    fn write<W: Writer>(&self, w: &mut W, eh_frame: bool) -> Result<()> {
72
7.79k
        let mut cie_offsets = vec![None; self.cies.len()];
73
35.6k
        for (cie_id, fde) in &self.fdes {
74
35.6k
            let cie_index = cie_id.index;
75
35.6k
            let cie = self.cies.get_index(cie_index).unwrap();
76
35.6k
            let cie_offset = match cie_offsets[cie_index] {
77
27.8k
                Some(offset) => offset,
78
                None => {
79
                    // Only write CIEs as they are referenced.
80
7.79k
                    let offset = cie.write(w, eh_frame)?;
81
7.79k
                    cie_offsets[cie_index] = Some(offset);
82
7.79k
                    offset
83
                }
84
            };
85
86
35.6k
            fde.write(w, eh_frame, cie_offset, cie)?;
87
        }
88
        // TODO: write length 0 terminator for eh_frame?
89
7.79k
        Ok(())
90
7.79k
    }
91
}
92
93
/// A common information entry. This contains information that is shared between FDEs.
94
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
95
pub struct CommonInformationEntry {
96
    encoding: Encoding,
97
98
    /// A constant that is factored out of code offsets.
99
    ///
100
    /// This should be set to the minimum instruction length.
101
    /// Writing a code offset that is not a multiple of this factor will generate an error.
102
    code_alignment_factor: u8,
103
104
    /// A constant that is factored out of data offsets.
105
    ///
106
    /// This should be set to the minimum data alignment for the frame.
107
    /// Writing a data offset that is not a multiple of this factor will generate an error.
108
    data_alignment_factor: i8,
109
110
    /// The return address register. This might not correspond to an actual machine register.
111
    return_address_register: Register,
112
113
    /// The address of the personality function and its encoding.
114
    pub personality: Option<(constants::DwEhPe, Address)>,
115
116
    /// The encoding to use for the LSDA address in FDEs.
117
    ///
118
    /// If set then all FDEs which use this CIE must have a LSDA address.
119
    pub lsda_encoding: Option<constants::DwEhPe>,
120
121
    /// The encoding to use for addresses in FDEs.
122
    pub fde_address_encoding: constants::DwEhPe,
123
124
    /// True for signal trampolines.
125
    pub signal_trampoline: bool,
126
127
    /// The initial instructions upon entry to this function.
128
    instructions: Vec<CallFrameInstruction>,
129
}
130
131
impl CommonInformationEntry {
132
    /// Create a new common information entry.
133
    ///
134
    /// The encoding version must be a CFI version, not a DWARF version.
135
27.6k
    pub fn new(
136
27.6k
        encoding: Encoding,
137
27.6k
        code_alignment_factor: u8,
138
27.6k
        data_alignment_factor: i8,
139
27.6k
        return_address_register: Register,
140
27.6k
    ) -> Self {
141
27.6k
        CommonInformationEntry {
142
27.6k
            encoding,
143
27.6k
            code_alignment_factor,
144
27.6k
            data_alignment_factor,
145
27.6k
            return_address_register,
146
27.6k
            personality: None,
147
27.6k
            lsda_encoding: None,
148
27.6k
            fde_address_encoding: constants::DW_EH_PE_absptr,
149
27.6k
            signal_trampoline: false,
150
27.6k
            instructions: Vec::new(),
151
27.6k
        }
152
27.6k
    }
153
154
    /// Add an initial instruction.
155
55.2k
    pub fn add_instruction(&mut self, instruction: CallFrameInstruction) {
156
55.2k
        self.instructions.push(instruction);
157
55.2k
    }
158
159
304k
    fn has_augmentation(&self) -> bool {
160
304k
        self.personality.is_some()
161
53.7k
            || self.lsda_encoding.is_some()
162
53.7k
            || self.signal_trampoline
163
53.7k
            || self.fde_address_encoding != constants::DW_EH_PE_absptr
164
304k
    }
165
166
    /// Returns the section offset of the CIE.
167
27.6k
    fn write<W: Writer>(&self, w: &mut W, eh_frame: bool) -> Result<usize> {
168
27.6k
        let encoding = self.encoding;
169
27.6k
        let offset = w.len();
170
171
27.6k
        let length_offset = w.write_initial_length(encoding.format)?;
172
27.6k
        let length_base = w.len();
173
174
27.6k
        if eh_frame {
175
27.6k
            w.write_u32(0)?;
176
        } else {
177
0
            match encoding.format {
178
0
                Format::Dwarf32 => w.write_u32(0xffff_ffff)?,
179
0
                Format::Dwarf64 => w.write_u64(0xffff_ffff_ffff_ffff)?,
180
            }
181
        }
182
183
27.6k
        if eh_frame {
184
27.6k
            if encoding.version != 1 {
185
0
                return Err(Error::UnsupportedVersion(encoding.version));
186
27.6k
            };
187
        } else {
188
0
            match encoding.version {
189
0
                1 | 3 | 4 => {}
190
0
                _ => return Err(Error::UnsupportedVersion(encoding.version)),
191
            };
192
        }
193
27.6k
        w.write_u8(encoding.version as u8)?;
194
195
27.6k
        let augmentation = self.has_augmentation();
196
27.6k
        if augmentation {
197
19.7k
            w.write_u8(b'z')?;
198
19.7k
            if self.lsda_encoding.is_some() {
199
19.7k
                w.write_u8(b'L')?;
200
0
            }
201
19.7k
            if self.personality.is_some() {
202
19.7k
                w.write_u8(b'P')?;
203
0
            }
204
19.7k
            if self.fde_address_encoding != constants::DW_EH_PE_absptr {
205
0
                w.write_u8(b'R')?;
206
19.7k
            }
207
19.7k
            if self.signal_trampoline {
208
0
                w.write_u8(b'S')?;
209
19.7k
            }
210
7.86k
        }
211
27.6k
        w.write_u8(0)?;
212
213
27.6k
        if encoding.version >= 4 {
214
0
            w.write_u8(encoding.address_size)?;
215
0
            w.write_u8(0)?; // segment_selector_size
216
27.6k
        }
217
218
27.6k
        w.write_uleb128(self.code_alignment_factor.into())?;
219
27.6k
        w.write_sleb128(self.data_alignment_factor.into())?;
220
221
27.6k
        if !eh_frame && encoding.version == 1 {
222
0
            let register = self.return_address_register.0 as u8;
223
0
            if u16::from(register) != self.return_address_register.0 {
224
0
                return Err(Error::ValueTooLarge);
225
0
            }
226
0
            w.write_u8(register)?;
227
        } else {
228
27.6k
            w.write_uleb128(self.return_address_register.0.into())?;
229
        }
230
231
27.6k
        if augmentation {
232
19.7k
            let augmentation_length_offset = w.len();
233
19.7k
            w.write_u8(0)?;
234
19.7k
            let augmentation_length_base = w.len();
235
236
19.7k
            if let Some(eh_pe) = self.lsda_encoding {
237
19.7k
                w.write_u8(eh_pe.0)?;
238
0
            }
239
19.7k
            if let Some((eh_pe, address)) = self.personality {
240
19.7k
                w.write_u8(eh_pe.0)?;
241
19.7k
                w.write_eh_pointer(address, eh_pe, encoding.address_size)?;
242
0
            }
243
19.7k
            if self.fde_address_encoding != constants::DW_EH_PE_absptr {
244
0
                w.write_u8(self.fde_address_encoding.0)?;
245
19.7k
            }
246
247
19.7k
            let augmentation_length = (w.len() - augmentation_length_base) as u64;
248
19.7k
            debug_assert!(augmentation_length < 0x80);
249
19.7k
            w.write_udata_at(augmentation_length_offset, augmentation_length, 1)?;
250
7.86k
        }
251
252
55.2k
        for instruction in &self.instructions {
253
55.2k
            instruction.write(w, encoding, self)?;
254
        }
255
256
27.6k
        write_nop(
257
27.6k
            w,
258
27.6k
            encoding.format.word_size() as usize + w.len() - length_base,
259
27.6k
            encoding.address_size,
260
0
        )?;
261
262
27.6k
        let length = (w.len() - length_base) as u64;
263
27.6k
        w.write_initial_length_at(length_offset, length, encoding.format)?;
264
265
27.6k
        Ok(offset)
266
27.6k
    }
<gimli::write::cfi::CommonInformationEntry>::write::<wasmer_compiler_cranelift::dwarf::WriterRelocate>
Line
Count
Source
167
7.79k
    fn write<W: Writer>(&self, w: &mut W, eh_frame: bool) -> Result<usize> {
168
7.79k
        let encoding = self.encoding;
169
7.79k
        let offset = w.len();
170
171
7.79k
        let length_offset = w.write_initial_length(encoding.format)?;
172
7.79k
        let length_base = w.len();
173
174
7.79k
        if eh_frame {
175
7.79k
            w.write_u32(0)?;
176
        } else {
177
0
            match encoding.format {
178
0
                Format::Dwarf32 => w.write_u32(0xffff_ffff)?,
179
0
                Format::Dwarf64 => w.write_u64(0xffff_ffff_ffff_ffff)?,
180
            }
181
        }
182
183
7.79k
        if eh_frame {
184
7.79k
            if encoding.version != 1 {
185
0
                return Err(Error::UnsupportedVersion(encoding.version));
186
7.79k
            };
187
        } else {
188
0
            match encoding.version {
189
0
                1 | 3 | 4 => {}
190
0
                _ => return Err(Error::UnsupportedVersion(encoding.version)),
191
            };
192
        }
193
7.79k
        w.write_u8(encoding.version as u8)?;
194
195
7.79k
        let augmentation = self.has_augmentation();
196
7.79k
        if augmentation {
197
7.79k
            w.write_u8(b'z')?;
198
7.79k
            if self.lsda_encoding.is_some() {
199
7.79k
                w.write_u8(b'L')?;
200
0
            }
201
7.79k
            if self.personality.is_some() {
202
7.79k
                w.write_u8(b'P')?;
203
0
            }
204
7.79k
            if self.fde_address_encoding != constants::DW_EH_PE_absptr {
205
0
                w.write_u8(b'R')?;
206
7.79k
            }
207
7.79k
            if self.signal_trampoline {
208
0
                w.write_u8(b'S')?;
209
7.79k
            }
210
0
        }
211
7.79k
        w.write_u8(0)?;
212
213
7.79k
        if encoding.version >= 4 {
214
0
            w.write_u8(encoding.address_size)?;
215
0
            w.write_u8(0)?; // segment_selector_size
216
7.79k
        }
217
218
7.79k
        w.write_uleb128(self.code_alignment_factor.into())?;
219
7.79k
        w.write_sleb128(self.data_alignment_factor.into())?;
220
221
7.79k
        if !eh_frame && encoding.version == 1 {
222
0
            let register = self.return_address_register.0 as u8;
223
0
            if u16::from(register) != self.return_address_register.0 {
224
0
                return Err(Error::ValueTooLarge);
225
0
            }
226
0
            w.write_u8(register)?;
227
        } else {
228
7.79k
            w.write_uleb128(self.return_address_register.0.into())?;
229
        }
230
231
7.79k
        if augmentation {
232
7.79k
            let augmentation_length_offset = w.len();
233
7.79k
            w.write_u8(0)?;
234
7.79k
            let augmentation_length_base = w.len();
235
236
7.79k
            if let Some(eh_pe) = self.lsda_encoding {
237
7.79k
                w.write_u8(eh_pe.0)?;
238
0
            }
239
7.79k
            if let Some((eh_pe, address)) = self.personality {
240
7.79k
                w.write_u8(eh_pe.0)?;
241
7.79k
                w.write_eh_pointer(address, eh_pe, encoding.address_size)?;
242
0
            }
243
7.79k
            if self.fde_address_encoding != constants::DW_EH_PE_absptr {
244
0
                w.write_u8(self.fde_address_encoding.0)?;
245
7.79k
            }
246
247
7.79k
            let augmentation_length = (w.len() - augmentation_length_base) as u64;
248
7.79k
            debug_assert!(augmentation_length < 0x80);
249
7.79k
            w.write_udata_at(augmentation_length_offset, augmentation_length, 1)?;
250
0
        }
251
252
15.5k
        for instruction in &self.instructions {
253
15.5k
            instruction.write(w, encoding, self)?;
254
        }
255
256
7.79k
        write_nop(
257
7.79k
            w,
258
7.79k
            encoding.format.word_size() as usize + w.len() - length_base,
259
7.79k
            encoding.address_size,
260
0
        )?;
261
262
7.79k
        let length = (w.len() - length_base) as u64;
263
7.79k
        w.write_initial_length_at(length_offset, length, encoding.format)?;
264
265
7.79k
        Ok(offset)
266
7.79k
    }
Unexecuted instantiation: <gimli::write::cfi::CommonInformationEntry>::write::<_>
<gimli::write::cfi::CommonInformationEntry>::write::<wasmer_compiler_singlepass::dwarf::WriterRelocate>
Line
Count
Source
167
67
    fn write<W: Writer>(&self, w: &mut W, eh_frame: bool) -> Result<usize> {
168
67
        let encoding = self.encoding;
169
67
        let offset = w.len();
170
171
67
        let length_offset = w.write_initial_length(encoding.format)?;
172
67
        let length_base = w.len();
173
174
67
        if eh_frame {
175
67
            w.write_u32(0)?;
176
        } else {
177
0
            match encoding.format {
178
0
                Format::Dwarf32 => w.write_u32(0xffff_ffff)?,
179
0
                Format::Dwarf64 => w.write_u64(0xffff_ffff_ffff_ffff)?,
180
            }
181
        }
182
183
67
        if eh_frame {
184
67
            if encoding.version != 1 {
185
0
                return Err(Error::UnsupportedVersion(encoding.version));
186
67
            };
187
        } else {
188
0
            match encoding.version {
189
0
                1 | 3 | 4 => {}
190
0
                _ => return Err(Error::UnsupportedVersion(encoding.version)),
191
            };
192
        }
193
67
        w.write_u8(encoding.version as u8)?;
194
195
67
        let augmentation = self.has_augmentation();
196
67
        if augmentation {
197
0
            w.write_u8(b'z')?;
198
0
            if self.lsda_encoding.is_some() {
199
0
                w.write_u8(b'L')?;
200
0
            }
201
0
            if self.personality.is_some() {
202
0
                w.write_u8(b'P')?;
203
0
            }
204
0
            if self.fde_address_encoding != constants::DW_EH_PE_absptr {
205
0
                w.write_u8(b'R')?;
206
0
            }
207
0
            if self.signal_trampoline {
208
0
                w.write_u8(b'S')?;
209
0
            }
210
67
        }
211
67
        w.write_u8(0)?;
212
213
67
        if encoding.version >= 4 {
214
0
            w.write_u8(encoding.address_size)?;
215
0
            w.write_u8(0)?; // segment_selector_size
216
67
        }
217
218
67
        w.write_uleb128(self.code_alignment_factor.into())?;
219
67
        w.write_sleb128(self.data_alignment_factor.into())?;
220
221
67
        if !eh_frame && encoding.version == 1 {
222
0
            let register = self.return_address_register.0 as u8;
223
0
            if u16::from(register) != self.return_address_register.0 {
224
0
                return Err(Error::ValueTooLarge);
225
0
            }
226
0
            w.write_u8(register)?;
227
        } else {
228
67
            w.write_uleb128(self.return_address_register.0.into())?;
229
        }
230
231
67
        if augmentation {
232
0
            let augmentation_length_offset = w.len();
233
0
            w.write_u8(0)?;
234
0
            let augmentation_length_base = w.len();
235
236
0
            if let Some(eh_pe) = self.lsda_encoding {
237
0
                w.write_u8(eh_pe.0)?;
238
0
            }
239
0
            if let Some((eh_pe, address)) = self.personality {
240
0
                w.write_u8(eh_pe.0)?;
241
0
                w.write_eh_pointer(address, eh_pe, encoding.address_size)?;
242
0
            }
243
0
            if self.fde_address_encoding != constants::DW_EH_PE_absptr {
244
0
                w.write_u8(self.fde_address_encoding.0)?;
245
0
            }
246
247
0
            let augmentation_length = (w.len() - augmentation_length_base) as u64;
248
0
            debug_assert!(augmentation_length < 0x80);
249
0
            w.write_udata_at(augmentation_length_offset, augmentation_length, 1)?;
250
67
        }
251
252
134
        for instruction in &self.instructions {
253
134
            instruction.write(w, encoding, self)?;
254
        }
255
256
67
        write_nop(
257
67
            w,
258
67
            encoding.format.word_size() as usize + w.len() - length_base,
259
67
            encoding.address_size,
260
0
        )?;
261
262
67
        let length = (w.len() - length_base) as u64;
263
67
        w.write_initial_length_at(length_offset, length, encoding.format)?;
264
265
67
        Ok(offset)
266
67
    }
<gimli::write::cfi::CommonInformationEntry>::write::<wasmer_compiler_cranelift::dwarf::WriterRelocate>
Line
Count
Source
167
11.9k
    fn write<W: Writer>(&self, w: &mut W, eh_frame: bool) -> Result<usize> {
168
11.9k
        let encoding = self.encoding;
169
11.9k
        let offset = w.len();
170
171
11.9k
        let length_offset = w.write_initial_length(encoding.format)?;
172
11.9k
        let length_base = w.len();
173
174
11.9k
        if eh_frame {
175
11.9k
            w.write_u32(0)?;
176
        } else {
177
0
            match encoding.format {
178
0
                Format::Dwarf32 => w.write_u32(0xffff_ffff)?,
179
0
                Format::Dwarf64 => w.write_u64(0xffff_ffff_ffff_ffff)?,
180
            }
181
        }
182
183
11.9k
        if eh_frame {
184
11.9k
            if encoding.version != 1 {
185
0
                return Err(Error::UnsupportedVersion(encoding.version));
186
11.9k
            };
187
        } else {
188
0
            match encoding.version {
189
0
                1 | 3 | 4 => {}
190
0
                _ => return Err(Error::UnsupportedVersion(encoding.version)),
191
            };
192
        }
193
11.9k
        w.write_u8(encoding.version as u8)?;
194
195
11.9k
        let augmentation = self.has_augmentation();
196
11.9k
        if augmentation {
197
11.9k
            w.write_u8(b'z')?;
198
11.9k
            if self.lsda_encoding.is_some() {
199
11.9k
                w.write_u8(b'L')?;
200
0
            }
201
11.9k
            if self.personality.is_some() {
202
11.9k
                w.write_u8(b'P')?;
203
0
            }
204
11.9k
            if self.fde_address_encoding != constants::DW_EH_PE_absptr {
205
0
                w.write_u8(b'R')?;
206
11.9k
            }
207
11.9k
            if self.signal_trampoline {
208
0
                w.write_u8(b'S')?;
209
11.9k
            }
210
0
        }
211
11.9k
        w.write_u8(0)?;
212
213
11.9k
        if encoding.version >= 4 {
214
0
            w.write_u8(encoding.address_size)?;
215
0
            w.write_u8(0)?; // segment_selector_size
216
11.9k
        }
217
218
11.9k
        w.write_uleb128(self.code_alignment_factor.into())?;
219
11.9k
        w.write_sleb128(self.data_alignment_factor.into())?;
220
221
11.9k
        if !eh_frame && encoding.version == 1 {
222
0
            let register = self.return_address_register.0 as u8;
223
0
            if u16::from(register) != self.return_address_register.0 {
224
0
                return Err(Error::ValueTooLarge);
225
0
            }
226
0
            w.write_u8(register)?;
227
        } else {
228
11.9k
            w.write_uleb128(self.return_address_register.0.into())?;
229
        }
230
231
11.9k
        if augmentation {
232
11.9k
            let augmentation_length_offset = w.len();
233
11.9k
            w.write_u8(0)?;
234
11.9k
            let augmentation_length_base = w.len();
235
236
11.9k
            if let Some(eh_pe) = self.lsda_encoding {
237
11.9k
                w.write_u8(eh_pe.0)?;
238
0
            }
239
11.9k
            if let Some((eh_pe, address)) = self.personality {
240
11.9k
                w.write_u8(eh_pe.0)?;
241
11.9k
                w.write_eh_pointer(address, eh_pe, encoding.address_size)?;
242
0
            }
243
11.9k
            if self.fde_address_encoding != constants::DW_EH_PE_absptr {
244
0
                w.write_u8(self.fde_address_encoding.0)?;
245
11.9k
            }
246
247
11.9k
            let augmentation_length = (w.len() - augmentation_length_base) as u64;
248
11.9k
            debug_assert!(augmentation_length < 0x80);
249
11.9k
            w.write_udata_at(augmentation_length_offset, augmentation_length, 1)?;
250
0
        }
251
252
23.9k
        for instruction in &self.instructions {
253
23.9k
            instruction.write(w, encoding, self)?;
254
        }
255
256
11.9k
        write_nop(
257
11.9k
            w,
258
11.9k
            encoding.format.word_size() as usize + w.len() - length_base,
259
11.9k
            encoding.address_size,
260
0
        )?;
261
262
11.9k
        let length = (w.len() - length_base) as u64;
263
11.9k
        w.write_initial_length_at(length_offset, length, encoding.format)?;
264
265
11.9k
        Ok(offset)
266
11.9k
    }
<gimli::write::cfi::CommonInformationEntry>::write::<wasmer_compiler_singlepass::dwarf::WriterRelocate>
Line
Count
Source
167
7.79k
    fn write<W: Writer>(&self, w: &mut W, eh_frame: bool) -> Result<usize> {
168
7.79k
        let encoding = self.encoding;
169
7.79k
        let offset = w.len();
170
171
7.79k
        let length_offset = w.write_initial_length(encoding.format)?;
172
7.79k
        let length_base = w.len();
173
174
7.79k
        if eh_frame {
175
7.79k
            w.write_u32(0)?;
176
        } else {
177
0
            match encoding.format {
178
0
                Format::Dwarf32 => w.write_u32(0xffff_ffff)?,
179
0
                Format::Dwarf64 => w.write_u64(0xffff_ffff_ffff_ffff)?,
180
            }
181
        }
182
183
7.79k
        if eh_frame {
184
7.79k
            if encoding.version != 1 {
185
0
                return Err(Error::UnsupportedVersion(encoding.version));
186
7.79k
            };
187
        } else {
188
0
            match encoding.version {
189
0
                1 | 3 | 4 => {}
190
0
                _ => return Err(Error::UnsupportedVersion(encoding.version)),
191
            };
192
        }
193
7.79k
        w.write_u8(encoding.version as u8)?;
194
195
7.79k
        let augmentation = self.has_augmentation();
196
7.79k
        if augmentation {
197
0
            w.write_u8(b'z')?;
198
0
            if self.lsda_encoding.is_some() {
199
0
                w.write_u8(b'L')?;
200
0
            }
201
0
            if self.personality.is_some() {
202
0
                w.write_u8(b'P')?;
203
0
            }
204
0
            if self.fde_address_encoding != constants::DW_EH_PE_absptr {
205
0
                w.write_u8(b'R')?;
206
0
            }
207
0
            if self.signal_trampoline {
208
0
                w.write_u8(b'S')?;
209
0
            }
210
7.79k
        }
211
7.79k
        w.write_u8(0)?;
212
213
7.79k
        if encoding.version >= 4 {
214
0
            w.write_u8(encoding.address_size)?;
215
0
            w.write_u8(0)?; // segment_selector_size
216
7.79k
        }
217
218
7.79k
        w.write_uleb128(self.code_alignment_factor.into())?;
219
7.79k
        w.write_sleb128(self.data_alignment_factor.into())?;
220
221
7.79k
        if !eh_frame && encoding.version == 1 {
222
0
            let register = self.return_address_register.0 as u8;
223
0
            if u16::from(register) != self.return_address_register.0 {
224
0
                return Err(Error::ValueTooLarge);
225
0
            }
226
0
            w.write_u8(register)?;
227
        } else {
228
7.79k
            w.write_uleb128(self.return_address_register.0.into())?;
229
        }
230
231
7.79k
        if augmentation {
232
0
            let augmentation_length_offset = w.len();
233
0
            w.write_u8(0)?;
234
0
            let augmentation_length_base = w.len();
235
236
0
            if let Some(eh_pe) = self.lsda_encoding {
237
0
                w.write_u8(eh_pe.0)?;
238
0
            }
239
0
            if let Some((eh_pe, address)) = self.personality {
240
0
                w.write_u8(eh_pe.0)?;
241
0
                w.write_eh_pointer(address, eh_pe, encoding.address_size)?;
242
0
            }
243
0
            if self.fde_address_encoding != constants::DW_EH_PE_absptr {
244
0
                w.write_u8(self.fde_address_encoding.0)?;
245
0
            }
246
247
0
            let augmentation_length = (w.len() - augmentation_length_base) as u64;
248
0
            debug_assert!(augmentation_length < 0x80);
249
0
            w.write_udata_at(augmentation_length_offset, augmentation_length, 1)?;
250
7.79k
        }
251
252
15.5k
        for instruction in &self.instructions {
253
15.5k
            instruction.write(w, encoding, self)?;
254
        }
255
256
7.79k
        write_nop(
257
7.79k
            w,
258
7.79k
            encoding.format.word_size() as usize + w.len() - length_base,
259
7.79k
            encoding.address_size,
260
0
        )?;
261
262
7.79k
        let length = (w.len() - length_base) as u64;
263
7.79k
        w.write_initial_length_at(length_offset, length, encoding.format)?;
264
265
7.79k
        Ok(offset)
266
7.79k
    }
267
}
268
269
/// A frame description entry. There should be one FDE per function.
270
#[derive(Debug, Clone, PartialEq, Eq)]
271
pub struct FrameDescriptionEntry {
272
    /// The initial address of the function.
273
    address: Address,
274
275
    /// The length in bytes of the function.
276
    length: u32,
277
278
    /// The address of the LSDA.
279
    pub lsda: Option<Address>,
280
281
    /// The instructions for this function, ordered by offset.
282
    instructions: Vec<(u32, CallFrameInstruction)>,
283
}
284
285
impl FrameDescriptionEntry {
286
    /// Create a new frame description entry for a function.
287
276k
    pub fn new(address: Address, length: u32) -> Self {
288
276k
        FrameDescriptionEntry {
289
276k
            address,
290
276k
            length,
291
276k
            lsda: None,
292
276k
            instructions: Vec::new(),
293
276k
        }
294
276k
    }
295
296
    /// Add an instruction.
297
    ///
298
    /// Instructions must be added in increasing order of offset, or writing will fail.
299
1.08M
    pub fn add_instruction(&mut self, offset: u32, instruction: CallFrameInstruction) {
300
1.08M
        debug_assert!(self.instructions.last().map(|x| x.0).unwrap_or(0) <= offset);
301
1.08M
        self.instructions.push((offset, instruction));
302
1.08M
    }
303
304
276k
    fn write<W: Writer>(
305
276k
        &self,
306
276k
        w: &mut W,
307
276k
        eh_frame: bool,
308
276k
        cie_offset: usize,
309
276k
        cie: &CommonInformationEntry,
310
276k
    ) -> Result<()> {
311
276k
        let encoding = cie.encoding;
312
276k
        let length_offset = w.write_initial_length(encoding.format)?;
313
276k
        let length_base = w.len();
314
315
276k
        if eh_frame {
316
            // .eh_frame uses a relative offset which doesn't need relocation.
317
276k
            w.write_udata((w.len() - cie_offset) as u64, 4)?;
318
        } else {
319
0
            w.write_offset(
320
0
                cie_offset,
321
0
                SectionId::DebugFrame,
322
0
                encoding.format.word_size(),
323
0
            )?;
324
        }
325
326
276k
        if cie.fde_address_encoding != constants::DW_EH_PE_absptr {
327
0
            w.write_eh_pointer(
328
0
                self.address,
329
0
                cie.fde_address_encoding,
330
0
                encoding.address_size,
331
0
            )?;
332
0
            w.write_eh_pointer_data(
333
0
                self.length.into(),
334
0
                cie.fde_address_encoding.format(),
335
0
                encoding.address_size,
336
0
            )?;
337
        } else {
338
276k
            w.write_address(self.address, encoding.address_size)?;
339
276k
            w.write_udata(self.length.into(), encoding.address_size)?;
340
        }
341
342
276k
        if cie.has_augmentation() {
343
231k
            let augmentation_length_offset = w.len();
344
231k
            w.write_u8(0)?;
345
231k
            let augmentation_length_base = w.len();
346
347
231k
            debug_assert_eq!(self.lsda.is_some(), cie.lsda_encoding.is_some());
348
231k
            if let (Some(lsda), Some(lsda_encoding)) = (self.lsda, cie.lsda_encoding) {
349
231k
                w.write_eh_pointer(lsda, lsda_encoding, encoding.address_size)?;
350
0
            }
351
352
231k
            let augmentation_length = (w.len() - augmentation_length_base) as u64;
353
231k
            debug_assert!(augmentation_length < 0x80);
354
231k
            w.write_udata_at(augmentation_length_offset, augmentation_length, 1)?;
355
45.8k
        }
356
357
276k
        let mut prev_offset = 0;
358
1.08M
        for (offset, instruction) in &self.instructions {
359
1.08M
            write_advance_loc(w, cie.code_alignment_factor, prev_offset, *offset)?;
360
1.08M
            prev_offset = *offset;
361
1.08M
            instruction.write(w, encoding, cie)?;
362
        }
363
364
276k
        write_nop(
365
276k
            w,
366
276k
            encoding.format.word_size() as usize + w.len() - length_base,
367
276k
            encoding.address_size,
368
0
        )?;
369
370
276k
        let length = (w.len() - length_base) as u64;
371
276k
        w.write_initial_length_at(length_offset, length, encoding.format)?;
372
373
276k
        Ok(())
374
276k
    }
<gimli::write::cfi::FrameDescriptionEntry>::write::<wasmer_compiler_cranelift::dwarf::WriterRelocate>
Line
Count
Source
304
35.6k
    fn write<W: Writer>(
305
35.6k
        &self,
306
35.6k
        w: &mut W,
307
35.6k
        eh_frame: bool,
308
35.6k
        cie_offset: usize,
309
35.6k
        cie: &CommonInformationEntry,
310
35.6k
    ) -> Result<()> {
311
35.6k
        let encoding = cie.encoding;
312
35.6k
        let length_offset = w.write_initial_length(encoding.format)?;
313
35.6k
        let length_base = w.len();
314
315
35.6k
        if eh_frame {
316
            // .eh_frame uses a relative offset which doesn't need relocation.
317
35.6k
            w.write_udata((w.len() - cie_offset) as u64, 4)?;
318
        } else {
319
0
            w.write_offset(
320
0
                cie_offset,
321
0
                SectionId::DebugFrame,
322
0
                encoding.format.word_size(),
323
0
            )?;
324
        }
325
326
35.6k
        if cie.fde_address_encoding != constants::DW_EH_PE_absptr {
327
0
            w.write_eh_pointer(
328
0
                self.address,
329
0
                cie.fde_address_encoding,
330
0
                encoding.address_size,
331
0
            )?;
332
0
            w.write_eh_pointer_data(
333
0
                self.length.into(),
334
0
                cie.fde_address_encoding.format(),
335
0
                encoding.address_size,
336
0
            )?;
337
        } else {
338
35.6k
            w.write_address(self.address, encoding.address_size)?;
339
35.6k
            w.write_udata(self.length.into(), encoding.address_size)?;
340
        }
341
342
35.6k
        if cie.has_augmentation() {
343
35.6k
            let augmentation_length_offset = w.len();
344
35.6k
            w.write_u8(0)?;
345
35.6k
            let augmentation_length_base = w.len();
346
347
35.6k
            debug_assert_eq!(self.lsda.is_some(), cie.lsda_encoding.is_some());
348
35.6k
            if let (Some(lsda), Some(lsda_encoding)) = (self.lsda, cie.lsda_encoding) {
349
35.6k
                w.write_eh_pointer(lsda, lsda_encoding, encoding.address_size)?;
350
0
            }
351
352
35.6k
            let augmentation_length = (w.len() - augmentation_length_base) as u64;
353
35.6k
            debug_assert!(augmentation_length < 0x80);
354
35.6k
            w.write_udata_at(augmentation_length_offset, augmentation_length, 1)?;
355
0
        }
356
357
35.6k
        let mut prev_offset = 0;
358
115k
        for (offset, instruction) in &self.instructions {
359
115k
            write_advance_loc(w, cie.code_alignment_factor, prev_offset, *offset)?;
360
115k
            prev_offset = *offset;
361
115k
            instruction.write(w, encoding, cie)?;
362
        }
363
364
35.6k
        write_nop(
365
35.6k
            w,
366
35.6k
            encoding.format.word_size() as usize + w.len() - length_base,
367
35.6k
            encoding.address_size,
368
0
        )?;
369
370
35.6k
        let length = (w.len() - length_base) as u64;
371
35.6k
        w.write_initial_length_at(length_offset, length, encoding.format)?;
372
373
35.6k
        Ok(())
374
35.6k
    }
Unexecuted instantiation: <gimli::write::cfi::FrameDescriptionEntry>::write::<_>
<gimli::write::cfi::FrameDescriptionEntry>::write::<wasmer_compiler_singlepass::dwarf::WriterRelocate>
Line
Count
Source
304
10.1k
    fn write<W: Writer>(
305
10.1k
        &self,
306
10.1k
        w: &mut W,
307
10.1k
        eh_frame: bool,
308
10.1k
        cie_offset: usize,
309
10.1k
        cie: &CommonInformationEntry,
310
10.1k
    ) -> Result<()> {
311
10.1k
        let encoding = cie.encoding;
312
10.1k
        let length_offset = w.write_initial_length(encoding.format)?;
313
10.1k
        let length_base = w.len();
314
315
10.1k
        if eh_frame {
316
            // .eh_frame uses a relative offset which doesn't need relocation.
317
10.1k
            w.write_udata((w.len() - cie_offset) as u64, 4)?;
318
        } else {
319
0
            w.write_offset(
320
0
                cie_offset,
321
0
                SectionId::DebugFrame,
322
0
                encoding.format.word_size(),
323
0
            )?;
324
        }
325
326
10.1k
        if cie.fde_address_encoding != constants::DW_EH_PE_absptr {
327
0
            w.write_eh_pointer(
328
0
                self.address,
329
0
                cie.fde_address_encoding,
330
0
                encoding.address_size,
331
0
            )?;
332
0
            w.write_eh_pointer_data(
333
0
                self.length.into(),
334
0
                cie.fde_address_encoding.format(),
335
0
                encoding.address_size,
336
0
            )?;
337
        } else {
338
10.1k
            w.write_address(self.address, encoding.address_size)?;
339
10.1k
            w.write_udata(self.length.into(), encoding.address_size)?;
340
        }
341
342
10.1k
        if cie.has_augmentation() {
343
0
            let augmentation_length_offset = w.len();
344
0
            w.write_u8(0)?;
345
0
            let augmentation_length_base = w.len();
346
347
0
            debug_assert_eq!(self.lsda.is_some(), cie.lsda_encoding.is_some());
348
0
            if let (Some(lsda), Some(lsda_encoding)) = (self.lsda, cie.lsda_encoding) {
349
0
                w.write_eh_pointer(lsda, lsda_encoding, encoding.address_size)?;
350
0
            }
351
352
0
            let augmentation_length = (w.len() - augmentation_length_base) as u64;
353
0
            debug_assert!(augmentation_length < 0x80);
354
0
            w.write_udata_at(augmentation_length_offset, augmentation_length, 1)?;
355
10.1k
        }
356
357
10.1k
        let mut prev_offset = 0;
358
80.5k
        for (offset, instruction) in &self.instructions {
359
80.5k
            write_advance_loc(w, cie.code_alignment_factor, prev_offset, *offset)?;
360
80.5k
            prev_offset = *offset;
361
80.5k
            instruction.write(w, encoding, cie)?;
362
        }
363
364
10.1k
        write_nop(
365
10.1k
            w,
366
10.1k
            encoding.format.word_size() as usize + w.len() - length_base,
367
10.1k
            encoding.address_size,
368
0
        )?;
369
370
10.1k
        let length = (w.len() - length_base) as u64;
371
10.1k
        w.write_initial_length_at(length_offset, length, encoding.format)?;
372
373
10.1k
        Ok(())
374
10.1k
    }
<gimli::write::cfi::FrameDescriptionEntry>::write::<wasmer_compiler_cranelift::dwarf::WriterRelocate>
Line
Count
Source
304
195k
    fn write<W: Writer>(
305
195k
        &self,
306
195k
        w: &mut W,
307
195k
        eh_frame: bool,
308
195k
        cie_offset: usize,
309
195k
        cie: &CommonInformationEntry,
310
195k
    ) -> Result<()> {
311
195k
        let encoding = cie.encoding;
312
195k
        let length_offset = w.write_initial_length(encoding.format)?;
313
195k
        let length_base = w.len();
314
315
195k
        if eh_frame {
316
            // .eh_frame uses a relative offset which doesn't need relocation.
317
195k
            w.write_udata((w.len() - cie_offset) as u64, 4)?;
318
        } else {
319
0
            w.write_offset(
320
0
                cie_offset,
321
0
                SectionId::DebugFrame,
322
0
                encoding.format.word_size(),
323
0
            )?;
324
        }
325
326
195k
        if cie.fde_address_encoding != constants::DW_EH_PE_absptr {
327
0
            w.write_eh_pointer(
328
0
                self.address,
329
0
                cie.fde_address_encoding,
330
0
                encoding.address_size,
331
0
            )?;
332
0
            w.write_eh_pointer_data(
333
0
                self.length.into(),
334
0
                cie.fde_address_encoding.format(),
335
0
                encoding.address_size,
336
0
            )?;
337
        } else {
338
195k
            w.write_address(self.address, encoding.address_size)?;
339
195k
            w.write_udata(self.length.into(), encoding.address_size)?;
340
        }
341
342
195k
        if cie.has_augmentation() {
343
195k
            let augmentation_length_offset = w.len();
344
195k
            w.write_u8(0)?;
345
195k
            let augmentation_length_base = w.len();
346
347
195k
            debug_assert_eq!(self.lsda.is_some(), cie.lsda_encoding.is_some());
348
195k
            if let (Some(lsda), Some(lsda_encoding)) = (self.lsda, cie.lsda_encoding) {
349
195k
                w.write_eh_pointer(lsda, lsda_encoding, encoding.address_size)?;
350
0
            }
351
352
195k
            let augmentation_length = (w.len() - augmentation_length_base) as u64;
353
195k
            debug_assert!(augmentation_length < 0x80);
354
195k
            w.write_udata_at(augmentation_length_offset, augmentation_length, 1)?;
355
0
        }
356
357
195k
        let mut prev_offset = 0;
358
658k
        for (offset, instruction) in &self.instructions {
359
658k
            write_advance_loc(w, cie.code_alignment_factor, prev_offset, *offset)?;
360
658k
            prev_offset = *offset;
361
658k
            instruction.write(w, encoding, cie)?;
362
        }
363
364
195k
        write_nop(
365
195k
            w,
366
195k
            encoding.format.word_size() as usize + w.len() - length_base,
367
195k
            encoding.address_size,
368
0
        )?;
369
370
195k
        let length = (w.len() - length_base) as u64;
371
195k
        w.write_initial_length_at(length_offset, length, encoding.format)?;
372
373
195k
        Ok(())
374
195k
    }
<gimli::write::cfi::FrameDescriptionEntry>::write::<wasmer_compiler_singlepass::dwarf::WriterRelocate>
Line
Count
Source
304
35.6k
    fn write<W: Writer>(
305
35.6k
        &self,
306
35.6k
        w: &mut W,
307
35.6k
        eh_frame: bool,
308
35.6k
        cie_offset: usize,
309
35.6k
        cie: &CommonInformationEntry,
310
35.6k
    ) -> Result<()> {
311
35.6k
        let encoding = cie.encoding;
312
35.6k
        let length_offset = w.write_initial_length(encoding.format)?;
313
35.6k
        let length_base = w.len();
314
315
35.6k
        if eh_frame {
316
            // .eh_frame uses a relative offset which doesn't need relocation.
317
35.6k
            w.write_udata((w.len() - cie_offset) as u64, 4)?;
318
        } else {
319
0
            w.write_offset(
320
0
                cie_offset,
321
0
                SectionId::DebugFrame,
322
0
                encoding.format.word_size(),
323
0
            )?;
324
        }
325
326
35.6k
        if cie.fde_address_encoding != constants::DW_EH_PE_absptr {
327
0
            w.write_eh_pointer(
328
0
                self.address,
329
0
                cie.fde_address_encoding,
330
0
                encoding.address_size,
331
0
            )?;
332
0
            w.write_eh_pointer_data(
333
0
                self.length.into(),
334
0
                cie.fde_address_encoding.format(),
335
0
                encoding.address_size,
336
0
            )?;
337
        } else {
338
35.6k
            w.write_address(self.address, encoding.address_size)?;
339
35.6k
            w.write_udata(self.length.into(), encoding.address_size)?;
340
        }
341
342
35.6k
        if cie.has_augmentation() {
343
0
            let augmentation_length_offset = w.len();
344
0
            w.write_u8(0)?;
345
0
            let augmentation_length_base = w.len();
346
347
0
            debug_assert_eq!(self.lsda.is_some(), cie.lsda_encoding.is_some());
348
0
            if let (Some(lsda), Some(lsda_encoding)) = (self.lsda, cie.lsda_encoding) {
349
0
                w.write_eh_pointer(lsda, lsda_encoding, encoding.address_size)?;
350
0
            }
351
352
0
            let augmentation_length = (w.len() - augmentation_length_base) as u64;
353
0
            debug_assert!(augmentation_length < 0x80);
354
0
            w.write_udata_at(augmentation_length_offset, augmentation_length, 1)?;
355
35.6k
        }
356
357
35.6k
        let mut prev_offset = 0;
358
232k
        for (offset, instruction) in &self.instructions {
359
232k
            write_advance_loc(w, cie.code_alignment_factor, prev_offset, *offset)?;
360
232k
            prev_offset = *offset;
361
232k
            instruction.write(w, encoding, cie)?;
362
        }
363
364
35.6k
        write_nop(
365
35.6k
            w,
366
35.6k
            encoding.format.word_size() as usize + w.len() - length_base,
367
35.6k
            encoding.address_size,
368
0
        )?;
369
370
35.6k
        let length = (w.len() - length_base) as u64;
371
35.6k
        w.write_initial_length_at(length_offset, length, encoding.format)?;
372
373
35.6k
        Ok(())
374
35.6k
    }
375
}
376
377
/// An instruction in a frame description entry.
378
///
379
/// This may be a CFA definition, a register rule, or some other directive.
380
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
381
#[non_exhaustive]
382
pub enum CallFrameInstruction {
383
    /// Define the CFA rule to use the provided register and offset.
384
    Cfa(Register, i32),
385
    /// Update the CFA rule to use the provided register. The offset is unchanged.
386
    CfaRegister(Register),
387
    /// Update the CFA rule to use the provided offset. The register is unchanged.
388
    CfaOffset(i32),
389
    /// Define the CFA rule to use the provided expression.
390
    CfaExpression(Expression),
391
392
    /// Restore the initial rule for the register.
393
    Restore(Register),
394
    /// The previous value of the register is not recoverable.
395
    Undefined(Register),
396
    /// The register has not been modified.
397
    SameValue(Register),
398
    /// The previous value of the register is saved at address CFA + offset.
399
    Offset(Register, i32),
400
    /// The previous value of the register is CFA + offset.
401
    ValOffset(Register, i32),
402
    /// The previous value of the register is stored in another register.
403
    Register(Register, Register),
404
    /// The previous value of the register is saved at address given by the expression.
405
    Expression(Register, Expression),
406
    /// The previous value of the register is given by the expression.
407
    ValExpression(Register, Expression),
408
409
    /// Push all register rules onto a stack.
410
    RememberState,
411
    /// Pop all register rules off the stack.
412
    RestoreState,
413
    /// The size of the arguments that have been pushed onto the stack.
414
    ArgsSize(u32),
415
416
    /// AAarch64 extension: negate the `RA_SIGN_STATE` pseudo-register.
417
    NegateRaState,
418
}
419
420
impl CallFrameInstruction {
421
1.14M
    fn write<W: Writer>(
422
1.14M
        &self,
423
1.14M
        w: &mut W,
424
1.14M
        encoding: Encoding,
425
1.14M
        cie: &CommonInformationEntry,
426
1.14M
    ) -> Result<()> {
427
1.14M
        match *self {
428
27.6k
            CallFrameInstruction::Cfa(register, offset) => {
429
27.6k
                if offset < 0 {
430
0
                    let offset = factored_data_offset(offset, cie.data_alignment_factor)?;
431
0
                    w.write_u8(constants::DW_CFA_def_cfa_sf.0)?;
432
0
                    w.write_uleb128(register.0.into())?;
433
0
                    w.write_sleb128(offset.into())?;
434
                } else {
435
                    // Unfactored offset.
436
27.6k
                    w.write_u8(constants::DW_CFA_def_cfa.0)?;
437
27.6k
                    w.write_uleb128(register.0.into())?;
438
27.6k
                    w.write_uleb128(offset as u64)?;
439
                }
440
            }
441
276k
            CallFrameInstruction::CfaRegister(register) => {
442
276k
                w.write_u8(constants::DW_CFA_def_cfa_register.0)?;
443
276k
                w.write_uleb128(register.0.into())?;
444
            }
445
276k
            CallFrameInstruction::CfaOffset(offset) => {
446
276k
                if offset < 0 {
447
0
                    let offset = factored_data_offset(offset, cie.data_alignment_factor)?;
448
0
                    w.write_u8(constants::DW_CFA_def_cfa_offset_sf.0)?;
449
0
                    w.write_sleb128(offset.into())?;
450
                } else {
451
                    // Unfactored offset.
452
276k
                    w.write_u8(constants::DW_CFA_def_cfa_offset.0)?;
453
276k
                    w.write_uleb128(offset as u64)?;
454
                }
455
            }
456
0
            CallFrameInstruction::CfaExpression(ref expression) => {
457
0
                w.write_u8(constants::DW_CFA_def_cfa_expression.0)?;
458
0
                w.write_uleb128(expression.size(encoding, None)? as u64)?;
459
0
                expression.write(w, None, encoding, None)?;
460
            }
461
0
            CallFrameInstruction::Restore(register) => {
462
0
                if register.0 < 0x40 {
463
0
                    w.write_u8(constants::DW_CFA_restore.0 | register.0 as u8)?;
464
                } else {
465
0
                    w.write_u8(constants::DW_CFA_restore_extended.0)?;
466
0
                    w.write_uleb128(register.0.into())?;
467
                }
468
            }
469
0
            CallFrameInstruction::Undefined(register) => {
470
0
                w.write_u8(constants::DW_CFA_undefined.0)?;
471
0
                w.write_uleb128(register.0.into())?;
472
            }
473
0
            CallFrameInstruction::SameValue(register) => {
474
0
                w.write_u8(constants::DW_CFA_same_value.0)?;
475
0
                w.write_uleb128(register.0.into())?;
476
            }
477
560k
            CallFrameInstruction::Offset(register, offset) => {
478
560k
                let offset = factored_data_offset(offset, cie.data_alignment_factor)?;
479
560k
                if offset < 0 {
480
0
                    w.write_u8(constants::DW_CFA_offset_extended_sf.0)?;
481
0
                    w.write_uleb128(register.0.into())?;
482
0
                    w.write_sleb128(offset.into())?;
483
560k
                } else if register.0 < 0x40 {
484
560k
                    w.write_u8(constants::DW_CFA_offset.0 | register.0 as u8)?;
485
560k
                    w.write_uleb128(offset as u64)?;
486
                } else {
487
0
                    w.write_u8(constants::DW_CFA_offset_extended.0)?;
488
0
                    w.write_uleb128(register.0.into())?;
489
0
                    w.write_uleb128(offset as u64)?;
490
                }
491
            }
492
0
            CallFrameInstruction::ValOffset(register, offset) => {
493
0
                let offset = factored_data_offset(offset, cie.data_alignment_factor)?;
494
0
                if offset < 0 {
495
0
                    w.write_u8(constants::DW_CFA_val_offset_sf.0)?;
496
0
                    w.write_uleb128(register.0.into())?;
497
0
                    w.write_sleb128(offset.into())?;
498
                } else {
499
0
                    w.write_u8(constants::DW_CFA_val_offset.0)?;
500
0
                    w.write_uleb128(register.0.into())?;
501
0
                    w.write_uleb128(offset as u64)?;
502
                }
503
            }
504
0
            CallFrameInstruction::Register(register1, register2) => {
505
0
                w.write_u8(constants::DW_CFA_register.0)?;
506
0
                w.write_uleb128(register1.0.into())?;
507
0
                w.write_uleb128(register2.0.into())?;
508
            }
509
0
            CallFrameInstruction::Expression(register, ref expression) => {
510
0
                w.write_u8(constants::DW_CFA_expression.0)?;
511
0
                w.write_uleb128(register.0.into())?;
512
0
                w.write_uleb128(expression.size(encoding, None)? as u64)?;
513
0
                expression.write(w, None, encoding, None)?;
514
            }
515
0
            CallFrameInstruction::ValExpression(register, ref expression) => {
516
0
                w.write_u8(constants::DW_CFA_val_expression.0)?;
517
0
                w.write_uleb128(register.0.into())?;
518
0
                w.write_uleb128(expression.size(encoding, None)? as u64)?;
519
0
                expression.write(w, None, encoding, None)?;
520
            }
521
            CallFrameInstruction::RememberState => {
522
0
                w.write_u8(constants::DW_CFA_remember_state.0)?;
523
            }
524
            CallFrameInstruction::RestoreState => {
525
0
                w.write_u8(constants::DW_CFA_restore_state.0)?;
526
            }
527
0
            CallFrameInstruction::ArgsSize(size) => {
528
0
                w.write_u8(constants::DW_CFA_GNU_args_size.0)?;
529
0
                w.write_uleb128(size.into())?;
530
            }
531
            CallFrameInstruction::NegateRaState => {
532
0
                w.write_u8(constants::DW_CFA_AARCH64_negate_ra_state.0)?;
533
            }
534
        }
535
1.14M
        Ok(())
536
1.14M
    }
<gimli::write::cfi::CallFrameInstruction>::write::<wasmer_compiler_cranelift::dwarf::WriterRelocate>
Line
Count
Source
421
130k
    fn write<W: Writer>(
422
130k
        &self,
423
130k
        w: &mut W,
424
130k
        encoding: Encoding,
425
130k
        cie: &CommonInformationEntry,
426
130k
    ) -> Result<()> {
427
130k
        match *self {
428
7.79k
            CallFrameInstruction::Cfa(register, offset) => {
429
7.79k
                if offset < 0 {
430
0
                    let offset = factored_data_offset(offset, cie.data_alignment_factor)?;
431
0
                    w.write_u8(constants::DW_CFA_def_cfa_sf.0)?;
432
0
                    w.write_uleb128(register.0.into())?;
433
0
                    w.write_sleb128(offset.into())?;
434
                } else {
435
                    // Unfactored offset.
436
7.79k
                    w.write_u8(constants::DW_CFA_def_cfa.0)?;
437
7.79k
                    w.write_uleb128(register.0.into())?;
438
7.79k
                    w.write_uleb128(offset as u64)?;
439
                }
440
            }
441
35.6k
            CallFrameInstruction::CfaRegister(register) => {
442
35.6k
                w.write_u8(constants::DW_CFA_def_cfa_register.0)?;
443
35.6k
                w.write_uleb128(register.0.into())?;
444
            }
445
35.6k
            CallFrameInstruction::CfaOffset(offset) => {
446
35.6k
                if offset < 0 {
447
0
                    let offset = factored_data_offset(offset, cie.data_alignment_factor)?;
448
0
                    w.write_u8(constants::DW_CFA_def_cfa_offset_sf.0)?;
449
0
                    w.write_sleb128(offset.into())?;
450
                } else {
451
                    // Unfactored offset.
452
35.6k
                    w.write_u8(constants::DW_CFA_def_cfa_offset.0)?;
453
35.6k
                    w.write_uleb128(offset as u64)?;
454
                }
455
            }
456
0
            CallFrameInstruction::CfaExpression(ref expression) => {
457
0
                w.write_u8(constants::DW_CFA_def_cfa_expression.0)?;
458
0
                w.write_uleb128(expression.size(encoding, None)? as u64)?;
459
0
                expression.write(w, None, encoding, None)?;
460
            }
461
0
            CallFrameInstruction::Restore(register) => {
462
0
                if register.0 < 0x40 {
463
0
                    w.write_u8(constants::DW_CFA_restore.0 | register.0 as u8)?;
464
                } else {
465
0
                    w.write_u8(constants::DW_CFA_restore_extended.0)?;
466
0
                    w.write_uleb128(register.0.into())?;
467
                }
468
            }
469
0
            CallFrameInstruction::Undefined(register) => {
470
0
                w.write_u8(constants::DW_CFA_undefined.0)?;
471
0
                w.write_uleb128(register.0.into())?;
472
            }
473
0
            CallFrameInstruction::SameValue(register) => {
474
0
                w.write_u8(constants::DW_CFA_same_value.0)?;
475
0
                w.write_uleb128(register.0.into())?;
476
            }
477
51.5k
            CallFrameInstruction::Offset(register, offset) => {
478
51.5k
                let offset = factored_data_offset(offset, cie.data_alignment_factor)?;
479
51.5k
                if offset < 0 {
480
0
                    w.write_u8(constants::DW_CFA_offset_extended_sf.0)?;
481
0
                    w.write_uleb128(register.0.into())?;
482
0
                    w.write_sleb128(offset.into())?;
483
51.5k
                } else if register.0 < 0x40 {
484
51.5k
                    w.write_u8(constants::DW_CFA_offset.0 | register.0 as u8)?;
485
51.5k
                    w.write_uleb128(offset as u64)?;
486
                } else {
487
0
                    w.write_u8(constants::DW_CFA_offset_extended.0)?;
488
0
                    w.write_uleb128(register.0.into())?;
489
0
                    w.write_uleb128(offset as u64)?;
490
                }
491
            }
492
0
            CallFrameInstruction::ValOffset(register, offset) => {
493
0
                let offset = factored_data_offset(offset, cie.data_alignment_factor)?;
494
0
                if offset < 0 {
495
0
                    w.write_u8(constants::DW_CFA_val_offset_sf.0)?;
496
0
                    w.write_uleb128(register.0.into())?;
497
0
                    w.write_sleb128(offset.into())?;
498
                } else {
499
0
                    w.write_u8(constants::DW_CFA_val_offset.0)?;
500
0
                    w.write_uleb128(register.0.into())?;
501
0
                    w.write_uleb128(offset as u64)?;
502
                }
503
            }
504
0
            CallFrameInstruction::Register(register1, register2) => {
505
0
                w.write_u8(constants::DW_CFA_register.0)?;
506
0
                w.write_uleb128(register1.0.into())?;
507
0
                w.write_uleb128(register2.0.into())?;
508
            }
509
0
            CallFrameInstruction::Expression(register, ref expression) => {
510
0
                w.write_u8(constants::DW_CFA_expression.0)?;
511
0
                w.write_uleb128(register.0.into())?;
512
0
                w.write_uleb128(expression.size(encoding, None)? as u64)?;
513
0
                expression.write(w, None, encoding, None)?;
514
            }
515
0
            CallFrameInstruction::ValExpression(register, ref expression) => {
516
0
                w.write_u8(constants::DW_CFA_val_expression.0)?;
517
0
                w.write_uleb128(register.0.into())?;
518
0
                w.write_uleb128(expression.size(encoding, None)? as u64)?;
519
0
                expression.write(w, None, encoding, None)?;
520
            }
521
            CallFrameInstruction::RememberState => {
522
0
                w.write_u8(constants::DW_CFA_remember_state.0)?;
523
            }
524
            CallFrameInstruction::RestoreState => {
525
0
                w.write_u8(constants::DW_CFA_restore_state.0)?;
526
            }
527
0
            CallFrameInstruction::ArgsSize(size) => {
528
0
                w.write_u8(constants::DW_CFA_GNU_args_size.0)?;
529
0
                w.write_uleb128(size.into())?;
530
            }
531
            CallFrameInstruction::NegateRaState => {
532
0
                w.write_u8(constants::DW_CFA_AARCH64_negate_ra_state.0)?;
533
            }
534
        }
535
130k
        Ok(())
536
130k
    }
Unexecuted instantiation: <gimli::write::cfi::CallFrameInstruction>::write::<_>
<gimli::write::cfi::CallFrameInstruction>::write::<wasmer_compiler_singlepass::dwarf::WriterRelocate>
Line
Count
Source
421
80.7k
    fn write<W: Writer>(
422
80.7k
        &self,
423
80.7k
        w: &mut W,
424
80.7k
        encoding: Encoding,
425
80.7k
        cie: &CommonInformationEntry,
426
80.7k
    ) -> Result<()> {
427
80.7k
        match *self {
428
67
            CallFrameInstruction::Cfa(register, offset) => {
429
67
                if offset < 0 {
430
0
                    let offset = factored_data_offset(offset, cie.data_alignment_factor)?;
431
0
                    w.write_u8(constants::DW_CFA_def_cfa_sf.0)?;
432
0
                    w.write_uleb128(register.0.into())?;
433
0
                    w.write_sleb128(offset.into())?;
434
                } else {
435
                    // Unfactored offset.
436
67
                    w.write_u8(constants::DW_CFA_def_cfa.0)?;
437
67
                    w.write_uleb128(register.0.into())?;
438
67
                    w.write_uleb128(offset as u64)?;
439
                }
440
            }
441
10.1k
            CallFrameInstruction::CfaRegister(register) => {
442
10.1k
                w.write_u8(constants::DW_CFA_def_cfa_register.0)?;
443
10.1k
                w.write_uleb128(register.0.into())?;
444
            }
445
10.1k
            CallFrameInstruction::CfaOffset(offset) => {
446
10.1k
                if offset < 0 {
447
0
                    let offset = factored_data_offset(offset, cie.data_alignment_factor)?;
448
0
                    w.write_u8(constants::DW_CFA_def_cfa_offset_sf.0)?;
449
0
                    w.write_sleb128(offset.into())?;
450
                } else {
451
                    // Unfactored offset.
452
10.1k
                    w.write_u8(constants::DW_CFA_def_cfa_offset.0)?;
453
10.1k
                    w.write_uleb128(offset as u64)?;
454
                }
455
            }
456
0
            CallFrameInstruction::CfaExpression(ref expression) => {
457
0
                w.write_u8(constants::DW_CFA_def_cfa_expression.0)?;
458
0
                w.write_uleb128(expression.size(encoding, None)? as u64)?;
459
0
                expression.write(w, None, encoding, None)?;
460
            }
461
0
            CallFrameInstruction::Restore(register) => {
462
0
                if register.0 < 0x40 {
463
0
                    w.write_u8(constants::DW_CFA_restore.0 | register.0 as u8)?;
464
                } else {
465
0
                    w.write_u8(constants::DW_CFA_restore_extended.0)?;
466
0
                    w.write_uleb128(register.0.into())?;
467
                }
468
            }
469
0
            CallFrameInstruction::Undefined(register) => {
470
0
                w.write_u8(constants::DW_CFA_undefined.0)?;
471
0
                w.write_uleb128(register.0.into())?;
472
            }
473
0
            CallFrameInstruction::SameValue(register) => {
474
0
                w.write_u8(constants::DW_CFA_same_value.0)?;
475
0
                w.write_uleb128(register.0.into())?;
476
            }
477
60.3k
            CallFrameInstruction::Offset(register, offset) => {
478
60.3k
                let offset = factored_data_offset(offset, cie.data_alignment_factor)?;
479
60.3k
                if offset < 0 {
480
0
                    w.write_u8(constants::DW_CFA_offset_extended_sf.0)?;
481
0
                    w.write_uleb128(register.0.into())?;
482
0
                    w.write_sleb128(offset.into())?;
483
60.3k
                } else if register.0 < 0x40 {
484
60.3k
                    w.write_u8(constants::DW_CFA_offset.0 | register.0 as u8)?;
485
60.3k
                    w.write_uleb128(offset as u64)?;
486
                } else {
487
0
                    w.write_u8(constants::DW_CFA_offset_extended.0)?;
488
0
                    w.write_uleb128(register.0.into())?;
489
0
                    w.write_uleb128(offset as u64)?;
490
                }
491
            }
492
0
            CallFrameInstruction::ValOffset(register, offset) => {
493
0
                let offset = factored_data_offset(offset, cie.data_alignment_factor)?;
494
0
                if offset < 0 {
495
0
                    w.write_u8(constants::DW_CFA_val_offset_sf.0)?;
496
0
                    w.write_uleb128(register.0.into())?;
497
0
                    w.write_sleb128(offset.into())?;
498
                } else {
499
0
                    w.write_u8(constants::DW_CFA_val_offset.0)?;
500
0
                    w.write_uleb128(register.0.into())?;
501
0
                    w.write_uleb128(offset as u64)?;
502
                }
503
            }
504
0
            CallFrameInstruction::Register(register1, register2) => {
505
0
                w.write_u8(constants::DW_CFA_register.0)?;
506
0
                w.write_uleb128(register1.0.into())?;
507
0
                w.write_uleb128(register2.0.into())?;
508
            }
509
0
            CallFrameInstruction::Expression(register, ref expression) => {
510
0
                w.write_u8(constants::DW_CFA_expression.0)?;
511
0
                w.write_uleb128(register.0.into())?;
512
0
                w.write_uleb128(expression.size(encoding, None)? as u64)?;
513
0
                expression.write(w, None, encoding, None)?;
514
            }
515
0
            CallFrameInstruction::ValExpression(register, ref expression) => {
516
0
                w.write_u8(constants::DW_CFA_val_expression.0)?;
517
0
                w.write_uleb128(register.0.into())?;
518
0
                w.write_uleb128(expression.size(encoding, None)? as u64)?;
519
0
                expression.write(w, None, encoding, None)?;
520
            }
521
            CallFrameInstruction::RememberState => {
522
0
                w.write_u8(constants::DW_CFA_remember_state.0)?;
523
            }
524
            CallFrameInstruction::RestoreState => {
525
0
                w.write_u8(constants::DW_CFA_restore_state.0)?;
526
            }
527
0
            CallFrameInstruction::ArgsSize(size) => {
528
0
                w.write_u8(constants::DW_CFA_GNU_args_size.0)?;
529
0
                w.write_uleb128(size.into())?;
530
            }
531
            CallFrameInstruction::NegateRaState => {
532
0
                w.write_u8(constants::DW_CFA_AARCH64_negate_ra_state.0)?;
533
            }
534
        }
535
80.7k
        Ok(())
536
80.7k
    }
<gimli::write::cfi::CallFrameInstruction>::write::<wasmer_compiler_cranelift::dwarf::WriterRelocate>
Line
Count
Source
421
682k
    fn write<W: Writer>(
422
682k
        &self,
423
682k
        w: &mut W,
424
682k
        encoding: Encoding,
425
682k
        cie: &CommonInformationEntry,
426
682k
    ) -> Result<()> {
427
682k
        match *self {
428
11.9k
            CallFrameInstruction::Cfa(register, offset) => {
429
11.9k
                if offset < 0 {
430
0
                    let offset = factored_data_offset(offset, cie.data_alignment_factor)?;
431
0
                    w.write_u8(constants::DW_CFA_def_cfa_sf.0)?;
432
0
                    w.write_uleb128(register.0.into())?;
433
0
                    w.write_sleb128(offset.into())?;
434
                } else {
435
                    // Unfactored offset.
436
11.9k
                    w.write_u8(constants::DW_CFA_def_cfa.0)?;
437
11.9k
                    w.write_uleb128(register.0.into())?;
438
11.9k
                    w.write_uleb128(offset as u64)?;
439
                }
440
            }
441
195k
            CallFrameInstruction::CfaRegister(register) => {
442
195k
                w.write_u8(constants::DW_CFA_def_cfa_register.0)?;
443
195k
                w.write_uleb128(register.0.into())?;
444
            }
445
195k
            CallFrameInstruction::CfaOffset(offset) => {
446
195k
                if offset < 0 {
447
0
                    let offset = factored_data_offset(offset, cie.data_alignment_factor)?;
448
0
                    w.write_u8(constants::DW_CFA_def_cfa_offset_sf.0)?;
449
0
                    w.write_sleb128(offset.into())?;
450
                } else {
451
                    // Unfactored offset.
452
195k
                    w.write_u8(constants::DW_CFA_def_cfa_offset.0)?;
453
195k
                    w.write_uleb128(offset as u64)?;
454
                }
455
            }
456
0
            CallFrameInstruction::CfaExpression(ref expression) => {
457
0
                w.write_u8(constants::DW_CFA_def_cfa_expression.0)?;
458
0
                w.write_uleb128(expression.size(encoding, None)? as u64)?;
459
0
                expression.write(w, None, encoding, None)?;
460
            }
461
0
            CallFrameInstruction::Restore(register) => {
462
0
                if register.0 < 0x40 {
463
0
                    w.write_u8(constants::DW_CFA_restore.0 | register.0 as u8)?;
464
                } else {
465
0
                    w.write_u8(constants::DW_CFA_restore_extended.0)?;
466
0
                    w.write_uleb128(register.0.into())?;
467
                }
468
            }
469
0
            CallFrameInstruction::Undefined(register) => {
470
0
                w.write_u8(constants::DW_CFA_undefined.0)?;
471
0
                w.write_uleb128(register.0.into())?;
472
            }
473
0
            CallFrameInstruction::SameValue(register) => {
474
0
                w.write_u8(constants::DW_CFA_same_value.0)?;
475
0
                w.write_uleb128(register.0.into())?;
476
            }
477
279k
            CallFrameInstruction::Offset(register, offset) => {
478
279k
                let offset = factored_data_offset(offset, cie.data_alignment_factor)?;
479
279k
                if offset < 0 {
480
0
                    w.write_u8(constants::DW_CFA_offset_extended_sf.0)?;
481
0
                    w.write_uleb128(register.0.into())?;
482
0
                    w.write_sleb128(offset.into())?;
483
279k
                } else if register.0 < 0x40 {
484
279k
                    w.write_u8(constants::DW_CFA_offset.0 | register.0 as u8)?;
485
279k
                    w.write_uleb128(offset as u64)?;
486
                } else {
487
0
                    w.write_u8(constants::DW_CFA_offset_extended.0)?;
488
0
                    w.write_uleb128(register.0.into())?;
489
0
                    w.write_uleb128(offset as u64)?;
490
                }
491
            }
492
0
            CallFrameInstruction::ValOffset(register, offset) => {
493
0
                let offset = factored_data_offset(offset, cie.data_alignment_factor)?;
494
0
                if offset < 0 {
495
0
                    w.write_u8(constants::DW_CFA_val_offset_sf.0)?;
496
0
                    w.write_uleb128(register.0.into())?;
497
0
                    w.write_sleb128(offset.into())?;
498
                } else {
499
0
                    w.write_u8(constants::DW_CFA_val_offset.0)?;
500
0
                    w.write_uleb128(register.0.into())?;
501
0
                    w.write_uleb128(offset as u64)?;
502
                }
503
            }
504
0
            CallFrameInstruction::Register(register1, register2) => {
505
0
                w.write_u8(constants::DW_CFA_register.0)?;
506
0
                w.write_uleb128(register1.0.into())?;
507
0
                w.write_uleb128(register2.0.into())?;
508
            }
509
0
            CallFrameInstruction::Expression(register, ref expression) => {
510
0
                w.write_u8(constants::DW_CFA_expression.0)?;
511
0
                w.write_uleb128(register.0.into())?;
512
0
                w.write_uleb128(expression.size(encoding, None)? as u64)?;
513
0
                expression.write(w, None, encoding, None)?;
514
            }
515
0
            CallFrameInstruction::ValExpression(register, ref expression) => {
516
0
                w.write_u8(constants::DW_CFA_val_expression.0)?;
517
0
                w.write_uleb128(register.0.into())?;
518
0
                w.write_uleb128(expression.size(encoding, None)? as u64)?;
519
0
                expression.write(w, None, encoding, None)?;
520
            }
521
            CallFrameInstruction::RememberState => {
522
0
                w.write_u8(constants::DW_CFA_remember_state.0)?;
523
            }
524
            CallFrameInstruction::RestoreState => {
525
0
                w.write_u8(constants::DW_CFA_restore_state.0)?;
526
            }
527
0
            CallFrameInstruction::ArgsSize(size) => {
528
0
                w.write_u8(constants::DW_CFA_GNU_args_size.0)?;
529
0
                w.write_uleb128(size.into())?;
530
            }
531
            CallFrameInstruction::NegateRaState => {
532
0
                w.write_u8(constants::DW_CFA_AARCH64_negate_ra_state.0)?;
533
            }
534
        }
535
682k
        Ok(())
536
682k
    }
<gimli::write::cfi::CallFrameInstruction>::write::<wasmer_compiler_singlepass::dwarf::WriterRelocate>
Line
Count
Source
421
248k
    fn write<W: Writer>(
422
248k
        &self,
423
248k
        w: &mut W,
424
248k
        encoding: Encoding,
425
248k
        cie: &CommonInformationEntry,
426
248k
    ) -> Result<()> {
427
248k
        match *self {
428
7.79k
            CallFrameInstruction::Cfa(register, offset) => {
429
7.79k
                if offset < 0 {
430
0
                    let offset = factored_data_offset(offset, cie.data_alignment_factor)?;
431
0
                    w.write_u8(constants::DW_CFA_def_cfa_sf.0)?;
432
0
                    w.write_uleb128(register.0.into())?;
433
0
                    w.write_sleb128(offset.into())?;
434
                } else {
435
                    // Unfactored offset.
436
7.79k
                    w.write_u8(constants::DW_CFA_def_cfa.0)?;
437
7.79k
                    w.write_uleb128(register.0.into())?;
438
7.79k
                    w.write_uleb128(offset as u64)?;
439
                }
440
            }
441
35.6k
            CallFrameInstruction::CfaRegister(register) => {
442
35.6k
                w.write_u8(constants::DW_CFA_def_cfa_register.0)?;
443
35.6k
                w.write_uleb128(register.0.into())?;
444
            }
445
35.6k
            CallFrameInstruction::CfaOffset(offset) => {
446
35.6k
                if offset < 0 {
447
0
                    let offset = factored_data_offset(offset, cie.data_alignment_factor)?;
448
0
                    w.write_u8(constants::DW_CFA_def_cfa_offset_sf.0)?;
449
0
                    w.write_sleb128(offset.into())?;
450
                } else {
451
                    // Unfactored offset.
452
35.6k
                    w.write_u8(constants::DW_CFA_def_cfa_offset.0)?;
453
35.6k
                    w.write_uleb128(offset as u64)?;
454
                }
455
            }
456
0
            CallFrameInstruction::CfaExpression(ref expression) => {
457
0
                w.write_u8(constants::DW_CFA_def_cfa_expression.0)?;
458
0
                w.write_uleb128(expression.size(encoding, None)? as u64)?;
459
0
                expression.write(w, None, encoding, None)?;
460
            }
461
0
            CallFrameInstruction::Restore(register) => {
462
0
                if register.0 < 0x40 {
463
0
                    w.write_u8(constants::DW_CFA_restore.0 | register.0 as u8)?;
464
                } else {
465
0
                    w.write_u8(constants::DW_CFA_restore_extended.0)?;
466
0
                    w.write_uleb128(register.0.into())?;
467
                }
468
            }
469
0
            CallFrameInstruction::Undefined(register) => {
470
0
                w.write_u8(constants::DW_CFA_undefined.0)?;
471
0
                w.write_uleb128(register.0.into())?;
472
            }
473
0
            CallFrameInstruction::SameValue(register) => {
474
0
                w.write_u8(constants::DW_CFA_same_value.0)?;
475
0
                w.write_uleb128(register.0.into())?;
476
            }
477
169k
            CallFrameInstruction::Offset(register, offset) => {
478
169k
                let offset = factored_data_offset(offset, cie.data_alignment_factor)?;
479
169k
                if offset < 0 {
480
0
                    w.write_u8(constants::DW_CFA_offset_extended_sf.0)?;
481
0
                    w.write_uleb128(register.0.into())?;
482
0
                    w.write_sleb128(offset.into())?;
483
169k
                } else if register.0 < 0x40 {
484
169k
                    w.write_u8(constants::DW_CFA_offset.0 | register.0 as u8)?;
485
169k
                    w.write_uleb128(offset as u64)?;
486
                } else {
487
0
                    w.write_u8(constants::DW_CFA_offset_extended.0)?;
488
0
                    w.write_uleb128(register.0.into())?;
489
0
                    w.write_uleb128(offset as u64)?;
490
                }
491
            }
492
0
            CallFrameInstruction::ValOffset(register, offset) => {
493
0
                let offset = factored_data_offset(offset, cie.data_alignment_factor)?;
494
0
                if offset < 0 {
495
0
                    w.write_u8(constants::DW_CFA_val_offset_sf.0)?;
496
0
                    w.write_uleb128(register.0.into())?;
497
0
                    w.write_sleb128(offset.into())?;
498
                } else {
499
0
                    w.write_u8(constants::DW_CFA_val_offset.0)?;
500
0
                    w.write_uleb128(register.0.into())?;
501
0
                    w.write_uleb128(offset as u64)?;
502
                }
503
            }
504
0
            CallFrameInstruction::Register(register1, register2) => {
505
0
                w.write_u8(constants::DW_CFA_register.0)?;
506
0
                w.write_uleb128(register1.0.into())?;
507
0
                w.write_uleb128(register2.0.into())?;
508
            }
509
0
            CallFrameInstruction::Expression(register, ref expression) => {
510
0
                w.write_u8(constants::DW_CFA_expression.0)?;
511
0
                w.write_uleb128(register.0.into())?;
512
0
                w.write_uleb128(expression.size(encoding, None)? as u64)?;
513
0
                expression.write(w, None, encoding, None)?;
514
            }
515
0
            CallFrameInstruction::ValExpression(register, ref expression) => {
516
0
                w.write_u8(constants::DW_CFA_val_expression.0)?;
517
0
                w.write_uleb128(register.0.into())?;
518
0
                w.write_uleb128(expression.size(encoding, None)? as u64)?;
519
0
                expression.write(w, None, encoding, None)?;
520
            }
521
            CallFrameInstruction::RememberState => {
522
0
                w.write_u8(constants::DW_CFA_remember_state.0)?;
523
            }
524
            CallFrameInstruction::RestoreState => {
525
0
                w.write_u8(constants::DW_CFA_restore_state.0)?;
526
            }
527
0
            CallFrameInstruction::ArgsSize(size) => {
528
0
                w.write_u8(constants::DW_CFA_GNU_args_size.0)?;
529
0
                w.write_uleb128(size.into())?;
530
            }
531
            CallFrameInstruction::NegateRaState => {
532
0
                w.write_u8(constants::DW_CFA_AARCH64_negate_ra_state.0)?;
533
            }
534
        }
535
248k
        Ok(())
536
248k
    }
537
}
538
539
1.08M
fn write_advance_loc<W: Writer>(
540
1.08M
    w: &mut W,
541
1.08M
    code_alignment_factor: u8,
542
1.08M
    prev_offset: u32,
543
1.08M
    offset: u32,
544
1.08M
) -> Result<()> {
545
1.08M
    if offset == prev_offset {
546
276k
        return Ok(());
547
810k
    }
548
810k
    let delta = factored_code_delta(prev_offset, offset, code_alignment_factor)?;
549
810k
    if delta < 0x40 {
550
810k
        w.write_u8(constants::DW_CFA_advance_loc.0 | delta as u8)?;
551
0
    } else if delta < 0x100 {
552
0
        w.write_u8(constants::DW_CFA_advance_loc1.0)?;
553
0
        w.write_u8(delta as u8)?;
554
0
    } else if delta < 0x10000 {
555
0
        w.write_u8(constants::DW_CFA_advance_loc2.0)?;
556
0
        w.write_u16(delta as u16)?;
557
    } else {
558
0
        w.write_u8(constants::DW_CFA_advance_loc4.0)?;
559
0
        w.write_u32(delta)?;
560
    }
561
810k
    Ok(())
562
1.08M
}
gimli::write::cfi::write_advance_loc::<wasmer_compiler_cranelift::dwarf::WriterRelocate>
Line
Count
Source
539
115k
fn write_advance_loc<W: Writer>(
540
115k
    w: &mut W,
541
115k
    code_alignment_factor: u8,
542
115k
    prev_offset: u32,
543
115k
    offset: u32,
544
115k
) -> Result<()> {
545
115k
    if offset == prev_offset {
546
35.6k
        return Ok(());
547
79.4k
    }
548
79.4k
    let delta = factored_code_delta(prev_offset, offset, code_alignment_factor)?;
549
79.4k
    if delta < 0x40 {
550
79.4k
        w.write_u8(constants::DW_CFA_advance_loc.0 | delta as u8)?;
551
0
    } else if delta < 0x100 {
552
0
        w.write_u8(constants::DW_CFA_advance_loc1.0)?;
553
0
        w.write_u8(delta as u8)?;
554
0
    } else if delta < 0x10000 {
555
0
        w.write_u8(constants::DW_CFA_advance_loc2.0)?;
556
0
        w.write_u16(delta as u16)?;
557
    } else {
558
0
        w.write_u8(constants::DW_CFA_advance_loc4.0)?;
559
0
        w.write_u32(delta)?;
560
    }
561
79.4k
    Ok(())
562
115k
}
Unexecuted instantiation: gimli::write::cfi::write_advance_loc::<_>
gimli::write::cfi::write_advance_loc::<wasmer_compiler_singlepass::dwarf::WriterRelocate>
Line
Count
Source
539
80.5k
fn write_advance_loc<W: Writer>(
540
80.5k
    w: &mut W,
541
80.5k
    code_alignment_factor: u8,
542
80.5k
    prev_offset: u32,
543
80.5k
    offset: u32,
544
80.5k
) -> Result<()> {
545
80.5k
    if offset == prev_offset {
546
10.1k
        return Ok(());
547
70.4k
    }
548
70.4k
    let delta = factored_code_delta(prev_offset, offset, code_alignment_factor)?;
549
70.4k
    if delta < 0x40 {
550
70.4k
        w.write_u8(constants::DW_CFA_advance_loc.0 | delta as u8)?;
551
0
    } else if delta < 0x100 {
552
0
        w.write_u8(constants::DW_CFA_advance_loc1.0)?;
553
0
        w.write_u8(delta as u8)?;
554
0
    } else if delta < 0x10000 {
555
0
        w.write_u8(constants::DW_CFA_advance_loc2.0)?;
556
0
        w.write_u16(delta as u16)?;
557
    } else {
558
0
        w.write_u8(constants::DW_CFA_advance_loc4.0)?;
559
0
        w.write_u32(delta)?;
560
    }
561
70.4k
    Ok(())
562
80.5k
}
gimli::write::cfi::write_advance_loc::<wasmer_compiler_cranelift::dwarf::WriterRelocate>
Line
Count
Source
539
658k
fn write_advance_loc<W: Writer>(
540
658k
    w: &mut W,
541
658k
    code_alignment_factor: u8,
542
658k
    prev_offset: u32,
543
658k
    offset: u32,
544
658k
) -> Result<()> {
545
658k
    if offset == prev_offset {
546
195k
        return Ok(());
547
463k
    }
548
463k
    let delta = factored_code_delta(prev_offset, offset, code_alignment_factor)?;
549
463k
    if delta < 0x40 {
550
463k
        w.write_u8(constants::DW_CFA_advance_loc.0 | delta as u8)?;
551
0
    } else if delta < 0x100 {
552
0
        w.write_u8(constants::DW_CFA_advance_loc1.0)?;
553
0
        w.write_u8(delta as u8)?;
554
0
    } else if delta < 0x10000 {
555
0
        w.write_u8(constants::DW_CFA_advance_loc2.0)?;
556
0
        w.write_u16(delta as u16)?;
557
    } else {
558
0
        w.write_u8(constants::DW_CFA_advance_loc4.0)?;
559
0
        w.write_u32(delta)?;
560
    }
561
463k
    Ok(())
562
658k
}
gimli::write::cfi::write_advance_loc::<wasmer_compiler_singlepass::dwarf::WriterRelocate>
Line
Count
Source
539
232k
fn write_advance_loc<W: Writer>(
540
232k
    w: &mut W,
541
232k
    code_alignment_factor: u8,
542
232k
    prev_offset: u32,
543
232k
    offset: u32,
544
232k
) -> Result<()> {
545
232k
    if offset == prev_offset {
546
35.6k
        return Ok(());
547
196k
    }
548
196k
    let delta = factored_code_delta(prev_offset, offset, code_alignment_factor)?;
549
196k
    if delta < 0x40 {
550
196k
        w.write_u8(constants::DW_CFA_advance_loc.0 | delta as u8)?;
551
0
    } else if delta < 0x100 {
552
0
        w.write_u8(constants::DW_CFA_advance_loc1.0)?;
553
0
        w.write_u8(delta as u8)?;
554
0
    } else if delta < 0x10000 {
555
0
        w.write_u8(constants::DW_CFA_advance_loc2.0)?;
556
0
        w.write_u16(delta as u16)?;
557
    } else {
558
0
        w.write_u8(constants::DW_CFA_advance_loc4.0)?;
559
0
        w.write_u32(delta)?;
560
    }
561
196k
    Ok(())
562
232k
}
563
564
304k
fn write_nop<W: Writer>(w: &mut W, len: usize, align: u8) -> Result<()> {
565
304k
    debug_assert_eq!(align & (align - 1), 0);
566
304k
    let tail_len = (!len + 1) & (align as usize - 1);
567
304k
    for _ in 0..tail_len {
568
1.65M
        w.write_u8(constants::DW_CFA_nop.0)?;
569
    }
570
304k
    Ok(())
571
304k
}
gimli::write::cfi::write_nop::<wasmer_compiler_cranelift::dwarf::WriterRelocate>
Line
Count
Source
564
43.4k
fn write_nop<W: Writer>(w: &mut W, len: usize, align: u8) -> Result<()> {
565
43.4k
    debug_assert_eq!(align & (align - 1), 0);
566
43.4k
    let tail_len = (!len + 1) & (align as usize - 1);
567
43.4k
    for _ in 0..tail_len {
568
237k
        w.write_u8(constants::DW_CFA_nop.0)?;
569
    }
570
43.4k
    Ok(())
571
43.4k
}
Unexecuted instantiation: gimli::write::cfi::write_nop::<_>
gimli::write::cfi::write_nop::<wasmer_compiler_singlepass::dwarf::WriterRelocate>
Line
Count
Source
564
10.2k
fn write_nop<W: Writer>(w: &mut W, len: usize, align: u8) -> Result<()> {
565
10.2k
    debug_assert_eq!(align & (align - 1), 0);
566
10.2k
    let tail_len = (!len + 1) & (align as usize - 1);
567
10.2k
    for _ in 0..tail_len {
568
11.8k
        w.write_u8(constants::DW_CFA_nop.0)?;
569
    }
570
10.2k
    Ok(())
571
10.2k
}
gimli::write::cfi::write_nop::<wasmer_compiler_cranelift::dwarf::WriterRelocate>
Line
Count
Source
564
207k
fn write_nop<W: Writer>(w: &mut W, len: usize, align: u8) -> Result<()> {
565
207k
    debug_assert_eq!(align & (align - 1), 0);
566
207k
    let tail_len = (!len + 1) & (align as usize - 1);
567
207k
    for _ in 0..tail_len {
568
1.26M
        w.write_u8(constants::DW_CFA_nop.0)?;
569
    }
570
207k
    Ok(())
571
207k
}
gimli::write::cfi::write_nop::<wasmer_compiler_singlepass::dwarf::WriterRelocate>
Line
Count
Source
564
43.4k
fn write_nop<W: Writer>(w: &mut W, len: usize, align: u8) -> Result<()> {
565
43.4k
    debug_assert_eq!(align & (align - 1), 0);
566
43.4k
    let tail_len = (!len + 1) & (align as usize - 1);
567
43.4k
    for _ in 0..tail_len {
568
138k
        w.write_u8(constants::DW_CFA_nop.0)?;
569
    }
570
43.4k
    Ok(())
571
43.4k
}
572
573
810k
fn factored_code_delta(prev_offset: u32, offset: u32, factor: u8) -> Result<u32> {
574
810k
    if offset < prev_offset {
575
0
        return Err(Error::InvalidFrameCodeOffset(offset));
576
810k
    }
577
810k
    let delta = offset - prev_offset;
578
810k
    let factor = u32::from(factor);
579
810k
    let factored_delta = delta / factor;
580
810k
    if delta != factored_delta * factor {
581
0
        return Err(Error::InvalidFrameCodeOffset(offset));
582
810k
    }
583
810k
    Ok(factored_delta)
584
810k
}
585
586
560k
fn factored_data_offset(offset: i32, factor: i8) -> Result<i32> {
587
560k
    let factor = i32::from(factor);
588
560k
    let factored_offset = offset / factor;
589
560k
    if offset != factored_offset * factor {
590
0
        return Err(Error::InvalidFrameDataOffset(offset));
591
560k
    }
592
560k
    Ok(factored_offset)
593
560k
}
594
595
#[cfg(feature = "read")]
596
pub(crate) mod convert {
597
    use super::*;
598
    use crate::read::{self, Reader};
599
    use crate::write::{ConvertError, ConvertResult};
600
    use std::collections::{hash_map, HashMap};
601
602
    impl FrameTable {
603
        /// Create a frame table by reading the data in the given section.
604
        ///
605
        /// `convert_address` is a function to convert read addresses into the `Address`
606
        /// type. For non-relocatable addresses, this function may simply return
607
        /// `Address::Constant(address)`. For relocatable addresses, it is the caller's
608
        /// responsibility to determine the symbol and addend corresponding to the address
609
        /// and return `Address::Symbol { symbol, addend }`.
610
0
        pub fn from<R, Section>(
611
0
            frame: &Section,
612
0
            convert_address: &dyn Fn(u64) -> Option<Address>,
613
0
        ) -> ConvertResult<FrameTable>
614
0
        where
615
0
            R: Reader<Offset = usize>,
616
0
            Section: read::UnwindSection<R>,
617
0
            Section::Offset: read::UnwindOffset<usize>,
618
        {
619
0
            let bases = read::BaseAddresses::default().set_eh_frame(0);
620
621
0
            let mut frame_table = FrameTable::default();
622
623
0
            let mut cie_ids = HashMap::new();
624
0
            let mut entries = frame.entries(&bases);
625
0
            while let Some(entry) = entries.next()? {
626
0
                let partial = match entry {
627
0
                    read::CieOrFde::Cie(_) => continue,
628
0
                    read::CieOrFde::Fde(partial) => partial,
629
                };
630
631
                // TODO: is it worth caching the parsed CIEs? It would be better if FDEs only
632
                // stored a reference.
633
0
                let from_fde = partial.parse(Section::cie_from_offset)?;
634
0
                let from_cie = from_fde.cie();
635
0
                let cie_id = match cie_ids.entry(from_cie.offset()) {
636
0
                    hash_map::Entry::Occupied(o) => *o.get(),
637
0
                    hash_map::Entry::Vacant(e) => {
638
0
                        let cie =
639
0
                            CommonInformationEntry::from(from_cie, frame, &bases, convert_address)?;
640
0
                        let cie_id = frame_table.add_cie(cie);
641
0
                        e.insert(cie_id);
642
0
                        cie_id
643
                    }
644
                };
645
0
                let fde = FrameDescriptionEntry::from(&from_fde, frame, &bases, convert_address)?;
646
0
                frame_table.add_fde(cie_id, fde);
647
            }
648
649
0
            Ok(frame_table)
650
0
        }
651
    }
652
653
    impl CommonInformationEntry {
654
0
        fn from<R, Section>(
655
0
            from_cie: &read::CommonInformationEntry<R>,
656
0
            frame: &Section,
657
0
            bases: &read::BaseAddresses,
658
0
            convert_address: &dyn Fn(u64) -> Option<Address>,
659
0
        ) -> ConvertResult<CommonInformationEntry>
660
0
        where
661
0
            R: Reader<Offset = usize>,
662
0
            Section: read::UnwindSection<R>,
663
0
            Section::Offset: read::UnwindOffset<usize>,
664
        {
665
0
            let mut cie = CommonInformationEntry::new(
666
0
                from_cie.encoding(),
667
0
                from_cie.code_alignment_factor() as u8,
668
0
                from_cie.data_alignment_factor() as i8,
669
0
                from_cie.return_address_register(),
670
            );
671
672
0
            cie.personality = match from_cie.personality_with_encoding() {
673
                // We treat these the same because the encoding already determines
674
                // whether it is indirect.
675
0
                Some((eh_pe, read::Pointer::Direct(p)))
676
0
                | Some((eh_pe, read::Pointer::Indirect(p))) => {
677
0
                    let address = convert_address(p).ok_or(ConvertError::InvalidAddress)?;
678
0
                    Some((eh_pe, address))
679
                }
680
0
                _ => None,
681
            };
682
0
            cie.lsda_encoding = from_cie.lsda_encoding();
683
0
            cie.fde_address_encoding = from_cie
684
0
                .fde_address_encoding()
685
0
                .unwrap_or(constants::DW_EH_PE_absptr);
686
0
            cie.signal_trampoline = from_cie.is_signal_trampoline();
687
688
0
            let mut offset = 0;
689
0
            let mut from_instructions = from_cie.instructions(frame, bases);
690
0
            while let Some(from_instruction) = from_instructions.next()? {
691
0
                if let Some(instruction) = CallFrameInstruction::from(
692
0
                    from_instruction,
693
0
                    from_cie,
694
0
                    frame,
695
0
                    convert_address,
696
0
                    &mut offset,
697
0
                )? {
698
0
                    cie.instructions.push(instruction);
699
0
                }
700
            }
701
0
            Ok(cie)
702
0
        }
703
    }
704
705
    impl FrameDescriptionEntry {
706
0
        fn from<R, Section>(
707
0
            from_fde: &read::FrameDescriptionEntry<R>,
708
0
            frame: &Section,
709
0
            bases: &read::BaseAddresses,
710
0
            convert_address: &dyn Fn(u64) -> Option<Address>,
711
0
        ) -> ConvertResult<FrameDescriptionEntry>
712
0
        where
713
0
            R: Reader<Offset = usize>,
714
0
            Section: read::UnwindSection<R>,
715
0
            Section::Offset: read::UnwindOffset<usize>,
716
        {
717
0
            let address =
718
0
                convert_address(from_fde.initial_address()).ok_or(ConvertError::InvalidAddress)?;
719
0
            let length = from_fde.len() as u32;
720
0
            let mut fde = FrameDescriptionEntry::new(address, length);
721
722
0
            match from_fde.lsda() {
723
                // We treat these the same because the encoding already determines
724
                // whether it is indirect.
725
0
                Some(read::Pointer::Direct(p)) | Some(read::Pointer::Indirect(p)) => {
726
0
                    let address = convert_address(p).ok_or(ConvertError::InvalidAddress)?;
727
0
                    fde.lsda = Some(address);
728
                }
729
0
                None => {}
730
            }
731
732
0
            let from_cie = from_fde.cie();
733
0
            let mut offset = 0;
734
0
            let mut from_instructions = from_fde.instructions(frame, bases);
735
0
            while let Some(from_instruction) = from_instructions.next()? {
736
0
                if let Some(instruction) = CallFrameInstruction::from(
737
0
                    from_instruction,
738
0
                    from_cie,
739
0
                    frame,
740
0
                    convert_address,
741
0
                    &mut offset,
742
0
                )? {
743
0
                    fde.instructions.push((offset, instruction));
744
0
                }
745
            }
746
747
0
            Ok(fde)
748
0
        }
749
    }
750
751
    impl CallFrameInstruction {
752
0
        fn from<R, Section>(
753
0
            from_instruction: read::CallFrameInstruction<R::Offset>,
754
0
            from_cie: &read::CommonInformationEntry<R>,
755
0
            frame: &Section,
756
0
            convert_address: &dyn Fn(u64) -> Option<Address>,
757
0
            offset: &mut u32,
758
0
        ) -> ConvertResult<Option<CallFrameInstruction>>
759
0
        where
760
0
            R: Reader<Offset = usize>,
761
0
            Section: read::UnwindSection<R>,
762
        {
763
0
            let convert_expression =
764
0
                |x| Expression::from(x, from_cie.encoding(), None, None, None, convert_address);
765
            // TODO: validate integer type conversions
766
0
            Ok(Some(match from_instruction {
767
                read::CallFrameInstruction::SetLoc { .. } => {
768
0
                    return Err(ConvertError::UnsupportedCfiInstruction);
769
                }
770
0
                read::CallFrameInstruction::AdvanceLoc { delta } => {
771
0
                    *offset += delta * from_cie.code_alignment_factor() as u32;
772
0
                    return Ok(None);
773
                }
774
0
                read::CallFrameInstruction::DefCfa { register, offset } => {
775
0
                    CallFrameInstruction::Cfa(register, offset as i32)
776
                }
777
                read::CallFrameInstruction::DefCfaSf {
778
0
                    register,
779
0
                    factored_offset,
780
                } => {
781
0
                    let offset = factored_offset * from_cie.data_alignment_factor();
782
0
                    CallFrameInstruction::Cfa(register, offset as i32)
783
                }
784
0
                read::CallFrameInstruction::DefCfaRegister { register } => {
785
0
                    CallFrameInstruction::CfaRegister(register)
786
                }
787
788
0
                read::CallFrameInstruction::DefCfaOffset { offset } => {
789
0
                    CallFrameInstruction::CfaOffset(offset as i32)
790
                }
791
0
                read::CallFrameInstruction::DefCfaOffsetSf { factored_offset } => {
792
0
                    let offset = factored_offset * from_cie.data_alignment_factor();
793
0
                    CallFrameInstruction::CfaOffset(offset as i32)
794
                }
795
0
                read::CallFrameInstruction::DefCfaExpression { expression } => {
796
0
                    let expression = expression.get(frame)?;
797
0
                    CallFrameInstruction::CfaExpression(convert_expression(expression)?)
798
                }
799
0
                read::CallFrameInstruction::Undefined { register } => {
800
0
                    CallFrameInstruction::Undefined(register)
801
                }
802
0
                read::CallFrameInstruction::SameValue { register } => {
803
0
                    CallFrameInstruction::SameValue(register)
804
                }
805
                read::CallFrameInstruction::Offset {
806
0
                    register,
807
0
                    factored_offset,
808
                } => {
809
0
                    let offset = factored_offset as i64 * from_cie.data_alignment_factor();
810
0
                    CallFrameInstruction::Offset(register, offset as i32)
811
                }
812
                read::CallFrameInstruction::OffsetExtendedSf {
813
0
                    register,
814
0
                    factored_offset,
815
                } => {
816
0
                    let offset = factored_offset * from_cie.data_alignment_factor();
817
0
                    CallFrameInstruction::Offset(register, offset as i32)
818
                }
819
                read::CallFrameInstruction::ValOffset {
820
0
                    register,
821
0
                    factored_offset,
822
                } => {
823
0
                    let offset = factored_offset as i64 * from_cie.data_alignment_factor();
824
0
                    CallFrameInstruction::ValOffset(register, offset as i32)
825
                }
826
                read::CallFrameInstruction::ValOffsetSf {
827
0
                    register,
828
0
                    factored_offset,
829
                } => {
830
0
                    let offset = factored_offset * from_cie.data_alignment_factor();
831
0
                    CallFrameInstruction::ValOffset(register, offset as i32)
832
                }
833
                read::CallFrameInstruction::Register {
834
0
                    dest_register,
835
0
                    src_register,
836
0
                } => CallFrameInstruction::Register(dest_register, src_register),
837
                read::CallFrameInstruction::Expression {
838
0
                    register,
839
0
                    expression,
840
                } => {
841
0
                    let expression = expression.get(frame)?;
842
0
                    CallFrameInstruction::Expression(register, convert_expression(expression)?)
843
                }
844
                read::CallFrameInstruction::ValExpression {
845
0
                    register,
846
0
                    expression,
847
                } => {
848
0
                    let expression = expression.get(frame)?;
849
0
                    CallFrameInstruction::ValExpression(register, convert_expression(expression)?)
850
                }
851
0
                read::CallFrameInstruction::Restore { register } => {
852
0
                    CallFrameInstruction::Restore(register)
853
                }
854
0
                read::CallFrameInstruction::RememberState => CallFrameInstruction::RememberState,
855
0
                read::CallFrameInstruction::RestoreState => CallFrameInstruction::RestoreState,
856
0
                read::CallFrameInstruction::ArgsSize { size } => {
857
0
                    CallFrameInstruction::ArgsSize(size as u32)
858
                }
859
0
                read::CallFrameInstruction::NegateRaState => CallFrameInstruction::NegateRaState,
860
0
                read::CallFrameInstruction::Nop => return Ok(None),
861
            }))
862
0
        }
863
    }
864
}
865
866
#[cfg(test)]
867
#[cfg(feature = "read")]
868
mod tests {
869
    use super::*;
870
    use crate::arch::X86_64;
871
    use crate::read;
872
    use crate::write::EndianVec;
873
    use crate::{LittleEndian, Vendor};
874
875
    #[test]
876
    fn test_frame_table() {
877
        for &version in &[1, 3, 4] {
878
            for &address_size in &[4, 8] {
879
                for &format in &[Format::Dwarf32, Format::Dwarf64] {
880
                    let encoding = Encoding {
881
                        format,
882
                        version,
883
                        address_size,
884
                    };
885
                    let mut frames = FrameTable::default();
886
887
                    let cie1 = CommonInformationEntry::new(encoding, 1, 8, X86_64::RA);
888
                    let cie1_id = frames.add_cie(cie1.clone());
889
                    assert_eq!(cie1_id, frames.add_cie(cie1.clone()));
890
891
                    let mut cie2 = CommonInformationEntry::new(encoding, 1, 8, X86_64::RA);
892
                    cie2.lsda_encoding = Some(constants::DW_EH_PE_absptr);
893
                    cie2.personality =
894
                        Some((constants::DW_EH_PE_absptr, Address::Constant(0x1234)));
895
                    cie2.signal_trampoline = true;
896
                    let cie2_id = frames.add_cie(cie2.clone());
897
                    assert_ne!(cie1_id, cie2_id);
898
                    assert_eq!(cie2_id, frames.add_cie(cie2.clone()));
899
900
                    let fde1 = FrameDescriptionEntry::new(Address::Constant(0x1000), 0x10);
901
                    frames.add_fde(cie1_id, fde1.clone());
902
903
                    let fde2 = FrameDescriptionEntry::new(Address::Constant(0x2000), 0x20);
904
                    frames.add_fde(cie1_id, fde2.clone());
905
906
                    let mut fde3 = FrameDescriptionEntry::new(Address::Constant(0x3000), 0x30);
907
                    fde3.lsda = Some(Address::Constant(0x3300));
908
                    frames.add_fde(cie2_id, fde3.clone());
909
910
                    let mut fde4 = FrameDescriptionEntry::new(Address::Constant(0x4000), 0x40);
911
                    fde4.lsda = Some(Address::Constant(0x4400));
912
                    frames.add_fde(cie2_id, fde4.clone());
913
914
                    let mut cie3 = CommonInformationEntry::new(encoding, 1, 8, X86_64::RA);
915
                    cie3.fde_address_encoding =
916
                        constants::DW_EH_PE_pcrel | constants::DW_EH_PE_sdata4;
917
                    cie3.lsda_encoding =
918
                        Some(constants::DW_EH_PE_pcrel | constants::DW_EH_PE_sdata4);
919
                    cie3.personality = Some((
920
                        constants::DW_EH_PE_pcrel | constants::DW_EH_PE_sdata4,
921
                        Address::Constant(0x1235),
922
                    ));
923
                    cie3.signal_trampoline = true;
924
                    let cie3_id = frames.add_cie(cie3.clone());
925
                    assert_ne!(cie2_id, cie3_id);
926
                    assert_eq!(cie3_id, frames.add_cie(cie3.clone()));
927
928
                    let mut fde5 = FrameDescriptionEntry::new(Address::Constant(0x5000), 0x50);
929
                    fde5.lsda = Some(Address::Constant(0x5500));
930
                    frames.add_fde(cie3_id, fde5.clone());
931
932
                    // Test writing `.debug_frame`.
933
                    let mut debug_frame = DebugFrame::from(EndianVec::new(LittleEndian));
934
                    frames.write_debug_frame(&mut debug_frame).unwrap();
935
936
                    let mut read_debug_frame =
937
                        read::DebugFrame::new(debug_frame.slice(), LittleEndian);
938
                    read_debug_frame.set_address_size(address_size);
939
                    let convert_frames = FrameTable::from(&read_debug_frame, &|address| {
940
                        Some(Address::Constant(address))
941
                    })
942
                    .unwrap();
943
                    assert_eq!(frames.cies, convert_frames.cies);
944
                    assert_eq!(frames.fdes.len(), convert_frames.fdes.len());
945
                    for (a, b) in frames.fdes.iter().zip(convert_frames.fdes.iter()) {
946
                        assert_eq!(a.1, b.1);
947
                    }
948
949
                    if version == 1 {
950
                        // Test writing `.eh_frame`.
951
                        let mut eh_frame = EhFrame::from(EndianVec::new(LittleEndian));
952
                        frames.write_eh_frame(&mut eh_frame).unwrap();
953
954
                        let mut read_eh_frame = read::EhFrame::new(eh_frame.slice(), LittleEndian);
955
                        read_eh_frame.set_address_size(address_size);
956
                        let convert_frames = FrameTable::from(&read_eh_frame, &|address| {
957
                            Some(Address::Constant(address))
958
                        })
959
                        .unwrap();
960
                        assert_eq!(frames.cies, convert_frames.cies);
961
                        assert_eq!(frames.fdes.len(), convert_frames.fdes.len());
962
                        for (a, b) in frames.fdes.iter().zip(convert_frames.fdes.iter()) {
963
                            assert_eq!(a.1, b.1);
964
                        }
965
                    }
966
                }
967
            }
968
        }
969
    }
970
971
    #[test]
972
    fn test_frame_instruction() {
973
        let mut expression = Expression::new();
974
        expression.op_constu(0);
975
976
        let cie_instructions = [
977
            CallFrameInstruction::Cfa(X86_64::RSP, 8),
978
            CallFrameInstruction::Offset(X86_64::RA, -8),
979
        ];
980
981
        let fde_instructions = [
982
            (0, CallFrameInstruction::Cfa(X86_64::RSP, 0)),
983
            (0, CallFrameInstruction::Cfa(X86_64::RSP, -8)),
984
            (2, CallFrameInstruction::CfaRegister(X86_64::RBP)),
985
            (4, CallFrameInstruction::CfaOffset(8)),
986
            (4, CallFrameInstruction::CfaOffset(0)),
987
            (4, CallFrameInstruction::CfaOffset(-8)),
988
            (6, CallFrameInstruction::CfaExpression(expression.clone())),
989
            (8, CallFrameInstruction::Restore(Register(1))),
990
            (8, CallFrameInstruction::Restore(Register(101))),
991
            (10, CallFrameInstruction::Undefined(Register(2))),
992
            (12, CallFrameInstruction::SameValue(Register(3))),
993
            (14, CallFrameInstruction::Offset(Register(4), 16)),
994
            (14, CallFrameInstruction::Offset(Register(104), 16)),
995
            (16, CallFrameInstruction::ValOffset(Register(5), -24)),
996
            (16, CallFrameInstruction::ValOffset(Register(5), 24)),
997
            (18, CallFrameInstruction::Register(Register(6), Register(7))),
998
            (
999
                20,
1000
                CallFrameInstruction::Expression(Register(8), expression.clone()),
1001
            ),
1002
            (
1003
                22,
1004
                CallFrameInstruction::ValExpression(Register(9), expression.clone()),
1005
            ),
1006
            (24 + 0x80, CallFrameInstruction::RememberState),
1007
            (26 + 0x280, CallFrameInstruction::RestoreState),
1008
            (28 + 0x20280, CallFrameInstruction::ArgsSize(23)),
1009
        ];
1010
1011
        let fde_instructions_aarch64 = [(0, CallFrameInstruction::NegateRaState)];
1012
1013
        for &version in &[1, 3, 4] {
1014
            for &address_size in &[4, 8] {
1015
                for &vendor in &[Vendor::Default, Vendor::AArch64] {
1016
                    for &format in &[Format::Dwarf32, Format::Dwarf64] {
1017
                        let encoding = Encoding {
1018
                            format,
1019
                            version,
1020
                            address_size,
1021
                        };
1022
                        let mut frames = FrameTable::default();
1023
1024
                        let mut cie = CommonInformationEntry::new(encoding, 2, 8, X86_64::RA);
1025
                        for i in &cie_instructions {
1026
                            cie.add_instruction(i.clone());
1027
                        }
1028
                        let cie_id = frames.add_cie(cie);
1029
1030
                        let mut fde = FrameDescriptionEntry::new(Address::Constant(0x1000), 0x10);
1031
                        for (o, i) in &fde_instructions {
1032
                            fde.add_instruction(*o, i.clone());
1033
                        }
1034
                        frames.add_fde(cie_id, fde);
1035
1036
                        if vendor == Vendor::AArch64 {
1037
                            let mut fde =
1038
                                FrameDescriptionEntry::new(Address::Constant(0x2000), 0x10);
1039
                            for (o, i) in &fde_instructions_aarch64 {
1040
                                fde.add_instruction(*o, i.clone());
1041
                            }
1042
                            frames.add_fde(cie_id, fde);
1043
                        }
1044
1045
                        let mut debug_frame = DebugFrame::from(EndianVec::new(LittleEndian));
1046
                        frames.write_debug_frame(&mut debug_frame).unwrap();
1047
1048
                        let mut read_debug_frame =
1049
                            read::DebugFrame::new(debug_frame.slice(), LittleEndian);
1050
                        read_debug_frame.set_address_size(address_size);
1051
                        read_debug_frame.set_vendor(vendor);
1052
                        let frames = FrameTable::from(&read_debug_frame, &|address| {
1053
                            Some(Address::Constant(address))
1054
                        })
1055
                        .unwrap();
1056
1057
                        assert_eq!(
1058
                            &frames.cies.get_index(0).unwrap().instructions,
1059
                            &cie_instructions
1060
                        );
1061
                        assert_eq!(&frames.fdes[0].1.instructions, &fde_instructions);
1062
                        if vendor == Vendor::AArch64 {
1063
                            assert_eq!(&frames.fdes[1].1.instructions, &fde_instructions_aarch64);
1064
                        }
1065
                    }
1066
                }
1067
            }
1068
        }
1069
    }
1070
}