mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-26 21:39:07 +00:00
refactor
This commit is contained in:
parent
540d3c29f9
commit
9bbe0e029f
1 changed files with 48 additions and 74 deletions
|
@ -35,7 +35,10 @@ struct PeMetadata {
|
|||
|
||||
optional_header_offset: usize,
|
||||
|
||||
/// Symbols that the host imports, like roc__mainForHost_1_exposed_generic
|
||||
imports: Vec<String>,
|
||||
|
||||
/// Symbols that the host exports, like roc_alloc
|
||||
exports: MutMap<String, i64>,
|
||||
|
||||
dynamic_relocations: DynamicRelocationsPe,
|
||||
|
@ -361,7 +364,7 @@ pub(crate) fn surgery_pe(
|
|||
.map(|s| (s.name, s.offset_in_section as u64))
|
||||
.collect();
|
||||
|
||||
redirect_dummy_dll_functions_help(executable, &symbols, &md.imports, md.thunks_start_offset);
|
||||
redirect_dummy_dll_functions(executable, &symbols, &md.imports, md.thunks_start_offset);
|
||||
|
||||
remove_dummy_dll_import_table(
|
||||
executable,
|
||||
|
@ -738,12 +741,7 @@ fn mmap_mut(path: &Path, length: usize) -> MmapMut {
|
|||
unsafe { MmapMut::map_mut(&out_file).unwrap_or_else(|e| internal_error!("{e}")) }
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn redirect_dummy_dll_functions(
|
||||
executable: &mut [u8],
|
||||
dynamic_relocations: &DynamicRelocationsPe,
|
||||
function_definition_vas: &[(String, u64)],
|
||||
) {
|
||||
fn find_thunks_start_offset(exec_data: &[u8], dynamic_relocations: &DynamicRelocationsPe) -> usize {
|
||||
// The host executable contains indirect calls to functions that the host should provide
|
||||
//
|
||||
// 14000105d: e8 8e 27 00 00 call 0x1400037f0
|
||||
|
@ -770,14 +768,13 @@ fn redirect_dummy_dll_functions(
|
|||
// sources:
|
||||
//
|
||||
// - https://learn.microsoft.com/en-us/archive/msdn-magazine/2002/february/inside-windows-win32-portable-executable-file-format-in-detail
|
||||
|
||||
const W: usize = std::mem::size_of::<ImageImportDescriptor>();
|
||||
|
||||
let dummy_import_desc_start = dynamic_relocations.imports_offset_in_file as usize
|
||||
+ W * dynamic_relocations.dummy_import_index as usize;
|
||||
|
||||
let dummy_import_desc =
|
||||
load_struct_inplace::<ImageImportDescriptor>(executable, dummy_import_desc_start);
|
||||
load_struct_inplace::<ImageImportDescriptor>(exec_data, dummy_import_desc_start);
|
||||
|
||||
// per https://en.wikibooks.org/wiki/X86_Disassembly/Windows_Executable_Files#The_Import_directory,
|
||||
//
|
||||
|
@ -791,87 +788,35 @@ fn redirect_dummy_dll_functions(
|
|||
let dummy_thunks_address_va = dummy_import_desc.first_thunk;
|
||||
let dummy_thunks_address = dummy_thunks_address_va.get(LE);
|
||||
|
||||
dbg!(dummy_thunks_address);
|
||||
|
||||
let object = object::read::pe::PeFile64::parse(&*executable).unwrap();
|
||||
let imports: Vec<_> = object
|
||||
.imports()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.filter(|import| import.library() == b"roc-cheaty-lib.dll")
|
||||
.map(|import| {
|
||||
std::str::from_utf8(import.name())
|
||||
.unwrap_or_default()
|
||||
.to_owned()
|
||||
})
|
||||
.collect();
|
||||
|
||||
let data: &[u8] = executable;
|
||||
|
||||
let dos_header = object::pe::ImageDosHeader::parse(data).unwrap();
|
||||
let dos_header = object::pe::ImageDosHeader::parse(exec_data).unwrap();
|
||||
let mut offset = dos_header.nt_headers_offset().into();
|
||||
|
||||
use object::read::pe::ImageNtHeaders;
|
||||
let (nt_headers, _data_directories) = ImageNtHeaders64::parse(data, &mut offset).unwrap();
|
||||
let sections = nt_headers.sections(data, offset).unwrap();
|
||||
let (nt_headers, _data_directories) = ImageNtHeaders64::parse(exec_data, &mut offset).unwrap();
|
||||
let sections = nt_headers.sections(exec_data, offset).unwrap();
|
||||
|
||||
// so we look at what section this virtual address is in
|
||||
// find the section the virtual address is in
|
||||
let (section_va, offset_in_file) = sections
|
||||
.iter()
|
||||
.find_map(|section| {
|
||||
section.pe_data_containing(data, dummy_thunks_address).map(
|
||||
|(_section_data, section_va)| (section_va, section.pointer_to_raw_data.get(LE)),
|
||||
)
|
||||
section
|
||||
.pe_data_containing(exec_data, dummy_thunks_address)
|
||||
.map(|(_section_data, section_va)| {
|
||||
(section_va, section.pointer_to_raw_data.get(LE))
|
||||
})
|
||||
})
|
||||
.expect("Invalid thunk virtual address");
|
||||
|
||||
// and get the offset in the file of 0x1400037f0
|
||||
let thunks_start_offset = (dummy_thunks_address - section_va + offset_in_file) as usize;
|
||||
|
||||
dbg!(&imports, thunks_start_offset);
|
||||
|
||||
redirect_dummy_dll_functions_help(
|
||||
executable,
|
||||
function_definition_vas,
|
||||
&imports,
|
||||
thunks_start_offset,
|
||||
)
|
||||
(dummy_thunks_address - section_va + offset_in_file) as usize
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn redirect_dummy_dll_functions_help(
|
||||
fn redirect_dummy_dll_functions(
|
||||
executable: &mut [u8],
|
||||
function_definition_vas: &[(String, u64)],
|
||||
imports: &[String],
|
||||
thunks_start_offset: usize,
|
||||
) {
|
||||
// The host executable contains indirect calls to functions that the host should provide
|
||||
//
|
||||
// 14000105d: e8 8e 27 00 00 call 0x1400037f0
|
||||
// 140001062: 89 c3 mov ebx,eax
|
||||
// 140001064: b1 21 mov cl,0x21
|
||||
//
|
||||
// This `call` is an indirect call (see https://www.felixcloutier.com/x86/call, our call starts
|
||||
// with 0xe8, so it is relative) In other words, at runtime the program will go to 0x1400037f0,
|
||||
// read a pointer-sized value there, and jump to that location.
|
||||
//
|
||||
// The 0x1400037f0 virtual address is located in the .rdata section
|
||||
//
|
||||
// Sections:
|
||||
// Idx Name Size VMA LMA File off Algn
|
||||
// 0 .text 0000169a 0000000140001000 0000000140001000 00000600 2**4
|
||||
// CONTENTS, ALLOC, LOAD, READONLY, CODE
|
||||
// 1 .rdata 00000ba8 0000000140003000 0000000140003000 00001e00 2**4
|
||||
// CONTENTS, ALLOC, LOAD, READONLY, DATA
|
||||
//
|
||||
// Our task is then to put a valid function pointer at 0x1400037f0. The value should be a
|
||||
// virtual address pointing at the start of a function (which must be located in an executable
|
||||
// section)
|
||||
//
|
||||
// sources:
|
||||
//
|
||||
// - https://learn.microsoft.com/en-us/archive/msdn-magazine/2002/february/inside-windows-win32-portable-executable-file-format-in-detail
|
||||
|
||||
// it could be that a symbol exposed by the app is not used by the host. We must skip unused symbols
|
||||
let mut targets = function_definition_vas.iter();
|
||||
'outer: for (i, name) in imports.iter().enumerate() {
|
||||
|
@ -1385,6 +1330,35 @@ mod test {
|
|||
increase_number_of_sections_help(PE_DYNHOST, &new_sections, &path);
|
||||
}
|
||||
|
||||
fn redirect_dummy_dll_functions_test(
|
||||
executable: &mut [u8],
|
||||
dynamic_relocations: &DynamicRelocationsPe,
|
||||
function_definition_vas: &[(String, u64)],
|
||||
) {
|
||||
let object = object::read::pe::PeFile64::parse(&*executable).unwrap();
|
||||
let imports: Vec<_> = object
|
||||
.imports()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.filter(|import| import.library() == b"roc-cheaty-lib.dll")
|
||||
.map(|import| {
|
||||
std::str::from_utf8(import.name())
|
||||
.unwrap_or_default()
|
||||
.to_owned()
|
||||
})
|
||||
.collect();
|
||||
|
||||
// and get the offset in the file of 0x1400037f0
|
||||
let thunks_start_offset = find_thunks_start_offset(executable, dynamic_relocations);
|
||||
|
||||
redirect_dummy_dll_functions(
|
||||
executable,
|
||||
function_definition_vas,
|
||||
&imports,
|
||||
thunks_start_offset,
|
||||
)
|
||||
}
|
||||
|
||||
fn link_zig_host_and_app_help(dir: &Path) {
|
||||
use object::ObjectSection;
|
||||
|
||||
|
@ -1658,7 +1632,7 @@ mod test {
|
|||
.into_iter()
|
||||
.map(|s| (s.name, s.offset_in_section as u64))
|
||||
.collect();
|
||||
redirect_dummy_dll_functions(&mut app, &dynamic_relocations, &symbols);
|
||||
redirect_dummy_dll_functions_test(&mut app, &dynamic_relocations, &symbols);
|
||||
|
||||
remove_dummy_dll_import_table(
|
||||
&mut app,
|
||||
|
@ -1917,7 +1891,7 @@ mod test {
|
|||
.into_iter()
|
||||
.map(|s| (s.name, s.offset_in_section as u64))
|
||||
.collect();
|
||||
redirect_dummy_dll_functions(&mut app, &dynamic_relocations, &symbols);
|
||||
redirect_dummy_dll_functions_test(&mut app, &dynamic_relocations, &symbols);
|
||||
|
||||
remove_dummy_dll_import_table(
|
||||
&mut app,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue