"Unpublish" code memory (transition it from executable to read/writable). This may be used to edit the code image, as long as the overall size of the memory remains the same. Note the hazards inherent in editing code that may have been executed: any stack frames with PC still active in this code must be suspended (e.g., called into a hostcall that is then invoking this method, or async-yielded) a
(&mut self)
| 511 | /// |
| 512 | /// If this fails, then the memory remains executable. |
| 513 | pub fn unpublish(&mut self) -> Result<()> { |
| 514 | assert!(self.published); |
| 515 | self.published = false; |
| 516 | |
| 517 | if self.text().is_empty() { |
| 518 | return Ok(()); |
| 519 | } |
| 520 | |
| 521 | if self.custom_unpublish()? { |
| 522 | return Ok(()); |
| 523 | } |
| 524 | |
| 525 | if !self.mmap.supports_virtual_memory() { |
| 526 | bail!("this target requires virtual memory to be enabled"); |
| 527 | } |
| 528 | |
| 529 | // SAFETY: we are guaranteed by our own safety conditions that |
| 530 | // we have exclusive access to this code and can change its |
| 531 | // permissions (removing the execute bit) without causing |
| 532 | // problems. |
| 533 | #[cfg(has_virtual_memory)] |
| 534 | unsafe { |
| 535 | self.mmap.make_readwrite(0..self.mmap.len())?; |
| 536 | } |
| 537 | |
| 538 | // Note that we do *not* unregister: we expect unpublish |
| 539 | // to be used for temporary edits, so we want the |
| 540 | // registration to "stick" after the initial publish and |
| 541 | // not toggle in subsequent unpublish/publish cycles. |
| 542 | |
| 543 | Ok(()) |
| 544 | } |
| 545 | |
| 546 | fn custom_unpublish(&mut self) -> Result<bool> { |
| 547 | if let Some(mem) = self.custom_code_memory.as_ref() { |
no test coverage detected