mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-27 05:49:08 +00:00
update the length of imports in the data directory after removing our dummy dll
This commit is contained in:
parent
6005ed0664
commit
841c478b98
1 changed files with 59 additions and 15 deletions
|
@ -4,6 +4,7 @@ use memmap2::{Mmap, MmapMut};
|
||||||
use object::{
|
use object::{
|
||||||
pe::{ImageImportDescriptor, ImageNtHeaders64, ImageSectionHeader, ImageThunkData64},
|
pe::{ImageImportDescriptor, ImageNtHeaders64, ImageSectionHeader, ImageThunkData64},
|
||||||
read::pe::ImportTable,
|
read::pe::ImportTable,
|
||||||
|
LittleEndian as LE,
|
||||||
};
|
};
|
||||||
use roc_collections::MutMap;
|
use roc_collections::MutMap;
|
||||||
use roc_error_macros::internal_error;
|
use roc_error_macros::internal_error;
|
||||||
|
@ -58,6 +59,10 @@ struct DynamicRelocationsPe {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
imports_offset_in_file: u32,
|
imports_offset_in_file: u32,
|
||||||
|
|
||||||
|
/// Offset in the file of the data directories
|
||||||
|
#[allow(dead_code)]
|
||||||
|
data_directories_offset_in_file: u32,
|
||||||
|
|
||||||
/// The dummy .dll is the `dummy_import_index`th import of the host .exe
|
/// The dummy .dll is the `dummy_import_index`th import of the host .exe
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
dummy_import_index: u32,
|
dummy_import_index: u32,
|
||||||
|
@ -71,8 +76,6 @@ impl DynamicRelocationsPe {
|
||||||
fn find_roc_dummy_dll(
|
fn find_roc_dummy_dll(
|
||||||
import_table: &ImportTable,
|
import_table: &ImportTable,
|
||||||
) -> object::read::Result<Option<(ImageImportDescriptor, u32)>> {
|
) -> object::read::Result<Option<(ImageImportDescriptor, u32)>> {
|
||||||
use object::LittleEndian as LE;
|
|
||||||
|
|
||||||
let mut index = 0;
|
let mut index = 0;
|
||||||
let mut it = import_table.descriptors()?;
|
let mut it = import_table.descriptors()?;
|
||||||
while let Some(descriptor) = it.next()? {
|
while let Some(descriptor) = it.next()? {
|
||||||
|
@ -95,8 +98,6 @@ impl DynamicRelocationsPe {
|
||||||
import_table: &ImportTable,
|
import_table: &ImportTable,
|
||||||
roc_dll_descriptor: &ImageImportDescriptor,
|
roc_dll_descriptor: &ImageImportDescriptor,
|
||||||
) -> object::read::Result<()> {
|
) -> object::read::Result<()> {
|
||||||
use object::LittleEndian as LE;
|
|
||||||
|
|
||||||
// offset of first thunk from the start of the section
|
// offset of first thunk from the start of the section
|
||||||
let thunk_start_offset =
|
let thunk_start_offset =
|
||||||
roc_dll_descriptor.original_first_thunk.get(LE) - self.section_virtual_address;
|
roc_dll_descriptor.original_first_thunk.get(LE) - self.section_virtual_address;
|
||||||
|
@ -127,10 +128,12 @@ impl DynamicRelocationsPe {
|
||||||
fn new_help(data: &[u8]) -> object::read::Result<Self> {
|
fn new_help(data: &[u8]) -> object::read::Result<Self> {
|
||||||
use object::pe;
|
use object::pe;
|
||||||
use object::read::pe::ImageNtHeaders;
|
use object::read::pe::ImageNtHeaders;
|
||||||
use object::LittleEndian as LE;
|
|
||||||
|
|
||||||
let dos_header = pe::ImageDosHeader::parse(data)?;
|
let dos_header = pe::ImageDosHeader::parse(data)?;
|
||||||
let mut offset = dos_header.nt_headers_offset().into();
|
let mut offset = dos_header.nt_headers_offset().into();
|
||||||
|
let data_directories_offset_in_file =
|
||||||
|
offset as u32 + std::mem::size_of::<ImageNtHeaders64>() as u32;
|
||||||
|
|
||||||
let (nt_headers, data_directories) = ImageNtHeaders64::parse(data, &mut offset)?;
|
let (nt_headers, data_directories) = ImageNtHeaders64::parse(data, &mut offset)?;
|
||||||
let sections = nt_headers.sections(data, offset)?;
|
let sections = nt_headers.sections(data, offset)?;
|
||||||
|
|
||||||
|
@ -169,6 +172,7 @@ impl DynamicRelocationsPe {
|
||||||
section_virtual_address: section_va,
|
section_virtual_address: section_va,
|
||||||
section_offset_in_file: offset_in_file,
|
section_offset_in_file: offset_in_file,
|
||||||
imports_offset_in_file,
|
imports_offset_in_file,
|
||||||
|
data_directories_offset_in_file,
|
||||||
dummy_import_index,
|
dummy_import_index,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -181,15 +185,33 @@ impl DynamicRelocationsPe {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn remove_dummy_dll_import_table(
|
fn remove_dummy_dll_import_table(
|
||||||
data: &mut [u8],
|
data: &mut [u8],
|
||||||
|
data_directories_offset_in_file: u32,
|
||||||
imports_offset_in_file: u32,
|
imports_offset_in_file: u32,
|
||||||
dummy_import_index: u32,
|
dummy_import_index: u32,
|
||||||
) {
|
) {
|
||||||
|
use object::pe;
|
||||||
|
|
||||||
const W: usize = std::mem::size_of::<ImageImportDescriptor>();
|
const W: usize = std::mem::size_of::<ImageImportDescriptor>();
|
||||||
|
|
||||||
|
// clear out the import table entry. we do implicitly assume that our dummy .dll is the last
|
||||||
let start = imports_offset_in_file as usize + W * dummy_import_index as usize;
|
let start = imports_offset_in_file as usize + W * dummy_import_index as usize;
|
||||||
for b in data[start..][..W].iter_mut() {
|
for b in data[start..][..W].iter_mut() {
|
||||||
*b = 0;
|
*b = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// in the data directories, update the length of the imports (there is one fewer now)
|
||||||
|
let dir = load_struct_inplace_mut::<pe::ImageDataDirectory>(
|
||||||
|
data,
|
||||||
|
data_directories_offset_in_file as usize
|
||||||
|
+ object::pe::IMAGE_DIRECTORY_ENTRY_IMPORT
|
||||||
|
* std::mem::size_of::<pe::ImageDataDirectory>(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let current = dir.size.get(LE);
|
||||||
|
dir.size.set(
|
||||||
|
LE,
|
||||||
|
current - std::mem::size_of::<pe::ImageImportDescriptor>() as u32,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Preprocess the host's .exe to make space for extra sections
|
/// Preprocess the host's .exe to make space for extra sections
|
||||||
|
@ -229,7 +251,6 @@ impl Preprocessor {
|
||||||
fn new(data: &[u8], extra_sections: &[[u8; 8]]) -> Self {
|
fn new(data: &[u8], extra_sections: &[[u8; 8]]) -> Self {
|
||||||
use object::pe;
|
use object::pe;
|
||||||
use object::read::pe::ImageNtHeaders;
|
use object::read::pe::ImageNtHeaders;
|
||||||
use object::LittleEndian as LE;
|
|
||||||
|
|
||||||
let dos_header = pe::ImageDosHeader::parse(data).unwrap_or_else(|e| internal_error!("{e}"));
|
let dos_header = pe::ImageDosHeader::parse(data).unwrap_or_else(|e| internal_error!("{e}"));
|
||||||
let mut offset = dos_header.nt_headers_offset().into();
|
let mut offset = dos_header.nt_headers_offset().into();
|
||||||
|
@ -319,8 +340,6 @@ impl Preprocessor {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fix(&self, result: &mut MmapMut, extra_sections: &[[u8; 8]]) {
|
fn fix(&self, result: &mut MmapMut, extra_sections: &[[u8; 8]]) {
|
||||||
use object::LittleEndian as LE;
|
|
||||||
|
|
||||||
self.write_dummy_sections(result, extra_sections);
|
self.write_dummy_sections(result, extra_sections);
|
||||||
|
|
||||||
// update the size of the headers
|
// update the size of the headers
|
||||||
|
@ -396,7 +415,7 @@ mod test {
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
use object::read::pe::PeFile64;
|
use object::read::pe::PeFile64;
|
||||||
use object::{pe, Object};
|
use object::{pe, LittleEndian as LE, Object, U32};
|
||||||
|
|
||||||
use indoc::indoc;
|
use indoc::indoc;
|
||||||
|
|
||||||
|
@ -535,17 +554,38 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn remove_dummy_dll_import() {
|
fn remove_dummy_dll_import() {
|
||||||
|
let object = PeFile64::parse(PE_DYNHOST).unwrap();
|
||||||
|
let before = object
|
||||||
|
.data_directories()
|
||||||
|
.get(pe::IMAGE_DIRECTORY_ENTRY_IMPORT)
|
||||||
|
.unwrap()
|
||||||
|
.size
|
||||||
|
.get(LE);
|
||||||
|
|
||||||
let dynamic_relocations = DynamicRelocationsPe::new(PE_DYNHOST);
|
let dynamic_relocations = DynamicRelocationsPe::new(PE_DYNHOST);
|
||||||
let mut data = PE_DYNHOST.to_vec();
|
let mut data = PE_DYNHOST.to_vec();
|
||||||
|
|
||||||
remove_dummy_dll_import_table(
|
remove_dummy_dll_import_table(
|
||||||
&mut data,
|
&mut data,
|
||||||
|
dynamic_relocations.data_directories_offset_in_file,
|
||||||
dynamic_relocations.imports_offset_in_file,
|
dynamic_relocations.imports_offset_in_file,
|
||||||
dynamic_relocations.dummy_import_index,
|
dynamic_relocations.dummy_import_index,
|
||||||
);
|
);
|
||||||
|
|
||||||
// parse and check that it's really gone
|
// parse and check that it's really gone
|
||||||
let object = object::File::parse(data.as_slice()).unwrap();
|
let object = PeFile64::parse(data.as_slice()).unwrap();
|
||||||
|
|
||||||
|
let after = object
|
||||||
|
.data_directories()
|
||||||
|
.get(pe::IMAGE_DIRECTORY_ENTRY_IMPORT)
|
||||||
|
.unwrap()
|
||||||
|
.size
|
||||||
|
.get(LE);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
before - after,
|
||||||
|
std::mem::size_of::<pe::ImageImportDescriptor>() as _
|
||||||
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
object
|
object
|
||||||
|
@ -576,7 +616,11 @@ mod test {
|
||||||
assert_eq!(actual, 7)
|
assert_eq!(actual, 7)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn increase_number_of_sections_help(input_data: &[u8], output_file: &Path) {
|
fn increase_number_of_sections_help(
|
||||||
|
input_data: &[u8],
|
||||||
|
new_sections: &[[u8; 8]],
|
||||||
|
output_file: &Path,
|
||||||
|
) {
|
||||||
use object::read::pe::ImageNtHeaders;
|
use object::read::pe::ImageNtHeaders;
|
||||||
|
|
||||||
let dos_header = pe::ImageDosHeader::parse(input_data).unwrap();
|
let dos_header = pe::ImageDosHeader::parse(input_data).unwrap();
|
||||||
|
@ -590,9 +634,7 @@ mod test {
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let new_sections = [*b"placehol", *b"aaaabbbb"];
|
let mmap = Preprocessor::preprocess(output_file, input_data, new_sections);
|
||||||
|
|
||||||
let mmap = Preprocessor::preprocess(output_file, input_data, &new_sections);
|
|
||||||
|
|
||||||
let data = mmap.deref();
|
let data = mmap.deref();
|
||||||
|
|
||||||
|
@ -625,7 +667,9 @@ mod test {
|
||||||
let dir = tempfile::tempdir().unwrap();
|
let dir = tempfile::tempdir().unwrap();
|
||||||
let path = dir.path().join("test.exe");
|
let path = dir.path().join("test.exe");
|
||||||
|
|
||||||
increase_number_of_sections_help(PE_DYNHOST, &path);
|
let new_sections = [*b"placehol", *b"aaaabbbb"];
|
||||||
|
|
||||||
|
increase_number_of_sections_help(PE_DYNHOST, &new_sections, &path);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue