mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-04 04:08:19 +00:00
centralize mmap logic
This commit is contained in:
parent
baa0dcc359
commit
764637594e
2 changed files with 40 additions and 83 deletions
|
@ -13,7 +13,7 @@ use roc_mono::ir::OptLevel;
|
|||
use std::cmp::Ordering;
|
||||
use std::convert::TryFrom;
|
||||
use std::ffi::CStr;
|
||||
use std::fs::{self, File};
|
||||
use std::fs;
|
||||
use std::mem;
|
||||
use std::os::raw::c_char;
|
||||
use std::path::Path;
|
||||
|
@ -204,11 +204,8 @@ fn dummy_lib_is_up_to_date(
|
|||
return false;
|
||||
}
|
||||
|
||||
let exec_file = fs::File::open(dummy_lib_path).unwrap_or_else(|e| internal_error!("{}", e));
|
||||
let exec_mmap = unsafe { Mmap::map(&exec_file).unwrap_or_else(|e| internal_error!("{}", e)) };
|
||||
let exec_data = &*exec_mmap;
|
||||
|
||||
let object = object::File::parse(exec_data).unwrap();
|
||||
let dummy_lib = open_mmap(dummy_lib_path);
|
||||
let object = object::File::parse(&*dummy_lib).unwrap();
|
||||
|
||||
// the user may have been cross-compiling.
|
||||
// The dynhost on disk must match our current target
|
||||
|
@ -524,9 +521,7 @@ fn preprocess_elf_and_macho(
|
|||
) {
|
||||
let total_start = Instant::now();
|
||||
let exec_parsing_start = total_start;
|
||||
let exec_file = fs::File::open(host_exe_path).unwrap_or_else(|e| internal_error!("{}", e));
|
||||
let exec_mmap = unsafe { Mmap::map(&exec_file).unwrap_or_else(|e| internal_error!("{}", e)) };
|
||||
let exec_data = &*exec_mmap;
|
||||
let exec_data = &*open_mmap(host_exe_path);
|
||||
let exec_obj = match object::File::parse(exec_data) {
|
||||
Ok(obj) => obj,
|
||||
Err(err) => {
|
||||
|
@ -788,7 +783,7 @@ fn preprocess_elf_and_macho(
|
|||
let scanning_dynamic_deps_duration;
|
||||
let platform_gen_start;
|
||||
|
||||
let (out_mmap, out_file) = match target.binary_format {
|
||||
let out_mmap = match target.binary_format {
|
||||
target_lexicon::BinaryFormat::Elf => match target
|
||||
.endianness()
|
||||
.unwrap_or(target_lexicon::Endianness::Little)
|
||||
|
@ -914,7 +909,6 @@ fn preprocess_elf_and_macho(
|
|||
.unwrap_or_else(|e| internal_error!("{}", e));
|
||||
// Also drop files to to ensure data is fully written here.
|
||||
drop(out_mmap);
|
||||
drop(out_file);
|
||||
let flushing_data_duration = flushing_data_start.elapsed();
|
||||
|
||||
let total_duration = total_start.elapsed();
|
||||
|
@ -954,7 +948,7 @@ fn gen_macho_le(
|
|||
macho_load_so_offset: usize,
|
||||
_target: &Triple,
|
||||
_verbose: bool,
|
||||
) -> (MmapMut, File) {
|
||||
) -> MmapMut {
|
||||
// Just adding some extra context/useful info here.
|
||||
// I was talking to Jakub from the Zig team about macho linking and here are some useful comments:
|
||||
// 1) Macho WILL run fine with multiple text segments (and theoretically data segments).
|
||||
|
@ -1002,18 +996,7 @@ fn gen_macho_le(
|
|||
|
||||
md.exec_len = exec_data.len() as u64 + md.added_byte_count;
|
||||
|
||||
let out_file = fs::OpenOptions::new()
|
||||
.read(true)
|
||||
.write(true)
|
||||
.create(true)
|
||||
.truncate(true)
|
||||
.open(out_filename)
|
||||
.unwrap_or_else(|e| internal_error!("{}", e));
|
||||
out_file
|
||||
.set_len(md.exec_len)
|
||||
.unwrap_or_else(|e| internal_error!("{}", e));
|
||||
let mut out_mmap =
|
||||
unsafe { MmapMut::map_mut(&out_file).unwrap_or_else(|e| internal_error!("{}", e)) };
|
||||
let mut out_mmap = open_mmap_mut(out_filename, md.exec_len as usize);
|
||||
let end_of_cmds = size_of_cmds + mem::size_of_val(exec_header);
|
||||
|
||||
// "Delete" the dylib load command - by copying all the bytes before it
|
||||
|
@ -1499,7 +1482,7 @@ fn gen_macho_le(
|
|||
// cmd_loc should be where the last offset ended
|
||||
md.macho_cmd_loc = offset as u64;
|
||||
|
||||
(out_mmap, out_file)
|
||||
out_mmap
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
|
@ -1512,7 +1495,7 @@ fn gen_elf_le(
|
|||
dynamic_lib_count: usize,
|
||||
shared_lib_index: usize,
|
||||
verbose: bool,
|
||||
) -> (MmapMut, File) {
|
||||
) -> MmapMut {
|
||||
let exec_header = load_struct_inplace::<elf::FileHeader64<LittleEndian>>(exec_data, 0);
|
||||
let ph_offset = exec_header.e_phoff.get(NativeEndian);
|
||||
let ph_ent_size = exec_header.e_phentsize.get(NativeEndian);
|
||||
|
@ -1540,18 +1523,7 @@ fn gen_elf_le(
|
|||
let physical_shift_start = ph_end as u64;
|
||||
|
||||
md.exec_len = exec_data.len() as u64 + md.added_byte_count;
|
||||
let out_file = fs::OpenOptions::new()
|
||||
.read(true)
|
||||
.write(true)
|
||||
.create(true)
|
||||
.truncate(true)
|
||||
.open(preprocessed_path)
|
||||
.unwrap_or_else(|e| internal_error!("{}", e));
|
||||
out_file
|
||||
.set_len(md.exec_len)
|
||||
.unwrap_or_else(|e| internal_error!("{}", e));
|
||||
let mut out_mmap =
|
||||
unsafe { MmapMut::map_mut(&out_file).unwrap_or_else(|e| internal_error!("{}", e)) };
|
||||
let mut out_mmap = open_mmap_mut(preprocessed_path, md.exec_len as usize);
|
||||
|
||||
out_mmap[..ph_end].copy_from_slice(&exec_data[..ph_end]);
|
||||
|
||||
|
@ -1827,7 +1799,7 @@ fn gen_elf_le(
|
|||
}
|
||||
file_header.e_phnum = endian::U16::new(LittleEndian, ph_num + added_header_count as u16);
|
||||
|
||||
(out_mmap, out_file)
|
||||
out_mmap
|
||||
}
|
||||
|
||||
// fn scan_macho_dynamic_deps(
|
||||
|
@ -2063,8 +2035,7 @@ fn surgery_elf_and_macho(
|
|||
target: &Triple,
|
||||
) {
|
||||
let app_parsing_start = Instant::now();
|
||||
let app_file = fs::File::open(app_path).unwrap_or_else(|e| internal_error!("{}", e));
|
||||
let app_mmap = unsafe { Mmap::map(&app_file).unwrap_or_else(|e| internal_error!("{}", e)) };
|
||||
let app_mmap = open_mmap(app_path);
|
||||
let app_data = &*app_mmap;
|
||||
let app_obj = match object::File::parse(app_data) {
|
||||
Ok(obj) => obj,
|
||||
|
@ -2082,19 +2053,8 @@ fn surgery_elf_and_macho(
|
|||
let loading_metadata_duration = loading_metadata_start.elapsed();
|
||||
|
||||
let load_and_mmap_start = Instant::now();
|
||||
let exec_file = fs::OpenOptions::new()
|
||||
.read(true)
|
||||
.write(true)
|
||||
.open(executable_path)
|
||||
.unwrap_or_else(|e| internal_error!("{}", e));
|
||||
|
||||
let max_out_len = md.exec_len + app_data.len() as u64 + md.load_align_constraint;
|
||||
exec_file
|
||||
.set_len(max_out_len)
|
||||
.unwrap_or_else(|e| internal_error!("{}", e));
|
||||
|
||||
let mut exec_mmap =
|
||||
unsafe { MmapMut::map_mut(&exec_file).unwrap_or_else(|e| internal_error!("{}", e)) };
|
||||
let mut exec_mmap = open_mmap_mut(executable_path, max_out_len as usize);
|
||||
|
||||
let load_and_mmap_duration = load_and_mmap_start.elapsed();
|
||||
let out_gen_start = Instant::now();
|
||||
|
@ -2131,10 +2091,6 @@ fn surgery_elf_and_macho(
|
|||
// Also drop files to to ensure data is fully written here.
|
||||
drop(exec_mmap);
|
||||
|
||||
exec_file
|
||||
.set_len(offset as u64 + 1)
|
||||
.unwrap_or_else(|e| internal_error!("{}", e));
|
||||
drop(exec_file);
|
||||
let flushing_data_duration = flushing_data_start.elapsed();
|
||||
|
||||
// Make sure the final executable has permision to execute.
|
||||
|
@ -3080,6 +3036,29 @@ fn load_structs_inplace_mut<T>(bytes: &mut [u8], offset: usize, count: usize) ->
|
|||
body
|
||||
}
|
||||
|
||||
pub(crate) fn open_mmap(path: &Path) -> Mmap {
|
||||
let in_file = std::fs::OpenOptions::new()
|
||||
.read(true)
|
||||
.open(path)
|
||||
.unwrap_or_else(|e| internal_error!("{e}"));
|
||||
|
||||
unsafe { Mmap::map(&in_file).unwrap_or_else(|e| internal_error!("{e}")) }
|
||||
}
|
||||
|
||||
pub(crate) fn open_mmap_mut(path: &Path, length: usize) -> MmapMut {
|
||||
let out_file = std::fs::OpenOptions::new()
|
||||
.read(true)
|
||||
.write(true)
|
||||
.create(true)
|
||||
.open(path)
|
||||
.unwrap_or_else(|e| internal_error!("{e}"));
|
||||
out_file
|
||||
.set_len(length as u64)
|
||||
.unwrap_or_else(|e| internal_error!("{e}"));
|
||||
|
||||
unsafe { MmapMut::map_mut(&out_file).unwrap_or_else(|e| internal_error!("{e}")) }
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
|
@ -5,7 +5,7 @@ use std::{
|
|||
};
|
||||
|
||||
use bincode::{deserialize_from, serialize_into};
|
||||
use memmap2::{Mmap, MmapMut};
|
||||
use memmap2::MmapMut;
|
||||
use object::{
|
||||
pe::{
|
||||
self, ImageFileHeader, ImageImportDescriptor, ImageNtHeaders64, ImageSectionHeader,
|
||||
|
@ -19,7 +19,9 @@ use serde::{Deserialize, Serialize};
|
|||
use roc_collections::MutMap;
|
||||
use roc_error_macros::internal_error;
|
||||
|
||||
use crate::{generate_dylib::APP_DLL, load_struct_inplace, load_struct_inplace_mut};
|
||||
use crate::{
|
||||
generate_dylib::APP_DLL, load_struct_inplace, load_struct_inplace_mut, open_mmap, open_mmap_mut,
|
||||
};
|
||||
|
||||
/// The metadata stores information about/from the host .exe because
|
||||
///
|
||||
|
@ -663,30 +665,6 @@ impl Preprocessor {
|
|||
}
|
||||
}
|
||||
|
||||
fn open_mmap(path: &Path) -> Mmap {
|
||||
let in_file = std::fs::OpenOptions::new()
|
||||
.read(true)
|
||||
.create(true)
|
||||
.open(path)
|
||||
.unwrap_or_else(|e| internal_error!("{e}"));
|
||||
|
||||
unsafe { Mmap::map(&in_file).unwrap_or_else(|e| internal_error!("{e}")) }
|
||||
}
|
||||
|
||||
fn open_mmap_mut(path: &Path, length: usize) -> MmapMut {
|
||||
let out_file = std::fs::OpenOptions::new()
|
||||
.read(true)
|
||||
.write(true)
|
||||
.create(true)
|
||||
.open(path)
|
||||
.unwrap_or_else(|e| internal_error!("{e}"));
|
||||
out_file
|
||||
.set_len(length as u64)
|
||||
.unwrap_or_else(|e| internal_error!("{e}"));
|
||||
|
||||
unsafe { MmapMut::map_mut(&out_file).unwrap_or_else(|e| internal_error!("{e}")) }
|
||||
}
|
||||
|
||||
/// Find the place in the executable where the thunks for our dummy .dll are stored
|
||||
fn find_thunks_start_offset(
|
||||
executable: &[u8],
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue