add test that combines a zig platform with a dll

This commit is contained in:
Folkert 2022-09-18 14:11:46 +02:00
parent 61366f0d43
commit 6005ed0664
No known key found for this signature in database
GPG key ID: 1F17F6FFD112B97C
4 changed files with 73 additions and 50 deletions

View file

@ -398,6 +398,8 @@ mod test {
use object::read::pe::PeFile64;
use object::{pe, Object};
use indoc::indoc;
use super::*;
#[test]
@ -574,27 +576,23 @@ mod test {
assert_eq!(actual, 7)
}
#[test]
fn increase_number_of_sections() {
fn increase_number_of_sections_help(input_data: &[u8], output_file: &Path) {
use object::read::pe::ImageNtHeaders;
let dos_header = pe::ImageDosHeader::parse(PE_DYNHOST).unwrap();
let dos_header = pe::ImageDosHeader::parse(input_data).unwrap();
let mut offset = dos_header.nt_headers_offset().into();
let header_offset = offset;
let number_of_sections_offset = header_offset + 4 + 2;
let sections_len_old = u16::from_le_bytes(
PE_DYNHOST[number_of_sections_offset as usize..][..2]
input_data[number_of_sections_offset as usize..][..2]
.try_into()
.unwrap(),
);
let new_sections = [*b"placehol", *b"aaaabbbb"];
let dir = tempfile::tempdir().unwrap();
let path = dir.path().join("test.exe");
let mmap = Preprocessor::preprocess(&path, PE_DYNHOST, &new_sections);
let mmap = Preprocessor::preprocess(output_file, input_data, &new_sections);
let data = mmap.deref();
@ -622,61 +620,53 @@ mod test {
assert_eq!(new_sections, names.as_slice());
}
#[test]
fn increase_number_of_sections() {
let dir = tempfile::tempdir().unwrap();
let path = dir.path().join("test.exe");
increase_number_of_sections_help(PE_DYNHOST, &path);
}
#[test]
fn preprocess_zig_host() {
let host_zig = include_str!("../trivial_host.zig");
let app_zig = include_str!("../trivial_app.zig");
let host_zig = indoc!(
r#"
extern fn double(u8) u8;
pub fn main() u8 {
return double(42);
}
"#
);
let app_zig = indoc!(
r#"
export fn double(n: u8) u8 {
return n + n;
}
"#
);
let zig = std::env::var("ROC_ZIG").unwrap_or_else(|_| "zig".into());
let dir = tempfile::tempdir().unwrap();
let dir = dir.path();
std::fs::write(dir.join("trivial_host.zig"), host_zig.as_bytes()).unwrap();
std::fs::write(dir.join("trivial_app.zig"), app_zig.as_bytes()).unwrap();
std::fs::write(dir.join("host.zig"), host_zig.as_bytes()).unwrap();
std::fs::write(dir.join("app.zig"), app_zig.as_bytes()).unwrap();
// here we would like to do
//
// let dylib_bytes = crate::generate_dylib::synthetic_dll(&["double".into(), "triple".into()]);
// std::fs::write(dir.join("roc-cheaty-lib.dll"), dylib_bytes).unwrap();
//
// but on windows, this is not so simple. To link a .dll into an .exe we need an additional
// .lib file, a so-called "import library". These are normally generated by the linker, and
// based on some googling there is other tooling on windows that can also generate them
// from a .dll. There is however very little information on what they should contain.
//
// Jakub intends to implement generating the .lib files in pure zig in the near(ish)
// future, so if we can wait then we can use the zig source to create our own logic for
// a very simple .lib file
let output = std::process::Command::new(&zig)
.current_dir(dir)
.args(&[
"build-lib",
"trivial_app.zig",
"-target",
"x86_64-windows-gnu",
"--strip",
"-OReleaseFast",
])
.output()
.unwrap();
if !output.status.success() {
use std::io::Write;
std::io::stdout().write_all(&output.stdout).unwrap();
std::io::stderr().write_all(&output.stderr).unwrap();
panic!();
}
let dylib_bytes = crate::generate_dylib::synthetic_dll(&["double".into()]);
std::fs::write(dir.join("libapp.obj"), dylib_bytes).unwrap();
let output = std::process::Command::new(&zig)
.current_dir(dir)
.args(&[
"build-exe",
"trivial_host.zig",
"trivial_app.lib",
"-fPIE",
"libapp.obj",
"host.zig",
"-lc",
"-target",
"x86_64-windows-gnu",
"--strip",
@ -691,7 +681,32 @@ mod test {
std::io::stdout().write_all(&output.stdout).unwrap();
std::io::stderr().write_all(&output.stderr).unwrap();
panic!();
panic!("zig build-exe failed");
}
let data = std::fs::read(dir.join("host.exe")).unwrap();
increase_number_of_sections_help(&data, &dir.join("dynhost.exe"));
let output = std::process::Command::new(&zig)
.current_dir(dir)
.args(&[
"build-obj",
"app.zig",
"-target",
"x86_64-windows-gnu",
"--strip",
"-OReleaseFast",
])
.output()
.unwrap();
if !output.status.success() {
use std::io::Write;
std::io::stdout().write_all(&output.stdout).unwrap();
std::io::stderr().write_all(&output.stderr).unwrap();
panic!("zig build-obj failed");
}
}
}