Fix libcall relocations for precompiled modules (#5608)
* Fix libcall relocations for precompiled modules This commit fixes some asserts and support for relocation libcalls in precompiled modules loaded from disk. In doing so this reworks how mmaps are managed for files from disk. All non-file-backed `Mmap` entries are read/write but file-backed versions were readonly. This commit changes this such that all `Mmap` objects, even if they're file-backed, start as read/write. The file-based versions all use copy-on-write to preserve the private-ness of the mapping. This is not functionally intended to change anything. Instead this should have some more memory writable after a module is loaded but the text section, for example, is still left as read/execute when loading is finished. Additionally this makes modules compiled in memory more consistent with modules loaded from disk. * Update a comment * Force images to become readonly during publish This marks compiled images as entirely readonly during the `CodeMemory::publish` step which happens just before the text section becomes executable. This ensures that all images, no matter where they come from, are guaranteed frozen before they start executing.
This commit is contained in:
@@ -68,11 +68,6 @@ impl MmapVec {
|
||||
Ok(MmapVec::new(mmap, len))
|
||||
}
|
||||
|
||||
/// Returns whether the original mmap was created from a readonly mapping.
|
||||
pub fn is_readonly(&self) -> bool {
|
||||
self.mmap.is_readonly()
|
||||
}
|
||||
|
||||
/// Splits the collection into two at the given index.
|
||||
///
|
||||
/// Returns a separate `MmapVec` which shares the underlying mapping, but
|
||||
@@ -95,24 +90,28 @@ impl MmapVec {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// Makes the specified `range` within this `mmap` to be read/write.
|
||||
pub unsafe fn make_writable(&self, range: Range<usize>) -> Result<()> {
|
||||
self.mmap
|
||||
.make_writable(range.start + self.range.start..range.end + self.range.start)
|
||||
}
|
||||
|
||||
/// Makes the specified `range` within this `mmap` to be read/execute.
|
||||
pub unsafe fn make_executable(
|
||||
&self,
|
||||
range: Range<usize>,
|
||||
enable_branch_protection: bool,
|
||||
) -> Result<()> {
|
||||
assert!(range.start <= range.end);
|
||||
assert!(range.end <= self.range.len());
|
||||
self.mmap.make_executable(
|
||||
range.start + self.range.start..range.end + self.range.start,
|
||||
enable_branch_protection,
|
||||
)
|
||||
}
|
||||
|
||||
/// Makes the specified `range` within this `mmap` to be read-only.
|
||||
pub unsafe fn make_readonly(&self, range: Range<usize>) -> Result<()> {
|
||||
assert!(range.start <= range.end);
|
||||
assert!(range.end <= self.range.len());
|
||||
self.mmap
|
||||
.make_readonly(range.start + self.range.start..range.end + self.range.start)
|
||||
}
|
||||
|
||||
/// Returns the underlying file that this mmap is mapping, if present.
|
||||
pub fn original_file(&self) -> Option<&Arc<File>> {
|
||||
self.mmap.original_file()
|
||||
@@ -135,7 +134,6 @@ impl Deref for MmapVec {
|
||||
|
||||
impl DerefMut for MmapVec {
|
||||
fn deref_mut(&mut self) -> &mut [u8] {
|
||||
debug_assert!(!self.is_readonly());
|
||||
// SAFETY: The underlying mmap is protected behind an `Arc` which means
|
||||
// there there can be many references to it. We are guaranteed, though,
|
||||
// that each reference to the underlying `mmap` has a disjoint `range`
|
||||
|
||||
Reference in New Issue
Block a user