Pushes the unwind information for a function into this builder. The function being described must be located at `function_offset` within the text section itself, and the function's size is specified by `function_len`. The `info` should come from Cranelift. and is handled here depending on its flavor.
(&mut self, function_offset: u64, function_len: u64, info: &'a UnwindInfo)
| 265 | /// The `info` should come from Cranelift. and is handled here depending on |
| 266 | /// its flavor. |
| 267 | fn push(&mut self, function_offset: u64, function_len: u64, info: &'a UnwindInfo) { |
| 268 | match info { |
| 269 | // Windows unwind information is stored in two locations: |
| 270 | // |
| 271 | // * First is the actual unwinding information which is stored |
| 272 | // in the `.xdata` section. This is where `info`'s emitted |
| 273 | // information will go into. |
| 274 | // * Second are pointers to connect all this unwind information, |
| 275 | // stored in the `.pdata` section. The `.pdata` section is an |
| 276 | // array of `RUNTIME_FUNCTION` structures. |
| 277 | // |
| 278 | // Due to how these will be loaded at runtime the `.pdata` isn't |
| 279 | // actually assembled byte-wise here. Instead that's deferred to |
| 280 | // happen later during `write_windows_unwind_info` which will apply |
| 281 | // a further offset to `unwind_address`. |
| 282 | // |
| 283 | // FIXME: in theory we could "intern" the `unwind_info` value |
| 284 | // here within the `.xdata` section. Most of our unwind |
| 285 | // information for functions is probably pretty similar in which |
| 286 | // case the `.xdata` could be quite small and `.pdata` could |
| 287 | // have multiple functions point to the same unwinding |
| 288 | // information. |
| 289 | UnwindInfo::WindowsX64(info) => { |
| 290 | let unwind_size = info.emit_size(); |
| 291 | let mut unwind_info = vec![0; unwind_size]; |
| 292 | info.emit(&mut unwind_info); |
| 293 | |
| 294 | // `.xdata` entries are always 4-byte aligned |
| 295 | while self.windows_xdata.len() % 4 != 0 { |
| 296 | self.windows_xdata.push(0x00); |
| 297 | } |
| 298 | let unwind_address = self.windows_xdata.len(); |
| 299 | self.windows_xdata.extend_from_slice(&unwind_info); |
| 300 | |
| 301 | // Record a `RUNTIME_FUNCTION` which this will point to. |
| 302 | self.windows_pdata.push(RUNTIME_FUNCTION { |
| 303 | begin: u32::try_from(function_offset).unwrap(), |
| 304 | end: u32::try_from(function_offset + function_len).unwrap(), |
| 305 | unwind_address: u32::try_from(unwind_address).unwrap(), |
| 306 | }); |
| 307 | } |
| 308 | |
| 309 | // See https://learn.microsoft.com/en-us/cpp/build/arm64-exception-handling |
| 310 | UnwindInfo::WindowsArm64(info) => { |
| 311 | let code_words = info.code_words(); |
| 312 | let mut unwind_codes = vec![0; (code_words * 4) as usize]; |
| 313 | info.emit(&mut unwind_codes); |
| 314 | |
| 315 | // `.xdata` entries are always 4-byte aligned |
| 316 | while self.windows_xdata.len() % 4 != 0 { |
| 317 | self.windows_xdata.push(0x00); |
| 318 | } |
| 319 | |
| 320 | // First word: |
| 321 | // 0-17: Function Length |
| 322 | // 18-19: Version (must be 0) |
| 323 | // 20: X bit (is exception data present?) |
| 324 | // 21: E bit (has single packed epilogue?) |
no test coverage detected