From 081dcb793cb8777e8ade5afb5e3dc095dd0581c0 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Fri, 11 Mar 2022 15:32:54 -0800 Subject: [PATCH 01/55] define --- crates/libs/define/Cargo.toml | 17 +++++++++++++++++ crates/libs/define/src/lib.rs | 7 +++++++ crates/libs/metagen/Cargo.toml | 8 ++++++++ crates/libs/metagen/src/lib.rs | 4 ++++ crates/libs/windows/Cargo.toml | 2 ++ crates/libs/windows/src/core/mod.rs | 4 ++++ crates/tests/define/Cargo.toml | 14 ++++++++++++++ crates/tests/define/src/lib.rs | 1 + crates/tests/define/tests/test.rs | 21 +++++++++++++++++++++ crates/tools/windows/src/main.rs | 2 ++ 10 files changed, 80 insertions(+) create mode 100644 crates/libs/define/Cargo.toml create mode 100644 crates/libs/define/src/lib.rs create mode 100644 crates/libs/metagen/Cargo.toml create mode 100644 crates/libs/metagen/src/lib.rs create mode 100644 crates/tests/define/Cargo.toml create mode 100644 crates/tests/define/src/lib.rs create mode 100644 crates/tests/define/tests/test.rs diff --git a/crates/libs/define/Cargo.toml b/crates/libs/define/Cargo.toml new file mode 100644 index 0000000000..814b4e8d09 --- /dev/null +++ b/crates/libs/define/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "windows-define" +version = "0.33.0" +authors = ["Microsoft"] +edition = "2018" +license = "MIT OR Apache-2.0" +description = "The define macro for the windows crate" +repository = "https://github.com/microsoft/windows-rs" + +[package.metadata.docs.rs] +default-target = "x86_64-pc-windows-msvc" +targets = [] + +[lib] +proc-macro = true + +[dependencies] diff --git a/crates/libs/define/src/lib.rs b/crates/libs/define/src/lib.rs new file mode 100644 index 0000000000..1ed84a7250 --- /dev/null +++ b/crates/libs/define/src/lib.rs @@ -0,0 +1,7 @@ +// The define macro should be called by a build script to define types and +// generate a corresponding OUT_DIR/crate_name.rs and OUT_DIR/crate_name.winmd + +#[proc_macro] +pub fn define(_stream: proc_macro::TokenStream) -> proc_macro::TokenStream { + proc_macro::TokenStream::new() +} diff --git a/crates/libs/metagen/Cargo.toml b/crates/libs/metagen/Cargo.toml new file mode 100644 index 0000000000..955b071437 --- /dev/null +++ b/crates/libs/metagen/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "windows-metagen" +version = "0.33.0" +authors = ["Microsoft"] +edition = "2018" +license = "MIT OR Apache-2.0" +description = "Metadata generation support for the windows crate" +repository = "https://github.com/microsoft/windows-rs" diff --git a/crates/libs/metagen/src/lib.rs b/crates/libs/metagen/src/lib.rs new file mode 100644 index 0000000000..d160caa04c --- /dev/null +++ b/crates/libs/metagen/src/lib.rs @@ -0,0 +1,4 @@ +// Bootstrap the winmd generation here... +pub fn test() { + +} diff --git a/crates/libs/windows/Cargo.toml b/crates/libs/windows/Cargo.toml index 879a3ddaa2..03837802f2 100644 --- a/crates/libs/windows/Cargo.toml +++ b/crates/libs/windows/Cargo.toml @@ -47,6 +47,7 @@ windows_x86_64_gnu = { path = "../../targets/x86_64_gnu", version = "0.33.0" } [dependencies] windows-implement = { path = "../implement", version = "0.33.0", optional = true } windows-interface = { path = "../interface", version = "0.33.0", optional = true } +windows-define = { path = "../define", version = "0.33.0", optional = true } [features] default = [] @@ -54,6 +55,7 @@ deprecated = [] alloc = [] implement = ["windows-implement"] interface = ["windows-interface"] +define = ["windows-define"] AI = [] AI_MachineLearning = ["AI"] AI_MachineLearning_Preview = ["AI_MachineLearning"] diff --git a/crates/libs/windows/src/core/mod.rs b/crates/libs/windows/src/core/mod.rs index 6bbb68e1b1..2f3a6d2de7 100644 --- a/crates/libs/windows/src/core/mod.rs +++ b/crates/libs/windows/src/core/mod.rs @@ -91,6 +91,10 @@ pub use windows_implement::implement; #[cfg(feature = "interface")] pub use windows_interface::interface; +#[doc(hidden)] +#[cfg(feature = "define")] +pub use windows_define::define; + extern "C" { #[doc(hidden)] pub fn memcmp(left: *const core::ffi::c_void, right: *const core::ffi::c_void, len: usize) -> i32; diff --git a/crates/tests/define/Cargo.toml b/crates/tests/define/Cargo.toml new file mode 100644 index 0000000000..2ded106d6a --- /dev/null +++ b/crates/tests/define/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "test_define" +version = "0.0.0" +authors = ["Microsoft"] +edition = "2018" + +[dependencies.windows] +path = "../../libs/windows" +features = [ + "define", +] + +[dependencies.windows-metagen] +path = "../../libs/metagen" diff --git a/crates/tests/define/src/lib.rs b/crates/tests/define/src/lib.rs new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/crates/tests/define/src/lib.rs @@ -0,0 +1 @@ + diff --git a/crates/tests/define/tests/test.rs b/crates/tests/define/tests/test.rs new file mode 100644 index 0000000000..1d3b2729ac --- /dev/null +++ b/crates/tests/define/tests/test.rs @@ -0,0 +1,21 @@ +#[test] +fn define() { + windows::core::define! { + mod Microsoft { + mod Windows { + struct StructType { x: i32, y: i32 } + + interface IInterfaceType { + fn Method(&self) -> StructType; + } + + class ClassType : IInterfaceType; + } + } + } +} + +#[test] +fn metagen() { + windows_metagen::test(); +} diff --git a/crates/tools/windows/src/main.rs b/crates/tools/windows/src/main.rs index 5df06e2216..0f99ffa8e0 100644 --- a/crates/tools/windows/src/main.rs +++ b/crates/tools/windows/src/main.rs @@ -70,6 +70,7 @@ windows_x86_64_gnu = { path = "../../targets/x86_64_gnu", version = "0.33.0" } [dependencies] windows-implement = { path = "../implement", version = "0.33.0", optional = true } windows-interface = { path = "../interface", version = "0.33.0", optional = true } +windows-define = { path = "../define", version = "0.33.0", optional = true } [features] default = [] @@ -77,6 +78,7 @@ deprecated = [] alloc = [] implement = ["windows-implement"] interface = ["windows-interface"] +define = ["windows-define"] "# .as_bytes(), ) From e52c863adc32d2491efd61c340f77f0c038e8020 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Fri, 11 Mar 2022 18:13:47 -0800 Subject: [PATCH 02/55] headers --- crates/libs/metagen/src/lib.rs | 186 +++++++++++++++++++++++++++++++++ 1 file changed, 186 insertions(+) diff --git a/crates/libs/metagen/src/lib.rs b/crates/libs/metagen/src/lib.rs index d160caa04c..510f0d451a 100644 --- a/crates/libs/metagen/src/lib.rs +++ b/crates/libs/metagen/src/lib.rs @@ -1,4 +1,190 @@ // Bootstrap the winmd generation here... +// https://en.wikipedia.org/wiki/Portable_Executable +// https://docs.microsoft.com/en-us/windows/win32/debug/pe-format +// https://docs.microsoft.com/en-us/archive/msdn-magazine/2002/february/inside-windows-win32-portable-executable-file-format-in-detail + +use std::mem::*; +use std::slice::*; + pub fn test() { + let mut buffer = Vec::::new(); + let dos = ImageDosHeader::new(); + write(&mut buffer, &dos); + let pe = ImageNtHeaderPlus::new(); + write(&mut buffer, &pe); + let sections = ImageSectionHeader::new(); + write(&mut buffer, §ions); + let cor = ImageCorHeader::new(); + write(&mut buffer, &cor); + + std::fs::write("/git/test.winmd", buffer).unwrap(); +} + +fn write(buffer: &mut Vec::, value: &T) { + unsafe { + buffer.extend_from_slice(from_raw_parts(value as *const _ as _, size_of::())); + } +} + +impl ImageDosHeader { + fn new() -> Self { + Self { + signature: IMAGE_DOS_SIGNATURE, + lfanew: size_of::() as _, + ..Default::default() + } + } +} + +impl ImageNtHeaderPlus { + fn new() -> Self { + let mut new = Self { + signature: IMAGE_NT_SIGNATURE, + ..Default::default() + }; + new.optional_header.data_directory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR as usize].virtual_address = 0; + new + } +} + +impl ImageSectionHeader { + fn new() -> Self { + Self { + ..Default::default() + } + } +} + +impl ImageCorHeader { + fn new() -> Self { + Self { + cb : size_of::() as _, + ..Default::default() + } + } +} + +const IMAGE_DOS_SIGNATURE: u16 = 0x5A4D; // Hi Mark! +const IMAGE_NT_SIGNATURE: u32 = 0x4550; // PE00 +const MAGIC_PE32: u16 = 0x10B; +const MAGIC_PE32PLUS: u16 = 0x20B; +const IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR: u32 = 14; +const STORAGE_MAGIC_SIG: u32 = 0x424A_5342; + +#[repr(C)] +#[derive(Default)] +struct ImageDosHeader { + signature: u16, + cblp: u16, + cp: u16, + crlc: u16, + cparhdr: u16, + minalloc: u16, + maxalloc: u16, + ss: u16, + sp: u16, + csum: u16, + ip: u16, + cs: u16, + lfarlc: u16, + ovno: u16, + res: [u16; 4], + oemid: u16, + oeminfo: u16, + res2: [u16; 10], + lfanew: i32, +} + +#[repr(C)] +#[derive(Default)] +struct ImageFileHeader { + machine: u16, + number_of_sections: u16, + time_date_stamp: u32, + pointer_to_symbol_table: u32, + number_of_symbols: u32, + size_of_optional_header: u16, + characteristics: u16, +} + +#[repr(C)] +#[derive(Default)] +struct ImageDataDirectory { + virtual_address: u32, + size: u32, +} + +#[repr(C)] +#[derive(Default)] +struct ImageNtHeaderPlus { + signature: u32, + file_header: ImageFileHeader, + optional_header: ImageOptionalHeaderPlus, +} + +#[repr(C)] +#[derive(Default)] +struct ImageOptionalHeaderPlus { + magic: u16, + major_linker_version: u8, + minor_linker_version: u8, + size_of_code: u32, + size_of_initialized_data: u32, + size_of_uninitialized_data: u32, + address_of_entry_point: u32, + base_of_code: u32, + image_base: u64, + section_alignment: u32, + file_alignment: u32, + major_operating_system_version: u16, + minor_operating_system_version: u16, + major_image_version: u16, + minor_image_version: u16, + major_subsystem_version: u16, + minor_subsystem_version: u16, + win32_version_value: u32, + size_of_image: u32, + size_of_headers: u32, + check_sum: u32, + subsystem: u16, + dll_characteristics: u16, + size_of_stack_reserve: u64, + size_of_stack_commit: u64, + size_of_heap_reserve: u64, + size_of_heap_commit: u64, + loader_flags: u32, + number_of_rva_and_sizes: u32, + data_directory: [ImageDataDirectory; 16], +} + +#[repr(C)] +#[derive(Default)] +struct ImageSectionHeader { + name: [u8; 8], + physical_address_or_virtual_size: u32, + virtual_address: u32, + size_of_raw_data: u32, + pointer_to_raw_data: u32, + pointer_to_relocations: u32, + pointer_to_line_numbers: u32, + number_of_relocations: u16, + number_of_line_numbers: u16, + characteristics: u32, +} +#[repr(C)] +#[derive(Default)] +struct ImageCorHeader { + cb: u32, + major_runtime_version: u16, + minor_runtime_version: u16, + meta_data: ImageDataDirectory, + flags: u32, + entry_point_token_or_entry_point_rva: u32, + resources: ImageDataDirectory, + strong_name_signature: ImageDataDirectory, + code_manager_table: ImageDataDirectory, + vtable_fixups: ImageDataDirectory, + export_address_table_jumps: ImageDataDirectory, + managed_native_header: ImageDataDirectory, } From 255e2c17cd90bbbfd896082a88988a41a27f098c Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Sat, 12 Mar 2022 23:20:42 -0800 Subject: [PATCH 03/55] headers --- crates/libs/metagen/src/lib.rs | 108 ++++++++++++++++++++++----------- 1 file changed, 73 insertions(+), 35 deletions(-) diff --git a/crates/libs/metagen/src/lib.rs b/crates/libs/metagen/src/lib.rs index 510f0d451a..fc972faa83 100644 --- a/crates/libs/metagen/src/lib.rs +++ b/crates/libs/metagen/src/lib.rs @@ -2,6 +2,7 @@ // https://en.wikipedia.org/wiki/Portable_Executable // https://docs.microsoft.com/en-us/windows/win32/debug/pe-format // https://docs.microsoft.com/en-us/archive/msdn-magazine/2002/february/inside-windows-win32-portable-executable-file-format-in-detail +// https://github.com/dotnet/runtime/blob/94c0a7c13d158eb79d27223f474ec8f8db747f11/src/coreclr/dlls/mscorpe/pewriter.cpp use std::mem::*; use std::slice::*; @@ -10,7 +11,7 @@ pub fn test() { let mut buffer = Vec::::new(); let dos = ImageDosHeader::new(); write(&mut buffer, &dos); - let pe = ImageNtHeaderPlus::new(); + let pe = ImageNtHeader::new(); write(&mut buffer, &pe); let sections = ImageSectionHeader::new(); write(&mut buffer, §ions); @@ -18,6 +19,9 @@ pub fn test() { write(&mut buffer, &cor); std::fs::write("/git/test.winmd", buffer).unwrap(); + + assert!(size_of::() == 0x40); + assert!(size_of::() == 0xE0); } fn write(buffer: &mut Vec::, value: &T) { @@ -29,24 +33,64 @@ fn write(buffer: &mut Vec::, value: &T) { impl ImageDosHeader { fn new() -> Self { Self { - signature: IMAGE_DOS_SIGNATURE, - lfanew: size_of::() as _, + magic: 0x5A4D, // MZ + lfarlc: 0x40, // file address of relocation table + lfanew: size_of::() as _, // file address of next header ..Default::default() } } } -impl ImageNtHeaderPlus { +impl ImageNtHeader { fn new() -> Self { let mut new = Self { - signature: IMAGE_NT_SIGNATURE, - ..Default::default() + signature: 0x4550, // PE\0\0 + file_header: ImageFileHeader::new(), + optional_header: ImageOptionalHeader::new(), }; - new.optional_header.data_directory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR as usize].virtual_address = 0; + new.optional_header.data_directory[14].virtual_address = 0; new } } +impl ImageFileHeader { + fn new() -> Self { + Self { + machine: 0x14C, // x86 + number_of_sections: 2, + size_of_optional_header: size_of::() as _, + characteristics: 0x2102, // DLL + ..Default::default() + } + } +} + +impl ImageOptionalHeader { + fn new() -> Self { + Self { + magic: 0x10B, // PE32 + major_linker_version: 0xB, + size_of_initialized_data: 0x400, + image_base: 0x400000, + section_alignment: 0x1000, + file_alignment: 0x200, + major_operating_system_version: 6, + minor_operating_system_version: 2, + major_subsystem_version: 6, + minor_subsystem_version: 2, + size_of_image: 0, // TODO: needs filling in + size_of_headers: 0x200, + subsystem: 3, // console + dll_characteristics: 0x540, + size_of_stack_reserve: 0x100000, + size_of_heap_reserve: 0x1000, + loader_flags: 0x100000, + number_of_rva_and_sizes: 0x10, + ..Default::default() + } + } +} + impl ImageSectionHeader { fn new() -> Self { Self { @@ -64,17 +108,10 @@ impl ImageCorHeader { } } -const IMAGE_DOS_SIGNATURE: u16 = 0x5A4D; // Hi Mark! -const IMAGE_NT_SIGNATURE: u32 = 0x4550; // PE00 -const MAGIC_PE32: u16 = 0x10B; -const MAGIC_PE32PLUS: u16 = 0x20B; -const IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR: u32 = 14; -const STORAGE_MAGIC_SIG: u32 = 0x424A_5342; - #[repr(C)] #[derive(Default)] struct ImageDosHeader { - signature: u16, + magic: u16, cblp: u16, cp: u16, crlc: u16, @@ -95,18 +132,6 @@ struct ImageDosHeader { lfanew: i32, } -#[repr(C)] -#[derive(Default)] -struct ImageFileHeader { - machine: u16, - number_of_sections: u16, - time_date_stamp: u32, - pointer_to_symbol_table: u32, - number_of_symbols: u32, - size_of_optional_header: u16, - characteristics: u16, -} - #[repr(C)] #[derive(Default)] struct ImageDataDirectory { @@ -116,15 +141,27 @@ struct ImageDataDirectory { #[repr(C)] #[derive(Default)] -struct ImageNtHeaderPlus { +struct ImageNtHeader { signature: u32, file_header: ImageFileHeader, - optional_header: ImageOptionalHeaderPlus, + optional_header: ImageOptionalHeader, +} + +#[repr(C)] +#[derive(Default)] +struct ImageFileHeader { + machine: u16, + number_of_sections: u16, + time_date_stamp: u32, + pointer_to_symbol_table: u32, + number_of_symbols: u32, + size_of_optional_header: u16, + characteristics: u16, } #[repr(C)] #[derive(Default)] -struct ImageOptionalHeaderPlus { +struct ImageOptionalHeader { magic: u16, major_linker_version: u8, minor_linker_version: u8, @@ -133,7 +170,8 @@ struct ImageOptionalHeaderPlus { size_of_uninitialized_data: u32, address_of_entry_point: u32, base_of_code: u32, - image_base: u64, + base_of_data: u32, + image_base: u32, section_alignment: u32, file_alignment: u32, major_operating_system_version: u16, @@ -148,10 +186,10 @@ struct ImageOptionalHeaderPlus { check_sum: u32, subsystem: u16, dll_characteristics: u16, - size_of_stack_reserve: u64, - size_of_stack_commit: u64, - size_of_heap_reserve: u64, - size_of_heap_commit: u64, + size_of_stack_reserve: u32, + size_of_stack_commit: u32, + size_of_heap_reserve: u32, + size_of_heap_commit: u32, loader_flags: u32, number_of_rva_and_sizes: u32, data_directory: [ImageDataDirectory; 16], From 182423691fddce7ee2c253a164d70cef91188a02 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Sun, 13 Mar 2022 19:45:28 -0700 Subject: [PATCH 04/55] COM --- crates/libs/metagen/src/lib.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/libs/metagen/src/lib.rs b/crates/libs/metagen/src/lib.rs index fc972faa83..dd50fd2720 100644 --- a/crates/libs/metagen/src/lib.rs +++ b/crates/libs/metagen/src/lib.rs @@ -48,7 +48,10 @@ impl ImageNtHeader { file_header: ImageFileHeader::new(), optional_header: ImageOptionalHeader::new(), }; - new.optional_header.data_directory[14].virtual_address = 0; + new.optional_header.data_directory[14] = ImageDataDirectory { + virtual_address: 0x1000, + size: 0x48, + }; new } } From 4b8cbd68b5c56dc5e25c20f77bf376d4c15fe656 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Tue, 15 Mar 2022 13:33:07 -0700 Subject: [PATCH 05/55] merge --- crates/libs/define/Cargo.toml | 2 +- crates/libs/metagen/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/libs/define/Cargo.toml b/crates/libs/define/Cargo.toml index 814b4e8d09..c3097b2a2c 100644 --- a/crates/libs/define/Cargo.toml +++ b/crates/libs/define/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "windows-define" -version = "0.33.0" +version = "0.34.0" authors = ["Microsoft"] edition = "2018" license = "MIT OR Apache-2.0" diff --git a/crates/libs/metagen/Cargo.toml b/crates/libs/metagen/Cargo.toml index 955b071437..9d1be536a7 100644 --- a/crates/libs/metagen/Cargo.toml +++ b/crates/libs/metagen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "windows-metagen" -version = "0.33.0" +version = "0.34.0" authors = ["Microsoft"] edition = "2018" license = "MIT OR Apache-2.0" From a319dfcba78ab79dc67203ecf1285a68f53acb58 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Tue, 15 Mar 2022 13:59:58 -0700 Subject: [PATCH 06/55] simpler --- crates/libs/metagen/src/lib.rs | 110 ++++++++++++--------------------- 1 file changed, 41 insertions(+), 69 deletions(-) diff --git a/crates/libs/metagen/src/lib.rs b/crates/libs/metagen/src/lib.rs index dd50fd2720..937fbad9e1 100644 --- a/crates/libs/metagen/src/lib.rs +++ b/crates/libs/metagen/src/lib.rs @@ -9,66 +9,51 @@ use std::slice::*; pub fn test() { let mut buffer = Vec::::new(); - let dos = ImageDosHeader::new(); + let dos = DosHeader::new(); write(&mut buffer, &dos); - let pe = ImageNtHeader::new(); + let pe = PeHeader::new(); write(&mut buffer, &pe); - let sections = ImageSectionHeader::new(); + let optional = OptionalHeader::new(); + write(&mut buffer, &optional); + let sections = SectionHeader::new(); write(&mut buffer, §ions); - let cor = ImageCorHeader::new(); - write(&mut buffer, &cor); + let clr = ClrHeader::new(); + write(&mut buffer, &clr); std::fs::write("/git/test.winmd", buffer).unwrap(); - - assert!(size_of::() == 0x40); - assert!(size_of::() == 0xE0); } -fn write(buffer: &mut Vec::, value: &T) { +fn write(buffer: &mut Vec, value: &T) { unsafe { - buffer.extend_from_slice(from_raw_parts(value as *const _ as _, size_of::())); + buffer.extend_from_slice(from_raw_parts(value as *const _ as _, size_of::())); } } -impl ImageDosHeader { +impl DosHeader { fn new() -> Self { Self { - magic: 0x5A4D, // MZ - lfarlc: 0x40, // file address of relocation table + magic: 0x5A4D, // MZ + lfarlc: 0x40, // file address of relocation table lfanew: size_of::() as _, // file address of next header ..Default::default() } } } -impl ImageNtHeader { - fn new() -> Self { - let mut new = Self { - signature: 0x4550, // PE\0\0 - file_header: ImageFileHeader::new(), - optional_header: ImageOptionalHeader::new(), - }; - new.optional_header.data_directory[14] = ImageDataDirectory { - virtual_address: 0x1000, - size: 0x48, - }; - new - } -} - -impl ImageFileHeader { +impl PeHeader { fn new() -> Self { Self { - machine: 0x14C, // x86 + signature: 0x4550, // PE\0\0 + machine: 0x14C, // x86 number_of_sections: 2, - size_of_optional_header: size_of::() as _, + size_of_optional_header: size_of::() as _, characteristics: 0x2102, // DLL ..Default::default() } } } -impl ImageOptionalHeader { +impl OptionalHeader { fn new() -> Self { Self { magic: 0x10B, // PE32 @@ -81,7 +66,6 @@ impl ImageOptionalHeader { minor_operating_system_version: 2, major_subsystem_version: 6, minor_subsystem_version: 2, - size_of_image: 0, // TODO: needs filling in size_of_headers: 0x200, subsystem: 3, // console dll_characteristics: 0x540, @@ -94,26 +78,21 @@ impl ImageOptionalHeader { } } -impl ImageSectionHeader { +impl SectionHeader { fn new() -> Self { - Self { - ..Default::default() - } + Self { ..Default::default() } } } -impl ImageCorHeader { +impl ClrHeader { fn new() -> Self { - Self { - cb : size_of::() as _, - ..Default::default() - } + Self { cb: size_of::() as _, ..Default::default() } } } #[repr(C)] #[derive(Default)] -struct ImageDosHeader { +struct DosHeader { magic: u16, cblp: u16, cp: u16, @@ -137,22 +116,8 @@ struct ImageDosHeader { #[repr(C)] #[derive(Default)] -struct ImageDataDirectory { - virtual_address: u32, - size: u32, -} - -#[repr(C)] -#[derive(Default)] -struct ImageNtHeader { +struct PeHeader { signature: u32, - file_header: ImageFileHeader, - optional_header: ImageOptionalHeader, -} - -#[repr(C)] -#[derive(Default)] -struct ImageFileHeader { machine: u16, number_of_sections: u16, time_date_stamp: u32, @@ -164,7 +129,7 @@ struct ImageFileHeader { #[repr(C)] #[derive(Default)] -struct ImageOptionalHeader { +struct OptionalHeader { magic: u16, major_linker_version: u8, minor_linker_version: u8, @@ -195,12 +160,19 @@ struct ImageOptionalHeader { size_of_heap_commit: u32, loader_flags: u32, number_of_rva_and_sizes: u32, - data_directory: [ImageDataDirectory; 16], + data_directory: [DataDirectory; 16], +} + +#[repr(C)] +#[derive(Default)] +struct DataDirectory { + virtual_address: u32, + size: u32, } #[repr(C)] #[derive(Default)] -struct ImageSectionHeader { +struct SectionHeader { name: [u8; 8], physical_address_or_virtual_size: u32, virtual_address: u32, @@ -215,17 +187,17 @@ struct ImageSectionHeader { #[repr(C)] #[derive(Default)] -struct ImageCorHeader { +struct ClrHeader { cb: u32, major_runtime_version: u16, minor_runtime_version: u16, - meta_data: ImageDataDirectory, + meta_data: DataDirectory, flags: u32, entry_point_token_or_entry_point_rva: u32, - resources: ImageDataDirectory, - strong_name_signature: ImageDataDirectory, - code_manager_table: ImageDataDirectory, - vtable_fixups: ImageDataDirectory, - export_address_table_jumps: ImageDataDirectory, - managed_native_header: ImageDataDirectory, + resources: DataDirectory, + strong_name_signature: DataDirectory, + code_manager_table: DataDirectory, + vtable_fixups: DataDirectory, + export_address_table_jumps: DataDirectory, + managed_native_header: DataDirectory, } From 3267509268677123cd7009c8ecf143d37cb63b8a Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Tue, 15 Mar 2022 14:40:49 -0700 Subject: [PATCH 07/55] .text --- crates/libs/metagen/src/lib.rs | 39 ++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/crates/libs/metagen/src/lib.rs b/crates/libs/metagen/src/lib.rs index 937fbad9e1..19753c4784 100644 --- a/crates/libs/metagen/src/lib.rs +++ b/crates/libs/metagen/src/lib.rs @@ -8,24 +8,31 @@ use std::mem::*; use std::slice::*; pub fn test() { - let mut buffer = Vec::::new(); let dos = DosHeader::new(); - write(&mut buffer, &dos); let pe = PeHeader::new(); - write(&mut buffer, &pe); - let optional = OptionalHeader::new(); - write(&mut buffer, &optional); - let sections = SectionHeader::new(); - write(&mut buffer, §ions); + let optional = OptionalHeader::new(0); // TODO: set to overall image size (e.g. including CLR metadata) + let section = SectionHeader::new(); let clr = ClrHeader::new(); - write(&mut buffer, &clr); + + let mut buffer = Vec::::new(); + buffer.write(&dos); + buffer.write(&pe); + buffer.write(&optional); + buffer.write(§ion); + buffer.write(&clr); std::fs::write("/git/test.winmd", buffer).unwrap(); } -fn write(buffer: &mut Vec, value: &T) { - unsafe { - buffer.extend_from_slice(from_raw_parts(value as *const _ as _, size_of::())); +trait Write { + fn write(&mut self, value: &T); +} + +impl Write for Vec:: { + fn write(&mut self, value: &T) { + unsafe { + self.extend_from_slice(from_raw_parts(value as *const _ as _, size_of::())); + } } } @@ -45,7 +52,7 @@ impl PeHeader { Self { signature: 0x4550, // PE\0\0 machine: 0x14C, // x86 - number_of_sections: 2, + number_of_sections: 1, size_of_optional_header: size_of::() as _, characteristics: 0x2102, // DLL ..Default::default() @@ -54,7 +61,7 @@ impl PeHeader { } impl OptionalHeader { - fn new() -> Self { + fn new(size_of_image: u32) -> Self { Self { magic: 0x10B, // PE32 major_linker_version: 0xB, @@ -66,6 +73,7 @@ impl OptionalHeader { minor_operating_system_version: 2, major_subsystem_version: 6, minor_subsystem_version: 2, + size_of_image, size_of_headers: 0x200, subsystem: 3, // console dll_characteristics: 0x540, @@ -80,7 +88,10 @@ impl OptionalHeader { impl SectionHeader { fn new() -> Self { - Self { ..Default::default() } + Self { + name: *b".text\0\0\0", + characteristics: 0x4000_0020, + ..Default::default() } } } From f40797f2779f7b65b1faace287d8f4af560acaf1 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Tue, 15 Mar 2022 16:17:02 -0700 Subject: [PATCH 08/55] align --- crates/libs/metagen/src/lib.rs | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/crates/libs/metagen/src/lib.rs b/crates/libs/metagen/src/lib.rs index 19753c4784..764a93c0f7 100644 --- a/crates/libs/metagen/src/lib.rs +++ b/crates/libs/metagen/src/lib.rs @@ -10,15 +10,28 @@ use std::slice::*; pub fn test() { let dos = DosHeader::new(); let pe = PeHeader::new(); - let optional = OptionalHeader::new(0); // TODO: set to overall image size (e.g. including CLR metadata) - let section = SectionHeader::new(); + let mut optional = OptionalHeader::new(); + let mut section = SectionHeader::new(); let clr = ClrHeader::new(); + optional.size_of_image = 0xAABBCCDD; + + optional.data_directory[14] = DataDirectory { + virtual_address: 0x1000, + size: size_of::() as _, + }; + + section.virtual_size = size_of::() as _; + section.size_of_raw_data = size_of::() as _; + section.pointer_to_raw_data = 0x200; + let mut buffer = Vec::::new(); buffer.write(&dos); buffer.write(&pe); buffer.write(&optional); buffer.write(§ion); + debug_assert!(buffer.len() < 0x200); + buffer.resize(0x200, 0); buffer.write(&clr); std::fs::write("/git/test.winmd", buffer).unwrap(); @@ -61,19 +74,18 @@ impl PeHeader { } impl OptionalHeader { - fn new(size_of_image: u32) -> Self { + fn new() -> Self { Self { magic: 0x10B, // PE32 major_linker_version: 0xB, size_of_initialized_data: 0x400, image_base: 0x400000, - section_alignment: 0x1000, + section_alignment: 0x200, file_alignment: 0x200, major_operating_system_version: 6, minor_operating_system_version: 2, major_subsystem_version: 6, minor_subsystem_version: 2, - size_of_image, size_of_headers: 0x200, subsystem: 3, // console dll_characteristics: 0x540, @@ -91,13 +103,20 @@ impl SectionHeader { Self { name: *b".text\0\0\0", characteristics: 0x4000_0020, + virtual_address: 0x1000, ..Default::default() } } } impl ClrHeader { fn new() -> Self { - Self { cb: size_of::() as _, ..Default::default() } + Self { + cb: size_of::() as _, + major_runtime_version: 2, + minor_runtime_version: 5, + flags: 0x1, + ..Default::default() + } } } @@ -185,7 +204,7 @@ struct DataDirectory { #[derive(Default)] struct SectionHeader { name: [u8; 8], - physical_address_or_virtual_size: u32, + virtual_size: u32, virtual_address: u32, size_of_raw_data: u32, pointer_to_raw_data: u32, From fb0c14279735d902778b6e0d876d234893045da4 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Tue, 15 Mar 2022 16:20:04 -0700 Subject: [PATCH 09/55] simpler --- crates/libs/metagen/src/lib.rs | 145 +++++++++++++++++---------------- 1 file changed, 73 insertions(+), 72 deletions(-) diff --git a/crates/libs/metagen/src/lib.rs b/crates/libs/metagen/src/lib.rs index 764a93c0f7..107bf33d9b 100644 --- a/crates/libs/metagen/src/lib.rs +++ b/crates/libs/metagen/src/lib.rs @@ -38,7 +38,7 @@ pub fn test() { } trait Write { - fn write(&mut self, value: &T); + fn write(&mut self, value: &T); } impl Write for Vec:: { @@ -49,77 +49,6 @@ impl Write for Vec:: { } } -impl DosHeader { - fn new() -> Self { - Self { - magic: 0x5A4D, // MZ - lfarlc: 0x40, // file address of relocation table - lfanew: size_of::() as _, // file address of next header - ..Default::default() - } - } -} - -impl PeHeader { - fn new() -> Self { - Self { - signature: 0x4550, // PE\0\0 - machine: 0x14C, // x86 - number_of_sections: 1, - size_of_optional_header: size_of::() as _, - characteristics: 0x2102, // DLL - ..Default::default() - } - } -} - -impl OptionalHeader { - fn new() -> Self { - Self { - magic: 0x10B, // PE32 - major_linker_version: 0xB, - size_of_initialized_data: 0x400, - image_base: 0x400000, - section_alignment: 0x200, - file_alignment: 0x200, - major_operating_system_version: 6, - minor_operating_system_version: 2, - major_subsystem_version: 6, - minor_subsystem_version: 2, - size_of_headers: 0x200, - subsystem: 3, // console - dll_characteristics: 0x540, - size_of_stack_reserve: 0x100000, - size_of_heap_reserve: 0x1000, - loader_flags: 0x100000, - number_of_rva_and_sizes: 0x10, - ..Default::default() - } - } -} - -impl SectionHeader { - fn new() -> Self { - Self { - name: *b".text\0\0\0", - characteristics: 0x4000_0020, - virtual_address: 0x1000, - ..Default::default() } - } -} - -impl ClrHeader { - fn new() -> Self { - Self { - cb: size_of::() as _, - major_runtime_version: 2, - minor_runtime_version: 5, - flags: 0x1, - ..Default::default() - } - } -} - #[repr(C)] #[derive(Default)] struct DosHeader { @@ -144,6 +73,17 @@ struct DosHeader { lfanew: i32, } +impl DosHeader { + fn new() -> Self { + Self { + magic: 0x5A4D, // MZ + lfarlc: 0x40, // file address of relocation table + lfanew: size_of::() as _, // file address of next header + ..Default::default() + } + } +} + #[repr(C)] #[derive(Default)] struct PeHeader { @@ -157,6 +97,19 @@ struct PeHeader { characteristics: u16, } +impl PeHeader { + fn new() -> Self { + Self { + signature: 0x4550, // PE\0\0 + machine: 0x14C, // x86 + number_of_sections: 1, + size_of_optional_header: size_of::() as _, + characteristics: 0x2102, // DLL + ..Default::default() + } + } +} + #[repr(C)] #[derive(Default)] struct OptionalHeader { @@ -193,6 +146,31 @@ struct OptionalHeader { data_directory: [DataDirectory; 16], } +impl OptionalHeader { + fn new() -> Self { + Self { + magic: 0x10B, // PE32 + major_linker_version: 0xB, + size_of_initialized_data: 0x400, + image_base: 0x400000, + section_alignment: 0x200, + file_alignment: 0x200, + major_operating_system_version: 6, + minor_operating_system_version: 2, + major_subsystem_version: 6, + minor_subsystem_version: 2, + size_of_headers: 0x200, + subsystem: 3, // console + dll_characteristics: 0x540, + size_of_stack_reserve: 0x100000, + size_of_heap_reserve: 0x1000, + loader_flags: 0x100000, + number_of_rva_and_sizes: 0x10, + ..Default::default() + } + } +} + #[repr(C)] #[derive(Default)] struct DataDirectory { @@ -215,6 +193,17 @@ struct SectionHeader { characteristics: u32, } +impl SectionHeader { + fn new() -> Self { + Self { + name: *b".text\0\0\0", + characteristics: 0x4000_0020, + virtual_address: 0x1000, + ..Default::default() } + } +} + + #[repr(C)] #[derive(Default)] struct ClrHeader { @@ -231,3 +220,15 @@ struct ClrHeader { export_address_table_jumps: DataDirectory, managed_native_header: DataDirectory, } + +impl ClrHeader { + fn new() -> Self { + Self { + cb: size_of::() as _, + major_runtime_version: 2, + minor_runtime_version: 5, + flags: 0x1, + ..Default::default() + } + } +} From 6dc490971bd4adc66df084d00b79fa08252afb03 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Wed, 16 Mar 2022 13:21:37 -0700 Subject: [PATCH 10/55] self-parse with no streams --- crates/libs/metadata/src/file.rs | 4 +-- crates/libs/metagen/src/lib.rs | 42 ++++++++++++++++++++++++++++--- crates/tests/define/Cargo.toml | 3 +++ crates/tests/define/src/lib.rs | 1 - crates/tests/define/src/main.rs | 5 ++++ crates/tests/define/tests/test.rs | 1 + 6 files changed, 49 insertions(+), 7 deletions(-) delete mode 100644 crates/tests/define/src/lib.rs create mode 100644 crates/tests/define/src/main.rs diff --git a/crates/libs/metadata/src/file.rs b/crates/libs/metadata/src/file.rs index 1a35465e4f..ec23790e41 100644 --- a/crates/libs/metadata/src/file.rs +++ b/crates/libs/metadata/src/file.rs @@ -215,7 +215,7 @@ impl File { (first, last) } - pub(crate) fn from_bytes(name: String, bytes: Vec) -> Self { + pub fn from_bytes(name: String, bytes: Vec) -> Self { let mut file = Self { name, bytes, ..Default::default() }; let dos = file.bytes.view_as::(0); @@ -474,7 +474,7 @@ impl File { file } - pub(crate) fn new>(filename: P) -> Self { + pub fn new>(filename: P) -> Self { let filename = filename.as_ref(); let bytes = std::fs::read(filename).unwrap_or_else(|e| panic!("Could not read file {:?}: {:?}", filename, e)); diff --git a/crates/libs/metagen/src/lib.rs b/crates/libs/metagen/src/lib.rs index 107bf33d9b..42d30454df 100644 --- a/crates/libs/metagen/src/lib.rs +++ b/crates/libs/metagen/src/lib.rs @@ -12,7 +12,8 @@ pub fn test() { let pe = PeHeader::new(); let mut optional = OptionalHeader::new(); let mut section = SectionHeader::new(); - let clr = ClrHeader::new(); + let mut clr = ClrHeader::new(); + let metadata = MetadataHeader::new(); optional.size_of_image = 0xAABBCCDD; @@ -21,10 +22,15 @@ pub fn test() { size: size_of::() as _, }; - section.virtual_size = size_of::() as _; - section.size_of_raw_data = size_of::() as _; + section.virtual_size = 0xAABBCCDD; + section.size_of_raw_data = 0xAABBCCDD; section.pointer_to_raw_data = 0x200; + clr.meta_data = DataDirectory { + virtual_address: 0x1000 + size_of::() as u32, + size: 0, + }; + let mut buffer = Vec::::new(); buffer.write(&dos); buffer.write(&pe); @@ -33,6 +39,7 @@ pub fn test() { debug_assert!(buffer.len() < 0x200); buffer.resize(0x200, 0); buffer.write(&clr); + buffer.write(&metadata); std::fs::write("/git/test.winmd", buffer).unwrap(); } @@ -153,7 +160,7 @@ impl OptionalHeader { major_linker_version: 0xB, size_of_initialized_data: 0x400, image_base: 0x400000, - section_alignment: 0x200, + section_alignment: 0x1000, file_alignment: 0x200, major_operating_system_version: 6, minor_operating_system_version: 2, @@ -232,3 +239,30 @@ impl ClrHeader { } } } + +#[repr(C)] +#[derive(Default)] +struct MetadataHeader { + signature: u32, + major_version: u16, + minor_version: u16, + reserved: u32, + length: u32, + version: [u8;15], + flags: u16, + streams: u16, +} + +impl MetadataHeader { + fn new() -> Self { + Self { + signature: 0x424A_5342, + major_version: 1, + minor_version: 1, + length: 15, + version: *b"WindowsRuntime\0", + streams: 0,//3, + ..Default::default() + } + } +} diff --git a/crates/tests/define/Cargo.toml b/crates/tests/define/Cargo.toml index 2ded106d6a..97d976f79f 100644 --- a/crates/tests/define/Cargo.toml +++ b/crates/tests/define/Cargo.toml @@ -12,3 +12,6 @@ features = [ [dependencies.windows-metagen] path = "../../libs/metagen" + +[dependencies.windows-metadata] +path = "../../libs/metadata" diff --git a/crates/tests/define/src/lib.rs b/crates/tests/define/src/lib.rs deleted file mode 100644 index 8b13789179..0000000000 --- a/crates/tests/define/src/lib.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/crates/tests/define/src/main.rs b/crates/tests/define/src/main.rs new file mode 100644 index 0000000000..74325c0bc0 --- /dev/null +++ b/crates/tests/define/src/main.rs @@ -0,0 +1,5 @@ + +fn main() { + windows_metagen::test(); + windows_metadata::File::new("/git/test.winmd"); +} diff --git a/crates/tests/define/tests/test.rs b/crates/tests/define/tests/test.rs index 1d3b2729ac..5db9620a37 100644 --- a/crates/tests/define/tests/test.rs +++ b/crates/tests/define/tests/test.rs @@ -18,4 +18,5 @@ fn define() { #[test] fn metagen() { windows_metagen::test(); + windows_metadata::File::new("/git/test.winmd"); } From 36355c3a603a000ffb6031edb7fc530bc67d18a5 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Wed, 16 Mar 2022 15:37:13 -0700 Subject: [PATCH 11/55] closer --- crates/libs/metagen/src/lib.rs | 38 +++++++++++++++++++++++++++------ crates/tests/define/src/main.rs | 1 - 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/crates/libs/metagen/src/lib.rs b/crates/libs/metagen/src/lib.rs index 42d30454df..2cd0a17f4a 100644 --- a/crates/libs/metagen/src/lib.rs +++ b/crates/libs/metagen/src/lib.rs @@ -14,16 +14,17 @@ pub fn test() { let mut section = SectionHeader::new(); let mut clr = ClrHeader::new(); let metadata = MetadataHeader::new(); + // let string_stream = - optional.size_of_image = 0xAABBCCDD; + optional.size_of_image = 0xCCCC; // TODO: calc size optional.data_directory[14] = DataDirectory { virtual_address: 0x1000, size: size_of::() as _, }; - section.virtual_size = 0xAABBCCDD; - section.size_of_raw_data = 0xAABBCCDD; + section.virtual_size = 0xCCCC; // TODO: calc size + section.size_of_raw_data = 0xCCCC; // TODO: calc size section.pointer_to_raw_data = 0x200; clr.meta_data = DataDirectory { @@ -39,8 +40,31 @@ pub fn test() { debug_assert!(buffer.len() < 0x200); buffer.resize(0x200, 0); buffer.write(&clr); + let metadata_offset = buffer.len(); buffer.write(&metadata); + + // String stream + buffer.write(&DataDirectory { + virtual_address: (buffer.len() - metadata_offset) as u32, + size: 4, + }); + buffer.write(b"#Strings\0\0\0\0"); + // Blob stream + buffer.write(&DataDirectory { + virtual_address: (buffer.len() - metadata_offset) as u32, + size: 4, + }); + buffer.write(b"#Blob\0\0\0"); + + // Table stream + buffer.write(&DataDirectory { + virtual_address: (buffer.len() - metadata_offset) as u32, + size: 4, + }); + buffer.write(b"#~\0\0"); + + buffer.resize(0xCF00, 0); // TODO: calc alignment? std::fs::write("/git/test.winmd", buffer).unwrap(); } @@ -248,7 +272,7 @@ struct MetadataHeader { minor_version: u16, reserved: u32, length: u32, - version: [u8;15], + version: [u8;20], flags: u16, streams: u16, } @@ -259,9 +283,9 @@ impl MetadataHeader { signature: 0x424A_5342, major_version: 1, minor_version: 1, - length: 15, - version: *b"WindowsRuntime\0", - streams: 0,//3, + length: 20, + version: *b"WindowsRuntime\0\0\0\0\0\0", + streams: 3, ..Default::default() } } diff --git a/crates/tests/define/src/main.rs b/crates/tests/define/src/main.rs index 74325c0bc0..4bfc500352 100644 --- a/crates/tests/define/src/main.rs +++ b/crates/tests/define/src/main.rs @@ -1,4 +1,3 @@ - fn main() { windows_metagen::test(); windows_metadata::File::new("/git/test.winmd"); From 4fc18f3a616d4a2351e93c4f05694acfea768069 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Wed, 16 Mar 2022 16:10:37 -0700 Subject: [PATCH 12/55] fixed heap size --- crates/libs/metadata/src/file.rs | 3 +++ crates/libs/metagen/src/lib.rs | 17 +++++++++++++++++ crates/tests/define/src/main.rs | 1 + 3 files changed, 21 insertions(+) diff --git a/crates/libs/metadata/src/file.rs b/crates/libs/metadata/src/file.rs index ec23790e41..537a8c1f23 100644 --- a/crates/libs/metadata/src/file.rs +++ b/crates/libs/metadata/src/file.rs @@ -269,6 +269,9 @@ impl File { let string_index_size = if (heap_sizes & 1) == 1 { 4 } else { 2 }; let guid_index_size = if (heap_sizes >> 1 & 1) == 1 { 4 } else { 2 }; let blob_index_size = if (heap_sizes >> 2 & 1) == 1 { 4 } else { 2 }; + println!("string_index_size {}", string_index_size); + println!("guid_index_size {}", guid_index_size); + println!("blob_index_size {}", blob_index_size); let valid_bits = file.bytes.copy_as::(tables_data.0 + 8); view = tables_data.0 + 24; diff --git a/crates/libs/metagen/src/lib.rs b/crates/libs/metagen/src/lib.rs index 2cd0a17f4a..d983a43a98 100644 --- a/crates/libs/metagen/src/lib.rs +++ b/crates/libs/metagen/src/lib.rs @@ -6,6 +6,7 @@ use std::mem::*; use std::slice::*; +use std::collections::*; pub fn test() { let dos = DosHeader::new(); @@ -16,6 +17,8 @@ pub fn test() { let metadata = MetadataHeader::new(); // let string_stream = + // TODO: these should all be at fixed offsets so we could just rewrite them in the buffer later on + // provided we keep track of the offsets. optional.size_of_image = 0xCCCC; // TODO: calc size optional.data_directory[14] = DataDirectory { @@ -290,3 +293,17 @@ impl MetadataHeader { } } } + +struct Strings(BTreeSet); + +impl Strings { + fn write(buffer: &mut Vec::) { + + } +} + +struct Blobs(BTreeSet>); + +struct Tables { + // TODO: just use fixed 4 byte index sizes +} diff --git a/crates/tests/define/src/main.rs b/crates/tests/define/src/main.rs index 4bfc500352..3f0a00587a 100644 --- a/crates/tests/define/src/main.rs +++ b/crates/tests/define/src/main.rs @@ -1,4 +1,5 @@ fn main() { windows_metagen::test(); windows_metadata::File::new("/git/test.winmd"); + //windows_metadata::File::new(r#"D:\git\windows-rs\crates\libs\metadata\default\windows.winmd"#); } From a4bbf7977b57b363fdc8add00836e379032b8aab Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Thu, 17 Mar 2022 12:03:49 -0700 Subject: [PATCH 13/55] heap sizes --- crates/libs/metagen/src/lib.rs | 131 +++++++++++++++++++++------------ 1 file changed, 83 insertions(+), 48 deletions(-) diff --git a/crates/libs/metagen/src/lib.rs b/crates/libs/metagen/src/lib.rs index d983a43a98..e810ddec83 100644 --- a/crates/libs/metagen/src/lib.rs +++ b/crates/libs/metagen/src/lib.rs @@ -4,9 +4,9 @@ // https://docs.microsoft.com/en-us/archive/msdn-magazine/2002/february/inside-windows-win32-portable-executable-file-format-in-detail // https://github.com/dotnet/runtime/blob/94c0a7c13d158eb79d27223f474ec8f8db747f11/src/coreclr/dlls/mscorpe/pewriter.cpp +use std::collections::*; use std::mem::*; use std::slice::*; -use std::collections::*; pub fn test() { let dos = DosHeader::new(); @@ -15,25 +15,26 @@ pub fn test() { let mut section = SectionHeader::new(); let mut clr = ClrHeader::new(); let metadata = MetadataHeader::new(); - // let string_stream = + + let strings = Strings::default(); + let blobs = Blobs::default(); + let tables = Tables::default(); + // TODO: populate metadata + let mut strings = strings.buffer(); + let mut blobs = blobs.buffer(); + let mut tables = tables.buffer(); // TODO: these should all be at fixed offsets so we could just rewrite them in the buffer later on // provided we keep track of the offsets. optional.size_of_image = 0xCCCC; // TODO: calc size - optional.data_directory[14] = DataDirectory { - virtual_address: 0x1000, - size: size_of::() as _, - }; + optional.data_directory[14] = DataDirectory { virtual_address: 0x1000, size: size_of::() as _ }; section.virtual_size = 0xCCCC; // TODO: calc size section.size_of_raw_data = 0xCCCC; // TODO: calc size section.pointer_to_raw_data = 0x200; - clr.meta_data = DataDirectory { - virtual_address: 0x1000 + size_of::() as u32, - size: 0, - }; + clr.meta_data = DataDirectory { virtual_address: 0x1000 + size_of::() as u32, size: 0 }; let mut buffer = Vec::::new(); buffer.write(&dos); @@ -45,37 +46,37 @@ pub fn test() { buffer.write(&clr); let metadata_offset = buffer.len(); buffer.write(&metadata); - - // String stream - buffer.write(&DataDirectory { - virtual_address: (buffer.len() - metadata_offset) as u32, - size: 4, - }); + + let stream_offset = buffer.len() - metadata_offset + + size_of::() + 12 // #Strings + + size_of::() + 8 // #Blob + + size_of::() + 4; // #~ + + // String stream header + buffer.write(&DataDirectory { virtual_address: stream_offset as u32, size: 4 }); buffer.write(b"#Strings\0\0\0\0"); - // Blob stream - buffer.write(&DataDirectory { - virtual_address: (buffer.len() - metadata_offset) as u32, - size: 4, - }); + // Blob stream header + buffer.write(&DataDirectory { virtual_address: (stream_offset + strings.len()) as u32, size: 4 }); buffer.write(b"#Blob\0\0\0"); - // Table stream - buffer.write(&DataDirectory { - virtual_address: (buffer.len() - metadata_offset) as u32, - size: 4, - }); + // Table stream header + buffer.write(&DataDirectory { virtual_address: (stream_offset + strings.len() + blobs.len()) as u32, size: 4 }); buffer.write(b"#~\0\0"); + buffer.append(&mut strings); + buffer.append(&mut blobs); + buffer.append(&mut tables); + buffer.resize(0xCF00, 0); // TODO: calc alignment? std::fs::write("/git/test.winmd", buffer).unwrap(); } trait Write { - fn write(&mut self, value: &T); + fn write(&mut self, value: &T); } -impl Write for Vec:: { +impl Write for Vec { fn write(&mut self, value: &T) { unsafe { self.extend_from_slice(from_raw_parts(value as *const _ as _, size_of::())); @@ -229,15 +230,10 @@ struct SectionHeader { impl SectionHeader { fn new() -> Self { - Self { - name: *b".text\0\0\0", - characteristics: 0x4000_0020, - virtual_address: 0x1000, - ..Default::default() } + Self { name: *b".text\0\0\0", characteristics: 0x4000_0020, virtual_address: 0x1000, ..Default::default() } } } - #[repr(C)] #[derive(Default)] struct ClrHeader { @@ -257,53 +253,92 @@ struct ClrHeader { impl ClrHeader { fn new() -> Self { - Self { - cb: size_of::() as _, - major_runtime_version: 2, - minor_runtime_version: 5, - flags: 0x1, - ..Default::default() - } + Self { cb: size_of::() as _, major_runtime_version: 2, minor_runtime_version: 5, flags: 0x1, ..Default::default() } } } #[repr(C)] #[derive(Default)] struct MetadataHeader { - signature: u32, + signature: u32, major_version: u16, minor_version: u16, reserved: u32, length: u32, - version: [u8;20], + version: [u8; 20], flags: u16, streams: u16, } impl MetadataHeader { fn new() -> Self { - Self { + Self { signature: 0x424A_5342, major_version: 1, minor_version: 1, length: 20, version: *b"WindowsRuntime\0\0\0\0\0\0", streams: 3, - ..Default::default() + ..Default::default() } } } +#[derive(Default)] struct Strings(BTreeSet); impl Strings { - fn write(buffer: &mut Vec::) { - + fn buffer(&self) -> Vec { + let mut buffer = Vec::new(); + buffer.push(0); + buffer } } +#[derive(Default)] struct Blobs(BTreeSet>); +impl Blobs { + fn buffer(&self) -> Vec { + let mut buffer = Vec::new(); + buffer.push(0); + buffer + } +} + +#[derive(Default)] struct Tables { - // TODO: just use fixed 4 byte index sizes + // TODO: just use fixed 4 byte index sizes +} + +impl Tables { + fn buffer(&self) -> Vec { + let mut buffer = Vec::new(); + let header = TableStreamHeader::new(); + buffer.write(&header); + buffer + } +} + +#[repr(C)] +#[derive(Default)] +struct TableStreamHeader { + reserved1: u32, + major_version: u8, + minor_version: u8, + heap_sizes: u8, + reserved2: u8, + valid: u64, + sorted: u64, +} + +impl TableStreamHeader { + fn new() -> Self { + Self { + major_version: 2, + reserved2: 1, + heap_sizes: 0b111, + ..Default::default() + } + } } From 5601163b090bc5480925edb09f08d3dfcc697d46 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Thu, 17 Mar 2022 12:12:46 -0700 Subject: [PATCH 14/55] sizes --- crates/libs/metagen/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/libs/metagen/src/lib.rs b/crates/libs/metagen/src/lib.rs index e810ddec83..d597877432 100644 --- a/crates/libs/metagen/src/lib.rs +++ b/crates/libs/metagen/src/lib.rs @@ -53,15 +53,15 @@ pub fn test() { + size_of::() + 4; // #~ // String stream header - buffer.write(&DataDirectory { virtual_address: stream_offset as u32, size: 4 }); + buffer.write(&DataDirectory { virtual_address: stream_offset as u32, size: strings.len() as _ }); buffer.write(b"#Strings\0\0\0\0"); // Blob stream header - buffer.write(&DataDirectory { virtual_address: (stream_offset + strings.len()) as u32, size: 4 }); + buffer.write(&DataDirectory { virtual_address: (stream_offset + strings.len()) as u32, size: blobs.len() as _ }); buffer.write(b"#Blob\0\0\0"); // Table stream header - buffer.write(&DataDirectory { virtual_address: (stream_offset + strings.len() + blobs.len()) as u32, size: 4 }); + buffer.write(&DataDirectory { virtual_address: (stream_offset + strings.len() + blobs.len()) as u32, size: tables.len() as _ }); buffer.write(b"#~\0\0"); buffer.append(&mut strings); From 2de2f3259699c1a7eb5d612ee8e2b05e5f03feb7 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Thu, 17 Mar 2022 14:04:31 -0700 Subject: [PATCH 15/55] size_of_image --- crates/libs/metagen/src/lib.rs | 48 ++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/crates/libs/metagen/src/lib.rs b/crates/libs/metagen/src/lib.rs index d597877432..1a442dd17f 100644 --- a/crates/libs/metagen/src/lib.rs +++ b/crates/libs/metagen/src/lib.rs @@ -8,7 +8,15 @@ use std::collections::*; use std::mem::*; use std::slice::*; +fn round(size: usize, page: usize) -> usize { + let page = page - 1; + (size + page) & !page +} + pub fn test() { + assert!(round(5, 4096) == 4096); + assert!(round(4096 + 5, 4096) == 8192); + let dos = DosHeader::new(); let pe = PeHeader::new(); let mut optional = OptionalHeader::new(); @@ -24,25 +32,24 @@ pub fn test() { let mut blobs = blobs.buffer(); let mut tables = tables.buffer(); - // TODO: these should all be at fixed offsets so we could just rewrite them in the buffer later on - // provided we keep track of the offsets. - optional.size_of_image = 0xCCCC; // TODO: calc size - - optional.data_directory[14] = DataDirectory { virtual_address: 0x1000, size: size_of::() as _ }; + let size_of_image = 512 + size_of::() + size_of::() + 48 + strings.len() + blobs.len() + tables.len(); + optional.size_of_image = round(size_of_image, 4096) as _; section.virtual_size = 0xCCCC; // TODO: calc size section.size_of_raw_data = 0xCCCC; // TODO: calc size - section.pointer_to_raw_data = 0x200; - clr.meta_data = DataDirectory { virtual_address: 0x1000 + size_of::() as u32, size: 0 }; + optional.data_directory[14] = DataDirectory { virtual_address: 4096, size: size_of::() as _ }; + section.pointer_to_raw_data = 512; + clr.meta_data = DataDirectory { virtual_address: 4096 + size_of::() as u32, size: 0 }; let mut buffer = Vec::::new(); buffer.write(&dos); buffer.write(&pe); buffer.write(&optional); buffer.write(§ion); - debug_assert!(buffer.len() < 0x200); - buffer.resize(0x200, 0); + debug_assert!(buffer.len() < 512); + println!("header: {}", buffer.len()); + buffer.resize(512, 0); buffer.write(&clr); let metadata_offset = buffer.len(); buffer.write(&metadata); @@ -68,7 +75,8 @@ pub fn test() { buffer.append(&mut blobs); buffer.append(&mut tables); - buffer.resize(0xCF00, 0); // TODO: calc alignment? + assert_eq!(size_of_image, buffer.len()); + std::fs::write("/git/test.winmd", buffer).unwrap(); } @@ -112,7 +120,7 @@ impl DosHeader { fn new() -> Self { Self { magic: 0x5A4D, // MZ - lfarlc: 0x40, // file address of relocation table + lfarlc: 64, // file address of relocation table lfanew: size_of::() as _, // file address of next header ..Default::default() } @@ -185,22 +193,22 @@ impl OptionalHeader { fn new() -> Self { Self { magic: 0x10B, // PE32 - major_linker_version: 0xB, - size_of_initialized_data: 0x400, + major_linker_version: 11, + size_of_initialized_data: 1024, image_base: 0x400000, - section_alignment: 0x1000, - file_alignment: 0x200, + section_alignment: 4096, + file_alignment: 512, major_operating_system_version: 6, minor_operating_system_version: 2, major_subsystem_version: 6, minor_subsystem_version: 2, - size_of_headers: 0x200, + size_of_headers: 512, subsystem: 3, // console dll_characteristics: 0x540, size_of_stack_reserve: 0x100000, - size_of_heap_reserve: 0x1000, + size_of_heap_reserve: 4096, loader_flags: 0x100000, - number_of_rva_and_sizes: 0x10, + number_of_rva_and_sizes: 16, ..Default::default() } } @@ -230,7 +238,7 @@ struct SectionHeader { impl SectionHeader { fn new() -> Self { - Self { name: *b".text\0\0\0", characteristics: 0x4000_0020, virtual_address: 0x1000, ..Default::default() } + Self { name: *b".text\0\0\0", characteristics: 0x4000_0020, virtual_address: 4096, ..Default::default() } } } @@ -337,7 +345,7 @@ impl TableStreamHeader { Self { major_version: 2, reserved2: 1, - heap_sizes: 0b111, + heap_sizes: 0b101, ..Default::default() } } From e17645b677e0863a4942d18b403413146fb06441 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Thu, 17 Mar 2022 14:44:16 -0700 Subject: [PATCH 16/55] relative sizes --- crates/libs/metagen/src/lib.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/crates/libs/metagen/src/lib.rs b/crates/libs/metagen/src/lib.rs index 1a442dd17f..06c4fdbaf7 100644 --- a/crates/libs/metagen/src/lib.rs +++ b/crates/libs/metagen/src/lib.rs @@ -32,14 +32,14 @@ pub fn test() { let mut blobs = blobs.buffer(); let mut tables = tables.buffer(); - let size_of_image = 512 + size_of::() + size_of::() + 48 + strings.len() + blobs.len() + tables.len(); + let size_of_image = optional.file_alignment as usize + size_of::() + size_of::() + 48 + strings.len() + blobs.len() + tables.len(); - optional.size_of_image = round(size_of_image, 4096) as _; - section.virtual_size = 0xCCCC; // TODO: calc size - section.size_of_raw_data = 0xCCCC; // TODO: calc size + optional.size_of_image = round(size_of_image, optional.section_alignment as _) as _; + section.virtual_size = size_of_image as u32 - optional.file_alignment; + section.size_of_raw_data = round(section.virtual_size as _, optional.file_alignment as _) as _; optional.data_directory[14] = DataDirectory { virtual_address: 4096, size: size_of::() as _ }; - section.pointer_to_raw_data = 512; + section.pointer_to_raw_data = optional.file_alignment; clr.meta_data = DataDirectory { virtual_address: 4096 + size_of::() as u32, size: 0 }; let mut buffer = Vec::::new(); @@ -47,9 +47,9 @@ pub fn test() { buffer.write(&pe); buffer.write(&optional); buffer.write(§ion); - debug_assert!(buffer.len() < 512); + debug_assert!(buffer.len() < optional.file_alignment as _); println!("header: {}", buffer.len()); - buffer.resize(512, 0); + buffer.resize(optional.file_alignment as _, 0); buffer.write(&clr); let metadata_offset = buffer.len(); buffer.write(&metadata); From 5813cf24cc4ff63ab868e7b5820704d8a36ff818 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Thu, 17 Mar 2022 15:05:45 -0700 Subject: [PATCH 17/55] fmt --- crates/libs/metagen/src/lib.rs | 35 ++++++++++++---------------------- 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/crates/libs/metagen/src/lib.rs b/crates/libs/metagen/src/lib.rs index 06c4fdbaf7..afbb8cb76d 100644 --- a/crates/libs/metagen/src/lib.rs +++ b/crates/libs/metagen/src/lib.rs @@ -1,22 +1,10 @@ -// Bootstrap the winmd generation here... -// https://en.wikipedia.org/wiki/Portable_Executable // https://docs.microsoft.com/en-us/windows/win32/debug/pe-format -// https://docs.microsoft.com/en-us/archive/msdn-magazine/2002/february/inside-windows-win32-portable-executable-file-format-in-detail -// https://github.com/dotnet/runtime/blob/94c0a7c13d158eb79d27223f474ec8f8db747f11/src/coreclr/dlls/mscorpe/pewriter.cpp use std::collections::*; use std::mem::*; use std::slice::*; -fn round(size: usize, page: usize) -> usize { - let page = page - 1; - (size + page) & !page -} - pub fn test() { - assert!(round(5, 4096) == 4096); - assert!(round(4096 + 5, 4096) == 8192); - let dos = DosHeader::new(); let pe = PeHeader::new(); let mut optional = OptionalHeader::new(); @@ -27,7 +15,7 @@ pub fn test() { let strings = Strings::default(); let blobs = Blobs::default(); let tables = Tables::default(); - // TODO: populate metadata + // TODO: populate CLI metadata let mut strings = strings.buffer(); let mut blobs = blobs.buffer(); let mut tables = tables.buffer(); @@ -40,7 +28,7 @@ pub fn test() { optional.data_directory[14] = DataDirectory { virtual_address: 4096, size: size_of::() as _ }; section.pointer_to_raw_data = optional.file_alignment; - clr.meta_data = DataDirectory { virtual_address: 4096 + size_of::() as u32, size: 0 }; + clr.meta_data = DataDirectory { virtual_address: 4096 + size_of::() as u32, size: section.virtual_size - size_of::() as u32 }; let mut buffer = Vec::::new(); buffer.write(&dos); @@ -54,9 +42,9 @@ pub fn test() { let metadata_offset = buffer.len(); buffer.write(&metadata); - let stream_offset = buffer.len() - metadata_offset + let stream_offset = buffer.len() - metadata_offset + size_of::() + 12 // #Strings - + size_of::() + 8 // #Blob + + size_of::() + 8 // #Blob + size_of::() + 4; // #~ // String stream header @@ -75,11 +63,17 @@ pub fn test() { buffer.append(&mut blobs); buffer.append(&mut tables); + assert_eq!(clr.meta_data.size as usize, buffer.len() - metadata_offset); assert_eq!(size_of_image, buffer.len()); std::fs::write("/git/test.winmd", buffer).unwrap(); } +fn round(size: usize, page: usize) -> usize { + let page = page - 1; + (size + page) & !page +} + trait Write { fn write(&mut self, value: &T); } @@ -120,7 +114,7 @@ impl DosHeader { fn new() -> Self { Self { magic: 0x5A4D, // MZ - lfarlc: 64, // file address of relocation table + lfarlc: 64, // file address of relocation table lfanew: size_of::() as _, // file address of next header ..Default::default() } @@ -342,11 +336,6 @@ struct TableStreamHeader { impl TableStreamHeader { fn new() -> Self { - Self { - major_version: 2, - reserved2: 1, - heap_sizes: 0b101, - ..Default::default() - } + Self { major_version: 2, reserved2: 1, heap_sizes: 0b101, ..Default::default() } } } From e354f03dba172c88754d6064bf6cbeb73354e74a Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Thu, 17 Mar 2022 15:18:43 -0700 Subject: [PATCH 18/55] simpler --- crates/libs/metagen/src/lib.rs | 89 ++++++++++++++++++++-------------- 1 file changed, 53 insertions(+), 36 deletions(-) diff --git a/crates/libs/metagen/src/lib.rs b/crates/libs/metagen/src/lib.rs index afbb8cb76d..4afcb891cd 100644 --- a/crates/libs/metagen/src/lib.rs +++ b/crates/libs/metagen/src/lib.rs @@ -20,7 +20,7 @@ pub fn test() { let mut blobs = blobs.buffer(); let mut tables = tables.buffer(); - let size_of_image = optional.file_alignment as usize + size_of::() + size_of::() + 48 + strings.len() + blobs.len() + tables.len(); + let size_of_image = optional.file_alignment as usize + size_of::() + size_of::() + size_of::() + strings.len() + blobs.len() + tables.len(); optional.size_of_image = round(size_of_image, optional.section_alignment as _) as _; section.virtual_size = size_of_image as u32 - optional.file_alignment; @@ -36,29 +36,21 @@ pub fn test() { buffer.write(&optional); buffer.write(§ion); debug_assert!(buffer.len() < optional.file_alignment as _); - println!("header: {}", buffer.len()); buffer.resize(optional.file_alignment as _, 0); buffer.write(&clr); let metadata_offset = buffer.len(); buffer.write(&metadata); - let stream_offset = buffer.len() - metadata_offset - + size_of::() + 12 // #Strings - + size_of::() + 8 // #Blob - + size_of::() + 4; // #~ - - // String stream header - buffer.write(&DataDirectory { virtual_address: stream_offset as u32, size: strings.len() as _ }); - buffer.write(b"#Strings\0\0\0\0"); - - // Blob stream header - buffer.write(&DataDirectory { virtual_address: (stream_offset + strings.len()) as u32, size: blobs.len() as _ }); - buffer.write(b"#Blob\0\0\0"); - - // Table stream header - buffer.write(&DataDirectory { virtual_address: (stream_offset + strings.len() + blobs.len()) as u32, size: tables.len() as _ }); - buffer.write(b"#~\0\0"); + let stream_offset = buffer.len() - metadata_offset + size_of::(); + let mut streams = StreamHeader::new(); + streams.strings_offset = stream_offset as u32; + streams.strings_size = strings.len() as _; + streams.blobs_offset = (stream_offset + strings.len()) as u32; + streams.blobs_size = blobs.len() as _; + streams.tables_offset = (stream_offset + strings.len() + blobs.len()) as u32; + streams.tables_size = tables.len() as _; + buffer.write(&streams); buffer.append(&mut strings); buffer.append(&mut blobs); buffer.append(&mut tables); @@ -286,6 +278,49 @@ impl MetadataHeader { } } +#[repr(C)] +#[derive(Default)] +struct StreamHeader { + strings_offset: u32, + strings_size: u32, + strings_name: [u8; 12], + blobs_offset: u32, + blobs_size: u32, + blobs_name: [u8; 8], + tables_offset: u32, + tables_size: u32, + tables_name: [u8; 4], +} + +impl StreamHeader { + fn new() -> Self { + Self { + strings_name: *b"#Strings\0\0\0\0", + blobs_name: *b"#Blob\0\0\0", + tables_name: *b"#~\0\0", + ..Default::default() + } + } +} + +#[repr(C)] +#[derive(Default)] +struct TableStreamHeader { + reserved1: u32, + major_version: u8, + minor_version: u8, + heap_sizes: u8, + reserved2: u8, + valid: u64, + sorted: u64, +} + +impl TableStreamHeader { + fn new() -> Self { + Self { major_version: 2, reserved2: 1, heap_sizes: 0b101, ..Default::default() } + } +} + #[derive(Default)] struct Strings(BTreeSet); @@ -321,21 +356,3 @@ impl Tables { buffer } } - -#[repr(C)] -#[derive(Default)] -struct TableStreamHeader { - reserved1: u32, - major_version: u8, - minor_version: u8, - heap_sizes: u8, - reserved2: u8, - valid: u64, - sorted: u64, -} - -impl TableStreamHeader { - fn new() -> Self { - Self { major_version: 2, reserved2: 1, heap_sizes: 0b101, ..Default::default() } - } -} From c0440cc920ab5ed5d7de7fa4393f3eab12069c73 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Thu, 17 Mar 2022 15:26:52 -0700 Subject: [PATCH 19/55] heap sizes --- crates/libs/metagen/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/libs/metagen/src/lib.rs b/crates/libs/metagen/src/lib.rs index 4afcb891cd..d921e2742c 100644 --- a/crates/libs/metagen/src/lib.rs +++ b/crates/libs/metagen/src/lib.rs @@ -317,7 +317,7 @@ struct TableStreamHeader { impl TableStreamHeader { fn new() -> Self { - Self { major_version: 2, reserved2: 1, heap_sizes: 0b101, ..Default::default() } + Self { major_version: 2, reserved2: 1, heap_sizes: 0b111, ..Default::default() } } } From cf48a85d225156ea627aea8259522b9454507152 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Fri, 18 Mar 2022 12:50:27 -0700 Subject: [PATCH 20/55] streams --- crates/libs/metadata/src/file.rs | 8 +-- crates/libs/metagen/src/lib.rs | 99 +++++++++++++++++++------------- 2 files changed, 63 insertions(+), 44 deletions(-) diff --git a/crates/libs/metadata/src/file.rs b/crates/libs/metadata/src/file.rs index 537a8c1f23..e311957b83 100644 --- a/crates/libs/metadata/src/file.rs +++ b/crates/libs/metadata/src/file.rs @@ -251,10 +251,10 @@ impl File { let stream_size = file.bytes.copy_as::(view + 4); let stream_name = file.bytes.view_as_str(view + 8); match stream_name { - b"#Strings" => file.strings = cli_offset + stream_offset, - b"#Blob" => file.blobs = cli_offset + stream_offset, - b"#~" => tables_data = (cli_offset + stream_offset, stream_size), - b"#GUID" => {} + b"#Strings" =>{ println!("#Strings"); file.strings = cli_offset + stream_offset; } + b"#Blob" => { println!("#Blob"); file.blobs = cli_offset + stream_offset; } + b"#~" => { println!("#~"); tables_data = (cli_offset + stream_offset, stream_size); } + b"#GUID" => { println!("#GUID"); } b"#US" => {} _ => unimplemented!(), } diff --git a/crates/libs/metagen/src/lib.rs b/crates/libs/metagen/src/lib.rs index d921e2742c..b6d14091e2 100644 --- a/crates/libs/metagen/src/lib.rs +++ b/crates/libs/metagen/src/lib.rs @@ -10,17 +10,25 @@ pub fn test() { let mut optional = OptionalHeader::new(); let mut section = SectionHeader::new(); let mut clr = ClrHeader::new(); - let metadata = MetadataHeader::new(); + let metadata = MetadataHeader::new(4); + let guids = Guids::default(); let strings = Strings::default(); let blobs = Blobs::default(); let tables = Tables::default(); // TODO: populate CLI metadata - let mut strings = strings.buffer(); - let mut blobs = blobs.buffer(); - let mut tables = tables.buffer(); + let mut guids = guids.stream(); + let mut strings = strings.stream(); + let mut blobs = blobs.stream(); + let mut tables = tables.stream(); - let size_of_image = optional.file_alignment as usize + size_of::() + size_of::() + size_of::() + strings.len() + blobs.len() + tables.len(); + type TablesHeader = StreamHeader<4>; + type StringsHeader = StreamHeader<12>; + type GuidsHeader = StreamHeader<8>; + type BlobsHeader = StreamHeader<8>; + + let size_of_stream_headers = size_of::() + size_of::() + size_of::() + size_of::(); + let size_of_image = optional.file_alignment as usize + size_of::() + size_of::() + size_of_stream_headers + guids.len() + strings.len() + blobs.len() + tables.len(); optional.size_of_image = round(size_of_image, optional.section_alignment as _) as _; section.virtual_size = size_of_image as u32 - optional.file_alignment; @@ -41,19 +49,21 @@ pub fn test() { let metadata_offset = buffer.len(); buffer.write(&metadata); - let stream_offset = buffer.len() - metadata_offset + size_of::(); - let mut streams = StreamHeader::new(); - streams.strings_offset = stream_offset as u32; - streams.strings_size = strings.len() as _; - streams.blobs_offset = (stream_offset + strings.len()) as u32; - streams.blobs_size = blobs.len() as _; - streams.tables_offset = (stream_offset + strings.len() + blobs.len()) as u32; - streams.tables_size = tables.len() as _; + let stream_offset = buffer.len() - metadata_offset + size_of_stream_headers; + let tables_header = TablesHeader::new(stream_offset as _, tables.len() as _, b"#~\0\0"); + let strings_header = StringsHeader::new(tables_header.next_offset(), strings.len() as _, b"#Strings\0\0\0\0"); + let guids_header = GuidsHeader::new(strings_header.next_offset(), guids.len() as _, b"#GUID\0\0\0"); + let blobs_header = BlobsHeader::new(guids_header.next_offset(), blobs.len() as _, b"#Blob\0\0\0"); + + buffer.write(&tables_header); + buffer.write(&strings_header); + buffer.write(&guids_header); + buffer.write(&blobs_header); - buffer.write(&streams); + buffer.append(&mut tables); buffer.append(&mut strings); + buffer.append(&mut guids); buffer.append(&mut blobs); - buffer.append(&mut tables); assert_eq!(clr.meta_data.size as usize, buffer.len() - metadata_offset); assert_eq!(size_of_image, buffer.len()); @@ -265,42 +275,35 @@ struct MetadataHeader { } impl MetadataHeader { - fn new() -> Self { + fn new(streams: u16) -> Self { Self { signature: 0x424A_5342, major_version: 1, minor_version: 1, length: 20, version: *b"WindowsRuntime\0\0\0\0\0\0", - streams: 3, + streams, ..Default::default() } } } #[repr(C)] -#[derive(Default)] -struct StreamHeader { - strings_offset: u32, - strings_size: u32, - strings_name: [u8; 12], - blobs_offset: u32, - blobs_size: u32, - blobs_name: [u8; 8], - tables_offset: u32, - tables_size: u32, - tables_name: [u8; 4], +struct StreamHeader { + offset: u32, + size: u32, + name: [u8; LEN], } -impl StreamHeader { - fn new() -> Self { +impl StreamHeader { + fn new(offset: u32, size: u32, name: &[u8; LEN]) -> Self { Self { - strings_name: *b"#Strings\0\0\0\0", - blobs_name: *b"#Blob\0\0\0", - tables_name: *b"#~\0\0", - ..Default::default() + offset, size, name: *name } } + fn next_offset(&self) -> u32 { + self.offset + self.size + } } #[repr(C)] @@ -317,7 +320,18 @@ struct TableStreamHeader { impl TableStreamHeader { fn new() -> Self { - Self { major_version: 2, reserved2: 1, heap_sizes: 0b111, ..Default::default() } + Self { major_version: 2, reserved2: 1, heap_sizes: 0b101, ..Default::default() } + } +} + +#[derive(Default)] +struct Guids(); + +impl Guids { + fn stream(&self) -> Vec { + let mut buffer = Vec::new(); + buffer.resize(16,0); // null guid + buffer } } @@ -325,9 +339,11 @@ impl TableStreamHeader { struct Strings(BTreeSet); impl Strings { - fn buffer(&self) -> Vec { + fn stream(&self) -> Vec { let mut buffer = Vec::new(); - buffer.push(0); + buffer.push(0); // start with empty striong + + buffer.resize(round(buffer.len(), 4), 0); buffer } } @@ -336,9 +352,11 @@ impl Strings { struct Blobs(BTreeSet>); impl Blobs { - fn buffer(&self) -> Vec { + fn stream(&self) -> Vec { let mut buffer = Vec::new(); - buffer.push(0); + buffer.push(0); // start with empty blob + + buffer.resize(round(buffer.len(), 4), 0); buffer } } @@ -349,10 +367,11 @@ struct Tables { } impl Tables { - fn buffer(&self) -> Vec { + fn stream(&self) -> Vec { let mut buffer = Vec::new(); let header = TableStreamHeader::new(); buffer.write(&header); + buffer.resize(round(buffer.len(), 4), 0); buffer } } From 70aa2eb1fcf613c840a3ddb07b3aa7e55e65b330 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Fri, 18 Mar 2022 12:56:34 -0700 Subject: [PATCH 21/55] clean --- crates/libs/metadata/src/file.rs | 8 ++++---- crates/libs/metagen/src/lib.rs | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/crates/libs/metadata/src/file.rs b/crates/libs/metadata/src/file.rs index e311957b83..537a8c1f23 100644 --- a/crates/libs/metadata/src/file.rs +++ b/crates/libs/metadata/src/file.rs @@ -251,10 +251,10 @@ impl File { let stream_size = file.bytes.copy_as::(view + 4); let stream_name = file.bytes.view_as_str(view + 8); match stream_name { - b"#Strings" =>{ println!("#Strings"); file.strings = cli_offset + stream_offset; } - b"#Blob" => { println!("#Blob"); file.blobs = cli_offset + stream_offset; } - b"#~" => { println!("#~"); tables_data = (cli_offset + stream_offset, stream_size); } - b"#GUID" => { println!("#GUID"); } + b"#Strings" => file.strings = cli_offset + stream_offset, + b"#Blob" => file.blobs = cli_offset + stream_offset, + b"#~" => tables_data = (cli_offset + stream_offset, stream_size), + b"#GUID" => {} b"#US" => {} _ => unimplemented!(), } diff --git a/crates/libs/metagen/src/lib.rs b/crates/libs/metagen/src/lib.rs index b6d14091e2..f333b71571 100644 --- a/crates/libs/metagen/src/lib.rs +++ b/crates/libs/metagen/src/lib.rs @@ -320,7 +320,7 @@ struct TableStreamHeader { impl TableStreamHeader { fn new() -> Self { - Self { major_version: 2, reserved2: 1, heap_sizes: 0b101, ..Default::default() } + Self { major_version: 2, reserved2: 1, heap_sizes: 0b111, ..Default::default() } } } @@ -330,7 +330,7 @@ struct Guids(); impl Guids { fn stream(&self) -> Vec { let mut buffer = Vec::new(); - buffer.resize(16,0); // null guid + buffer.resize(16,0); // zero guid buffer } } @@ -341,7 +341,7 @@ struct Strings(BTreeSet); impl Strings { fn stream(&self) -> Vec { let mut buffer = Vec::new(); - buffer.push(0); // start with empty striong + buffer.push(0); // start with empty string buffer.resize(round(buffer.len(), 4), 0); buffer @@ -354,7 +354,7 @@ struct Blobs(BTreeSet>); impl Blobs { fn stream(&self) -> Vec { let mut buffer = Vec::new(); - buffer.push(0); // start with empty blob + buffer.push(0); // start with zero byte buffer.resize(round(buffer.len(), 4), 0); buffer From ef875c6a56fc9135afda35cd4bb14bd215b14a23 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Fri, 18 Mar 2022 13:58:46 -0700 Subject: [PATCH 22/55] Module --- crates/libs/metagen/src/lib.rs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/crates/libs/metagen/src/lib.rs b/crates/libs/metagen/src/lib.rs index f333b71571..05cf96a791 100644 --- a/crates/libs/metagen/src/lib.rs +++ b/crates/libs/metagen/src/lib.rs @@ -1,5 +1,8 @@ // https://docs.microsoft.com/en-us/windows/win32/debug/pe-format +// TODO: maybe used sqlite as an intermediate format for collecting the metadata? +// Using the rusqlite crate? + use std::collections::*; use std::mem::*; use std::slice::*; @@ -320,7 +323,7 @@ struct TableStreamHeader { impl TableStreamHeader { fn new() -> Self { - Self { major_version: 2, reserved2: 1, heap_sizes: 0b111, ..Default::default() } + Self { major_version: 2, reserved2: 1, heap_sizes: 0b101, valid: 0b1, ..Default::default() } } } @@ -371,6 +374,17 @@ impl Tables { let mut buffer = Vec::new(); let header = TableStreamHeader::new(); buffer.write(&header); + + // row sizes + buffer.write(&1u32); // Module + + // Module table + buffer.write(&0u16); // Generation + buffer.write(&0u32); // Name + buffer.write(&0u32); // Mvid + buffer.write(&0u32); // EncId + buffer.write(&0u32); // EncBaseId + buffer.resize(round(buffer.len(), 4), 0); buffer } From 85c4bea4ae95b01dd1d97277681c4419562a0c1f Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Fri, 18 Mar 2022 14:17:58 -0700 Subject: [PATCH 23/55] fmt --- crates/libs/metagen/src/lib.rs | 27 +++++++-------------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/crates/libs/metagen/src/lib.rs b/crates/libs/metagen/src/lib.rs index 05cf96a791..a487b44a8c 100644 --- a/crates/libs/metagen/src/lib.rs +++ b/crates/libs/metagen/src/lib.rs @@ -1,8 +1,5 @@ // https://docs.microsoft.com/en-us/windows/win32/debug/pe-format -// TODO: maybe used sqlite as an intermediate format for collecting the metadata? -// Using the rusqlite crate? - use std::collections::*; use std::mem::*; use std::slice::*; @@ -279,15 +276,7 @@ struct MetadataHeader { impl MetadataHeader { fn new(streams: u16) -> Self { - Self { - signature: 0x424A_5342, - major_version: 1, - minor_version: 1, - length: 20, - version: *b"WindowsRuntime\0\0\0\0\0\0", - streams, - ..Default::default() - } + Self { signature: 0x424A_5342, major_version: 1, minor_version: 1, length: 20, version: *b"WindowsRuntime\0\0\0\0\0\0", streams, ..Default::default() } } } @@ -300,9 +289,7 @@ struct StreamHeader { impl StreamHeader { fn new(offset: u32, size: u32, name: &[u8; LEN]) -> Self { - Self { - offset, size, name: *name - } + Self { offset, size, name: *name } } fn next_offset(&self) -> u32 { self.offset + self.size @@ -333,7 +320,7 @@ struct Guids(); impl Guids { fn stream(&self) -> Vec { let mut buffer = Vec::new(); - buffer.resize(16,0); // zero guid + buffer.resize(16, 0); // zero guid buffer } } @@ -379,11 +366,11 @@ impl Tables { buffer.write(&1u32); // Module // Module table - buffer.write(&0u16); // Generation + buffer.write(&0u16); // Generation (reserved) buffer.write(&0u32); // Name - buffer.write(&0u32); // Mvid - buffer.write(&0u32); // EncId - buffer.write(&0u32); // EncBaseId + buffer.write(&1u32); // Mvid + buffer.write(&0u32); // EncId (reserved) + buffer.write(&0u32); // EncBaseId (reserved) buffer.resize(round(buffer.len(), 4), 0); buffer From 7fc510e3ebd32b1aaa0fd641708d1027dc981e27 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Fri, 18 Mar 2022 14:31:29 -0700 Subject: [PATCH 24/55] 4096 --- crates/libs/metagen/src/lib.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/crates/libs/metagen/src/lib.rs b/crates/libs/metagen/src/lib.rs index a487b44a8c..b9c03a1af8 100644 --- a/crates/libs/metagen/src/lib.rs +++ b/crates/libs/metagen/src/lib.rs @@ -34,9 +34,9 @@ pub fn test() { section.virtual_size = size_of_image as u32 - optional.file_alignment; section.size_of_raw_data = round(section.virtual_size as _, optional.file_alignment as _) as _; - optional.data_directory[14] = DataDirectory { virtual_address: 4096, size: size_of::() as _ }; + optional.data_directory[14] = DataDirectory { virtual_address: SECTION_ALIGNMENT, size: size_of::() as _ }; section.pointer_to_raw_data = optional.file_alignment; - clr.meta_data = DataDirectory { virtual_address: 4096 + size_of::() as u32, size: section.virtual_size - size_of::() as u32 }; + clr.meta_data = DataDirectory { virtual_address: SECTION_ALIGNMENT + size_of::() as u32, size: section.virtual_size - size_of::() as u32 }; let mut buffer = Vec::::new(); buffer.write(&dos); @@ -88,6 +88,8 @@ impl Write for Vec { } } +const SECTION_ALIGNMENT: u32 = 4096; + #[repr(C)] #[derive(Default)] struct DosHeader { @@ -192,7 +194,7 @@ impl OptionalHeader { major_linker_version: 11, size_of_initialized_data: 1024, image_base: 0x400000, - section_alignment: 4096, + section_alignment: SECTION_ALIGNMENT, file_alignment: 512, major_operating_system_version: 6, minor_operating_system_version: 2, @@ -234,7 +236,7 @@ struct SectionHeader { impl SectionHeader { fn new() -> Self { - Self { name: *b".text\0\0\0", characteristics: 0x4000_0020, virtual_address: 4096, ..Default::default() } + Self { name: *b".text\0\0\0", characteristics: 0x4000_0020, virtual_address: SECTION_ALIGNMENT, ..Default::default() } } } From f2e3d85928d77174b906e4238f0dd693fabb7790 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Fri, 18 Mar 2022 14:45:20 -0700 Subject: [PATCH 25/55] pe --- crates/libs/metagen/src/lib.rs | 325 +++------------------------------ crates/libs/metagen/src/pe.rs | 288 +++++++++++++++++++++++++++++ 2 files changed, 311 insertions(+), 302 deletions(-) create mode 100644 crates/libs/metagen/src/pe.rs diff --git a/crates/libs/metagen/src/lib.rs b/crates/libs/metagen/src/lib.rs index b9c03a1af8..c6b6828324 100644 --- a/crates/libs/metagen/src/lib.rs +++ b/crates/libs/metagen/src/lib.rs @@ -1,79 +1,21 @@ // https://docs.microsoft.com/en-us/windows/win32/debug/pe-format +mod pe; use std::collections::*; use std::mem::*; use std::slice::*; pub fn test() { - let dos = DosHeader::new(); - let pe = PeHeader::new(); - let mut optional = OptionalHeader::new(); - let mut section = SectionHeader::new(); - let mut clr = ClrHeader::new(); - let metadata = MetadataHeader::new(4); - - let guids = Guids::default(); let strings = Strings::default(); let blobs = Blobs::default(); let tables = Tables::default(); - // TODO: populate CLI metadata - let mut guids = guids.stream(); - let mut strings = strings.stream(); - let mut blobs = blobs.stream(); - let mut tables = tables.stream(); - - type TablesHeader = StreamHeader<4>; - type StringsHeader = StreamHeader<12>; - type GuidsHeader = StreamHeader<8>; - type BlobsHeader = StreamHeader<8>; - - let size_of_stream_headers = size_of::() + size_of::() + size_of::() + size_of::(); - let size_of_image = optional.file_alignment as usize + size_of::() + size_of::() + size_of_stream_headers + guids.len() + strings.len() + blobs.len() + tables.len(); - - optional.size_of_image = round(size_of_image, optional.section_alignment as _) as _; - section.virtual_size = size_of_image as u32 - optional.file_alignment; - section.size_of_raw_data = round(section.virtual_size as _, optional.file_alignment as _) as _; - - optional.data_directory[14] = DataDirectory { virtual_address: SECTION_ALIGNMENT, size: size_of::() as _ }; - section.pointer_to_raw_data = optional.file_alignment; - clr.meta_data = DataDirectory { virtual_address: SECTION_ALIGNMENT + size_of::() as u32, size: section.virtual_size - size_of::() as u32 }; - - let mut buffer = Vec::::new(); - buffer.write(&dos); - buffer.write(&pe); - buffer.write(&optional); - buffer.write(§ion); - debug_assert!(buffer.len() < optional.file_alignment as _); - buffer.resize(optional.file_alignment as _, 0); - buffer.write(&clr); - let metadata_offset = buffer.len(); - buffer.write(&metadata); - - let stream_offset = buffer.len() - metadata_offset + size_of_stream_headers; - let tables_header = TablesHeader::new(stream_offset as _, tables.len() as _, b"#~\0\0"); - let strings_header = StringsHeader::new(tables_header.next_offset(), strings.len() as _, b"#Strings\0\0\0\0"); - let guids_header = GuidsHeader::new(strings_header.next_offset(), guids.len() as _, b"#GUID\0\0\0"); - let blobs_header = BlobsHeader::new(guids_header.next_offset(), blobs.len() as _, b"#Blob\0\0\0"); - - buffer.write(&tables_header); - buffer.write(&strings_header); - buffer.write(&guids_header); - buffer.write(&blobs_header); - buffer.append(&mut tables); - buffer.append(&mut strings); - buffer.append(&mut guids); - buffer.append(&mut blobs); - - assert_eq!(clr.meta_data.size as usize, buffer.len() - metadata_offset); - assert_eq!(size_of_image, buffer.len()); - - std::fs::write("/git/test.winmd", buffer).unwrap(); + pe::write("/git/test.winmd", &strings, &blobs, &tables); } -fn round(size: usize, page: usize) -> usize { - let page = page - 1; - (size + page) & !page +fn round(size: usize, round: usize) -> usize { + let round = round - 1; + (size + round) & !round } trait Write { @@ -88,245 +30,6 @@ impl Write for Vec { } } -const SECTION_ALIGNMENT: u32 = 4096; - -#[repr(C)] -#[derive(Default)] -struct DosHeader { - magic: u16, - cblp: u16, - cp: u16, - crlc: u16, - cparhdr: u16, - minalloc: u16, - maxalloc: u16, - ss: u16, - sp: u16, - csum: u16, - ip: u16, - cs: u16, - lfarlc: u16, - ovno: u16, - res: [u16; 4], - oemid: u16, - oeminfo: u16, - res2: [u16; 10], - lfanew: i32, -} - -impl DosHeader { - fn new() -> Self { - Self { - magic: 0x5A4D, // MZ - lfarlc: 64, // file address of relocation table - lfanew: size_of::() as _, // file address of next header - ..Default::default() - } - } -} - -#[repr(C)] -#[derive(Default)] -struct PeHeader { - signature: u32, - machine: u16, - number_of_sections: u16, - time_date_stamp: u32, - pointer_to_symbol_table: u32, - number_of_symbols: u32, - size_of_optional_header: u16, - characteristics: u16, -} - -impl PeHeader { - fn new() -> Self { - Self { - signature: 0x4550, // PE\0\0 - machine: 0x14C, // x86 - number_of_sections: 1, - size_of_optional_header: size_of::() as _, - characteristics: 0x2102, // DLL - ..Default::default() - } - } -} - -#[repr(C)] -#[derive(Default)] -struct OptionalHeader { - magic: u16, - major_linker_version: u8, - minor_linker_version: u8, - size_of_code: u32, - size_of_initialized_data: u32, - size_of_uninitialized_data: u32, - address_of_entry_point: u32, - base_of_code: u32, - base_of_data: u32, - image_base: u32, - section_alignment: u32, - file_alignment: u32, - major_operating_system_version: u16, - minor_operating_system_version: u16, - major_image_version: u16, - minor_image_version: u16, - major_subsystem_version: u16, - minor_subsystem_version: u16, - win32_version_value: u32, - size_of_image: u32, - size_of_headers: u32, - check_sum: u32, - subsystem: u16, - dll_characteristics: u16, - size_of_stack_reserve: u32, - size_of_stack_commit: u32, - size_of_heap_reserve: u32, - size_of_heap_commit: u32, - loader_flags: u32, - number_of_rva_and_sizes: u32, - data_directory: [DataDirectory; 16], -} - -impl OptionalHeader { - fn new() -> Self { - Self { - magic: 0x10B, // PE32 - major_linker_version: 11, - size_of_initialized_data: 1024, - image_base: 0x400000, - section_alignment: SECTION_ALIGNMENT, - file_alignment: 512, - major_operating_system_version: 6, - minor_operating_system_version: 2, - major_subsystem_version: 6, - minor_subsystem_version: 2, - size_of_headers: 512, - subsystem: 3, // console - dll_characteristics: 0x540, - size_of_stack_reserve: 0x100000, - size_of_heap_reserve: 4096, - loader_flags: 0x100000, - number_of_rva_and_sizes: 16, - ..Default::default() - } - } -} - -#[repr(C)] -#[derive(Default)] -struct DataDirectory { - virtual_address: u32, - size: u32, -} - -#[repr(C)] -#[derive(Default)] -struct SectionHeader { - name: [u8; 8], - virtual_size: u32, - virtual_address: u32, - size_of_raw_data: u32, - pointer_to_raw_data: u32, - pointer_to_relocations: u32, - pointer_to_line_numbers: u32, - number_of_relocations: u16, - number_of_line_numbers: u16, - characteristics: u32, -} - -impl SectionHeader { - fn new() -> Self { - Self { name: *b".text\0\0\0", characteristics: 0x4000_0020, virtual_address: SECTION_ALIGNMENT, ..Default::default() } - } -} - -#[repr(C)] -#[derive(Default)] -struct ClrHeader { - cb: u32, - major_runtime_version: u16, - minor_runtime_version: u16, - meta_data: DataDirectory, - flags: u32, - entry_point_token_or_entry_point_rva: u32, - resources: DataDirectory, - strong_name_signature: DataDirectory, - code_manager_table: DataDirectory, - vtable_fixups: DataDirectory, - export_address_table_jumps: DataDirectory, - managed_native_header: DataDirectory, -} - -impl ClrHeader { - fn new() -> Self { - Self { cb: size_of::() as _, major_runtime_version: 2, minor_runtime_version: 5, flags: 0x1, ..Default::default() } - } -} - -#[repr(C)] -#[derive(Default)] -struct MetadataHeader { - signature: u32, - major_version: u16, - minor_version: u16, - reserved: u32, - length: u32, - version: [u8; 20], - flags: u16, - streams: u16, -} - -impl MetadataHeader { - fn new(streams: u16) -> Self { - Self { signature: 0x424A_5342, major_version: 1, minor_version: 1, length: 20, version: *b"WindowsRuntime\0\0\0\0\0\0", streams, ..Default::default() } - } -} - -#[repr(C)] -struct StreamHeader { - offset: u32, - size: u32, - name: [u8; LEN], -} - -impl StreamHeader { - fn new(offset: u32, size: u32, name: &[u8; LEN]) -> Self { - Self { offset, size, name: *name } - } - fn next_offset(&self) -> u32 { - self.offset + self.size - } -} - -#[repr(C)] -#[derive(Default)] -struct TableStreamHeader { - reserved1: u32, - major_version: u8, - minor_version: u8, - heap_sizes: u8, - reserved2: u8, - valid: u64, - sorted: u64, -} - -impl TableStreamHeader { - fn new() -> Self { - Self { major_version: 2, reserved2: 1, heap_sizes: 0b101, valid: 0b1, ..Default::default() } - } -} - -#[derive(Default)] -struct Guids(); - -impl Guids { - fn stream(&self) -> Vec { - let mut buffer = Vec::new(); - buffer.resize(16, 0); // zero guid - buffer - } -} - #[derive(Default)] struct Strings(BTreeSet); @@ -378,3 +81,21 @@ impl Tables { buffer } } + +#[repr(C)] +#[derive(Default)] +struct TableStreamHeader { + reserved1: u32, + major_version: u8, + minor_version: u8, + heap_sizes: u8, + reserved2: u8, + valid: u64, + sorted: u64, +} + +impl TableStreamHeader { + fn new() -> Self { + Self { major_version: 2, reserved2: 1, heap_sizes: 0b101, valid: 0b1, ..Default::default() } + } +} diff --git a/crates/libs/metagen/src/pe.rs b/crates/libs/metagen/src/pe.rs new file mode 100644 index 0000000000..d24b7852fe --- /dev/null +++ b/crates/libs/metagen/src/pe.rs @@ -0,0 +1,288 @@ +// https://docs.microsoft.com/en-us/windows/win32/debug/pe-format + +use crate::*; +use std::mem::*; + +pub(crate) fn write(filename: &str, strings: &Strings, blobs: &Blobs, tables: &Tables) { + let dos = DosHeader::new(); + let pe = PeHeader::new(); + let mut optional = OptionalHeader::new(); + let mut section = SectionHeader::new(); + let mut clr = ClrHeader::new(); + let metadata = MetadataHeader::new(4); + + let guids = Guids::default(); + let mut guids = guids.stream(); + let mut strings = strings.stream(); + let mut blobs = blobs.stream(); + let mut tables = tables.stream(); + + type TablesHeader = StreamHeader<4>; + type StringsHeader = StreamHeader<12>; + type GuidsHeader = StreamHeader<8>; + type BlobsHeader = StreamHeader<8>; + + let size_of_stream_headers = size_of::() + size_of::() + size_of::() + size_of::(); + let size_of_image = optional.file_alignment as usize + size_of::() + size_of::() + size_of_stream_headers + guids.len() + strings.len() + blobs.len() + tables.len(); + + optional.size_of_image = round(size_of_image, optional.section_alignment as _) as _; + section.virtual_size = size_of_image as u32 - optional.file_alignment; + section.size_of_raw_data = round(section.virtual_size as _, optional.file_alignment as _) as _; + + optional.data_directory[14] = DataDirectory { virtual_address: SECTION_ALIGNMENT, size: size_of::() as _ }; + section.pointer_to_raw_data = optional.file_alignment; + clr.meta_data = DataDirectory { virtual_address: SECTION_ALIGNMENT + size_of::() as u32, size: section.virtual_size - size_of::() as u32 }; + + let mut buffer = Vec::::new(); + buffer.write(&dos); + buffer.write(&pe); + buffer.write(&optional); + buffer.write(§ion); + debug_assert!(buffer.len() < optional.file_alignment as _); + buffer.resize(optional.file_alignment as _, 0); + buffer.write(&clr); + let metadata_offset = buffer.len(); + buffer.write(&metadata); + + let stream_offset = buffer.len() - metadata_offset + size_of_stream_headers; + let tables_header = TablesHeader::new(stream_offset as _, tables.len() as _, b"#~\0\0"); + let strings_header = StringsHeader::new(tables_header.next_offset(), strings.len() as _, b"#Strings\0\0\0\0"); + let guids_header = GuidsHeader::new(strings_header.next_offset(), guids.len() as _, b"#GUID\0\0\0"); + let blobs_header = BlobsHeader::new(guids_header.next_offset(), blobs.len() as _, b"#Blob\0\0\0"); + + buffer.write(&tables_header); + buffer.write(&strings_header); + buffer.write(&guids_header); + buffer.write(&blobs_header); + + buffer.append(&mut tables); + buffer.append(&mut strings); + buffer.append(&mut guids); + buffer.append(&mut blobs); + + assert_eq!(clr.meta_data.size as usize, buffer.len() - metadata_offset); + assert_eq!(size_of_image, buffer.len()); + + std::fs::write(filename, buffer).unwrap(); +} + +const SECTION_ALIGNMENT: u32 = 4096; + +#[repr(C)] +#[derive(Default)] +struct DosHeader { + magic: u16, + cblp: u16, + cp: u16, + crlc: u16, + cparhdr: u16, + minalloc: u16, + maxalloc: u16, + ss: u16, + sp: u16, + csum: u16, + ip: u16, + cs: u16, + lfarlc: u16, + ovno: u16, + res: [u16; 4], + oemid: u16, + oeminfo: u16, + res2: [u16; 10], + lfanew: i32, +} + +impl DosHeader { + fn new() -> Self { + Self { + magic: 0x5A4D, // MZ + lfarlc: 64, // file address of relocation table + lfanew: size_of::() as _, // file address of next header + ..Default::default() + } + } +} + +#[repr(C)] +#[derive(Default)] +struct PeHeader { + signature: u32, + machine: u16, + number_of_sections: u16, + time_date_stamp: u32, + pointer_to_symbol_table: u32, + number_of_symbols: u32, + size_of_optional_header: u16, + characteristics: u16, +} + +impl PeHeader { + fn new() -> Self { + Self { + signature: 0x4550, // PE\0\0 + machine: 0x14C, // x86 + number_of_sections: 1, + size_of_optional_header: size_of::() as _, + characteristics: 0x2102, // DLL + ..Default::default() + } + } +} + +#[repr(C)] +#[derive(Default)] +struct OptionalHeader { + magic: u16, + major_linker_version: u8, + minor_linker_version: u8, + size_of_code: u32, + size_of_initialized_data: u32, + size_of_uninitialized_data: u32, + address_of_entry_point: u32, + base_of_code: u32, + base_of_data: u32, + image_base: u32, + section_alignment: u32, + file_alignment: u32, + major_operating_system_version: u16, + minor_operating_system_version: u16, + major_image_version: u16, + minor_image_version: u16, + major_subsystem_version: u16, + minor_subsystem_version: u16, + win32_version_value: u32, + size_of_image: u32, + size_of_headers: u32, + check_sum: u32, + subsystem: u16, + dll_characteristics: u16, + size_of_stack_reserve: u32, + size_of_stack_commit: u32, + size_of_heap_reserve: u32, + size_of_heap_commit: u32, + loader_flags: u32, + number_of_rva_and_sizes: u32, + data_directory: [DataDirectory; 16], +} + +impl OptionalHeader { + fn new() -> Self { + Self { + magic: 0x10B, // PE32 + major_linker_version: 11, + size_of_initialized_data: 1024, + image_base: 0x400000, + section_alignment: SECTION_ALIGNMENT, + file_alignment: 512, + major_operating_system_version: 6, + minor_operating_system_version: 2, + major_subsystem_version: 6, + minor_subsystem_version: 2, + size_of_headers: 512, + subsystem: 3, // console + dll_characteristics: 0x540, + size_of_stack_reserve: 0x100000, + size_of_heap_reserve: 4096, + loader_flags: 0x100000, + number_of_rva_and_sizes: 16, + ..Default::default() + } + } +} + +#[repr(C)] +#[derive(Default)] +struct DataDirectory { + virtual_address: u32, + size: u32, +} + +#[repr(C)] +#[derive(Default)] +struct SectionHeader { + name: [u8; 8], + virtual_size: u32, + virtual_address: u32, + size_of_raw_data: u32, + pointer_to_raw_data: u32, + pointer_to_relocations: u32, + pointer_to_line_numbers: u32, + number_of_relocations: u16, + number_of_line_numbers: u16, + characteristics: u32, +} + +impl SectionHeader { + fn new() -> Self { + Self { name: *b".text\0\0\0", characteristics: 0x4000_0020, virtual_address: SECTION_ALIGNMENT, ..Default::default() } + } +} + +#[repr(C)] +#[derive(Default)] +struct ClrHeader { + cb: u32, + major_runtime_version: u16, + minor_runtime_version: u16, + meta_data: DataDirectory, + flags: u32, + entry_point_token_or_entry_point_rva: u32, + resources: DataDirectory, + strong_name_signature: DataDirectory, + code_manager_table: DataDirectory, + vtable_fixups: DataDirectory, + export_address_table_jumps: DataDirectory, + managed_native_header: DataDirectory, +} + +impl ClrHeader { + fn new() -> Self { + Self { cb: size_of::() as _, major_runtime_version: 2, minor_runtime_version: 5, flags: 0x1, ..Default::default() } + } +} + +#[repr(C)] +#[derive(Default)] +struct MetadataHeader { + signature: u32, + major_version: u16, + minor_version: u16, + reserved: u32, + length: u32, + version: [u8; 20], + flags: u16, + streams: u16, +} + +impl MetadataHeader { + fn new(streams: u16) -> Self { + Self { signature: 0x424A_5342, major_version: 1, minor_version: 1, length: 20, version: *b"WindowsRuntime\0\0\0\0\0\0", streams, ..Default::default() } + } +} + +#[repr(C)] +struct StreamHeader { + offset: u32, + size: u32, + name: [u8; LEN], +} + +impl StreamHeader { + fn new(offset: u32, size: u32, name: &[u8; LEN]) -> Self { + Self { offset, size, name: *name } + } + fn next_offset(&self) -> u32 { + self.offset + self.size + } +} + +#[derive(Default)] +struct Guids(); + +impl Guids { + fn stream(&self) -> Vec { + let mut buffer = Vec::new(); + buffer.resize(16, 0); // zero guid + buffer + } +} From f7084e8e85e3b909fc79b62c3f4f8f97c2a555de Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Fri, 18 Mar 2022 15:07:14 -0700 Subject: [PATCH 26/55] pe --- crates/libs/metagen/src/lib.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/crates/libs/metagen/src/lib.rs b/crates/libs/metagen/src/lib.rs index c6b6828324..f7cbca0507 100644 --- a/crates/libs/metagen/src/lib.rs +++ b/crates/libs/metagen/src/lib.rs @@ -6,7 +6,9 @@ use std::mem::*; use std::slice::*; pub fn test() { - let strings = Strings::default(); + let mut strings = Strings::default(); + strings.0.insert("hello".to_string()); + strings.0.insert("world".to_string()); let blobs = Blobs::default(); let tables = Tables::default(); @@ -38,6 +40,11 @@ impl Strings { let mut buffer = Vec::new(); buffer.push(0); // start with empty string + for value in &self.0 { + buffer.extend_from_slice(value.as_bytes()); + buffer.push(0); // terminator + } + buffer.resize(round(buffer.len(), 4), 0); buffer } @@ -96,6 +103,6 @@ struct TableStreamHeader { impl TableStreamHeader { fn new() -> Self { - Self { major_version: 2, reserved2: 1, heap_sizes: 0b101, valid: 0b1, ..Default::default() } + Self { major_version: 2, reserved2: 1, heap_sizes: 0b111, valid: 0b1, ..Default::default() } } } From 0ef060fe44eaec0d8e35fa6786016c7af429be02 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Fri, 18 Mar 2022 15:32:55 -0700 Subject: [PATCH 27/55] streams --- crates/libs/metagen/src/lib.rs | 39 ++++-------------------------- crates/libs/metagen/src/pe.rs | 43 ++++++++++++++++++++++++---------- 2 files changed, 35 insertions(+), 47 deletions(-) diff --git a/crates/libs/metagen/src/lib.rs b/crates/libs/metagen/src/lib.rs index f7cbca0507..245717b5c1 100644 --- a/crates/libs/metagen/src/lib.rs +++ b/crates/libs/metagen/src/lib.rs @@ -6,10 +6,10 @@ use std::mem::*; use std::slice::*; pub fn test() { - let mut strings = Strings::default(); - strings.0.insert("hello".to_string()); - strings.0.insert("world".to_string()); - let blobs = Blobs::default(); + let mut strings = BTreeSet::::new(); + strings.insert("hello".to_string()); + strings.insert("world".to_string()); + let blobs = BTreeSet::>::new(); let tables = Tables::default(); pe::write("/git/test.winmd", &strings, &blobs, &tables); @@ -32,37 +32,6 @@ impl Write for Vec { } } -#[derive(Default)] -struct Strings(BTreeSet); - -impl Strings { - fn stream(&self) -> Vec { - let mut buffer = Vec::new(); - buffer.push(0); // start with empty string - - for value in &self.0 { - buffer.extend_from_slice(value.as_bytes()); - buffer.push(0); // terminator - } - - buffer.resize(round(buffer.len(), 4), 0); - buffer - } -} - -#[derive(Default)] -struct Blobs(BTreeSet>); - -impl Blobs { - fn stream(&self) -> Vec { - let mut buffer = Vec::new(); - buffer.push(0); // start with zero byte - - buffer.resize(round(buffer.len(), 4), 0); - buffer - } -} - #[derive(Default)] struct Tables { // TODO: just use fixed 4 byte index sizes diff --git a/crates/libs/metagen/src/pe.rs b/crates/libs/metagen/src/pe.rs index d24b7852fe..06f8cff436 100644 --- a/crates/libs/metagen/src/pe.rs +++ b/crates/libs/metagen/src/pe.rs @@ -3,7 +3,7 @@ use crate::*; use std::mem::*; -pub(crate) fn write(filename: &str, strings: &Strings, blobs: &Blobs, tables: &Tables) { +pub(crate) fn write(filename: &str, strings: &BTreeSet, blobs: &BTreeSet>, tables: &Tables) { let dos = DosHeader::new(); let pe = PeHeader::new(); let mut optional = OptionalHeader::new(); @@ -11,10 +11,9 @@ pub(crate) fn write(filename: &str, strings: &Strings, blobs: &Blobs, tables: &T let mut clr = ClrHeader::new(); let metadata = MetadataHeader::new(4); - let guids = Guids::default(); - let mut guids = guids.stream(); - let mut strings = strings.stream(); - let mut blobs = blobs.stream(); + let mut guids = guid_stream(); + let mut strings = string_stream(strings); + let mut blobs = blob_stream(blobs); let mut tables = tables.stream(); type TablesHeader = StreamHeader<4>; @@ -276,13 +275,33 @@ impl StreamHeader { } } -#[derive(Default)] -struct Guids(); +fn guid_stream() -> Vec { + let mut buffer = Vec::new(); + buffer.resize(16, 0); // zero guid + buffer +} + +fn string_stream(strings: &BTreeSet) -> Vec { + let mut buffer = Vec::new(); + buffer.push(0); // start with empty string -impl Guids { - fn stream(&self) -> Vec { - let mut buffer = Vec::new(); - buffer.resize(16, 0); // zero guid - buffer + for value in strings { + buffer.extend_from_slice(value.as_bytes()); + buffer.push(0); // terminator } + + buffer.resize(round(buffer.len(), 4), 0); + buffer +} + +fn blob_stream(blobs: &BTreeSet>) -> Vec { + let mut buffer = Vec::new(); + buffer.push(0); // start with zero byte + + for value in blobs { + buffer.extend_from_slice(value); + } + + buffer.resize(round(buffer.len(), 4), 0); + buffer } From dec3b4df3708e3ce13c8f411d26532eb13421137 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Fri, 18 Mar 2022 16:26:02 -0700 Subject: [PATCH 28/55] ILSpy works --- crates/libs/metagen/src/lib.rs | 41 +++++++++++++++++++++++++++------- crates/libs/metagen/src/pe.rs | 4 ++-- 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/crates/libs/metagen/src/lib.rs b/crates/libs/metagen/src/lib.rs index 245717b5c1..b38c009d10 100644 --- a/crates/libs/metagen/src/lib.rs +++ b/crates/libs/metagen/src/lib.rs @@ -7,8 +7,7 @@ use std::slice::*; pub fn test() { let mut strings = BTreeSet::::new(); - strings.insert("hello".to_string()); - strings.insert("world".to_string()); + strings.insert("mscorlib".to_string()); let blobs = BTreeSet::>::new(); let tables = Tables::default(); @@ -33,11 +32,10 @@ impl Write for Vec { } #[derive(Default)] -struct Tables { - // TODO: just use fixed 4 byte index sizes -} +struct Tables {} impl Tables { + // TODO: must refer to the strings/blobs containers to get their relative offsets... fn stream(&self) -> Vec { let mut buffer = Vec::new(); let header = TableStreamHeader::new(); @@ -45,19 +43,34 @@ impl Tables { // row sizes buffer.write(&1u32); // Module + buffer.write(&1u32); // AssemblyRef // Module table buffer.write(&0u16); // Generation (reserved) - buffer.write(&0u32); // Name - buffer.write(&1u32); // Mvid + buffer.write(&0u32); // Name (none) + buffer.write(&1u32); // Mvid (zero guid) buffer.write(&0u32); // EncId (reserved) buffer.write(&0u32); // EncBaseId (reserved) + // AssemblyRef table + // mscorelib entry only required by ILSpy + buffer.write(&0u16); // MajorVersion + buffer.write(&0u16); // MinorVersion + buffer.write(&0u16); // BuildNumber + buffer.write(&0u16); // RevisionNumber + buffer.write(&0u32); // Flags (none) + buffer.write(&0u32); // PublicKeyOrToken (none) + buffer.write(&1u32); // Name (mscorelib) <-- TODO: this needs to point to an offset in the strings stream + buffer.write(&0u32); // Culture (none) + buffer.write(&0u32); // HashValue (none) + buffer.resize(round(buffer.len(), 4), 0); buffer } } +// TODO: push into pe.rs and abstract this lib to deal only with the logical metadata +// in a layout independent way #[repr(C)] #[derive(Default)] struct TableStreamHeader { @@ -72,6 +85,18 @@ struct TableStreamHeader { impl TableStreamHeader { fn new() -> Self { - Self { major_version: 2, reserved2: 1, heap_sizes: 0b111, valid: 0b1, ..Default::default() } + Self { + major_version: 2, + reserved2: 1, + heap_sizes: 0b111, // 4 byte indexes + valid: TableId::Module as u64 | TableId::AssemblyRef as u64, + ..Default::default() + } } } + +// TODO: just use constants +enum TableId { + Module = 1 << 0, + AssemblyRef = 1 << 0x23, +} diff --git a/crates/libs/metagen/src/pe.rs b/crates/libs/metagen/src/pe.rs index 06f8cff436..c213dada1c 100644 --- a/crates/libs/metagen/src/pe.rs +++ b/crates/libs/metagen/src/pe.rs @@ -285,7 +285,7 @@ fn string_stream(strings: &BTreeSet) -> Vec { let mut buffer = Vec::new(); buffer.push(0); // start with empty string - for value in strings { + for value in strings { buffer.extend_from_slice(value.as_bytes()); buffer.push(0); // terminator } @@ -298,7 +298,7 @@ fn blob_stream(blobs: &BTreeSet>) -> Vec { let mut buffer = Vec::new(); buffer.push(0); // start with zero byte - for value in blobs { + for value in blobs { buffer.extend_from_slice(value); } From 8595995d56d9e681bead509eaea8dcbef0fb4871 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Mon, 21 Mar 2022 10:29:12 -0700 Subject: [PATCH 29/55] strings --- crates/libs/metagen/src/lib.rs | 6 +++-- crates/libs/metagen/src/pe.rs | 18 +++------------ crates/libs/metagen/src/strings.rs | 36 ++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 17 deletions(-) create mode 100644 crates/libs/metagen/src/strings.rs diff --git a/crates/libs/metagen/src/lib.rs b/crates/libs/metagen/src/lib.rs index b38c009d10..d5649be8d2 100644 --- a/crates/libs/metagen/src/lib.rs +++ b/crates/libs/metagen/src/lib.rs @@ -1,17 +1,19 @@ // https://docs.microsoft.com/en-us/windows/win32/debug/pe-format mod pe; +mod strings; +use strings::*; use std::collections::*; use std::mem::*; use std::slice::*; pub fn test() { - let mut strings = BTreeSet::::new(); + let mut strings = Strings::new(); strings.insert("mscorlib".to_string()); let blobs = BTreeSet::>::new(); let tables = Tables::default(); - pe::write("/git/test.winmd", &strings, &blobs, &tables); + pe::write("/git/test.winmd", strings, &blobs, &tables); } fn round(size: usize, round: usize) -> usize { diff --git a/crates/libs/metagen/src/pe.rs b/crates/libs/metagen/src/pe.rs index c213dada1c..467706e61c 100644 --- a/crates/libs/metagen/src/pe.rs +++ b/crates/libs/metagen/src/pe.rs @@ -3,7 +3,7 @@ use crate::*; use std::mem::*; -pub(crate) fn write(filename: &str, strings: &BTreeSet, blobs: &BTreeSet>, tables: &Tables) { +pub(crate) fn write(filename: &str, strings: Strings, blobs: &BTreeSet>, tables: &Tables) { let dos = DosHeader::new(); let pe = PeHeader::new(); let mut optional = OptionalHeader::new(); @@ -12,7 +12,7 @@ pub(crate) fn write(filename: &str, strings: &BTreeSet, blobs: &BTreeSet let metadata = MetadataHeader::new(4); let mut guids = guid_stream(); - let mut strings = string_stream(strings); + let mut strings = strings.into_stream(); let mut blobs = blob_stream(blobs); let mut tables = tables.stream(); @@ -281,19 +281,6 @@ fn guid_stream() -> Vec { buffer } -fn string_stream(strings: &BTreeSet) -> Vec { - let mut buffer = Vec::new(); - buffer.push(0); // start with empty string - - for value in strings { - buffer.extend_from_slice(value.as_bytes()); - buffer.push(0); // terminator - } - - buffer.resize(round(buffer.len(), 4), 0); - buffer -} - fn blob_stream(blobs: &BTreeSet>) -> Vec { let mut buffer = Vec::new(); buffer.push(0); // start with zero byte @@ -305,3 +292,4 @@ fn blob_stream(blobs: &BTreeSet>) -> Vec { buffer.resize(round(buffer.len(), 4), 0); buffer } + diff --git a/crates/libs/metagen/src/strings.rs b/crates/libs/metagen/src/strings.rs new file mode 100644 index 0000000000..23a827a674 --- /dev/null +++ b/crates/libs/metagen/src/strings.rs @@ -0,0 +1,36 @@ +use crate::*; + +pub struct Strings { + set: BTreeMap, + stream: Vec, +} + +impl Strings { + pub fn new() -> Self { + Self { + set: BTreeMap::new(), + stream: vec![0], + } + } + + pub fn insert(&mut self, value: String) -> u32 { + let pos = self.stream.len(); + let mut insert = false; + + self.set.entry(value.to_string()).or_insert_with(|| { + insert = true; + pos + }); + + if insert { + self.stream.extend_from_slice(value.as_bytes()); + self.stream.push(0); // terminator + } + + pos as _ + } + + pub fn into_stream(self) -> Vec { + self.stream + } +} From bc8114312909cfc8bc825ff46494d518ff293e79 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Mon, 21 Mar 2022 11:10:13 -0700 Subject: [PATCH 30/55] strings & tables --- crates/libs/metagen/src/lib.rs | 79 ++---------------------------- crates/libs/metagen/src/pe.rs | 9 ++-- crates/libs/metagen/src/strings.rs | 4 +- crates/libs/metagen/src/tables.rs | 76 ++++++++++++++++++++++++++++ 4 files changed, 88 insertions(+), 80 deletions(-) create mode 100644 crates/libs/metagen/src/tables.rs diff --git a/crates/libs/metagen/src/lib.rs b/crates/libs/metagen/src/lib.rs index d5649be8d2..3872e814c4 100644 --- a/crates/libs/metagen/src/lib.rs +++ b/crates/libs/metagen/src/lib.rs @@ -2,18 +2,17 @@ mod pe; mod strings; +mod tables; use strings::*; +use tables::*; use std::collections::*; use std::mem::*; use std::slice::*; pub fn test() { - let mut strings = Strings::new(); - strings.insert("mscorlib".to_string()); - let blobs = BTreeSet::>::new(); - let tables = Tables::default(); + let tables = Tables::new(); - pe::write("/git/test.winmd", strings, &blobs, &tables); + pe::write("/git/test.winmd", tables); } fn round(size: usize, round: usize) -> usize { @@ -32,73 +31,3 @@ impl Write for Vec { } } } - -#[derive(Default)] -struct Tables {} - -impl Tables { - // TODO: must refer to the strings/blobs containers to get their relative offsets... - fn stream(&self) -> Vec { - let mut buffer = Vec::new(); - let header = TableStreamHeader::new(); - buffer.write(&header); - - // row sizes - buffer.write(&1u32); // Module - buffer.write(&1u32); // AssemblyRef - - // Module table - buffer.write(&0u16); // Generation (reserved) - buffer.write(&0u32); // Name (none) - buffer.write(&1u32); // Mvid (zero guid) - buffer.write(&0u32); // EncId (reserved) - buffer.write(&0u32); // EncBaseId (reserved) - - // AssemblyRef table - // mscorelib entry only required by ILSpy - buffer.write(&0u16); // MajorVersion - buffer.write(&0u16); // MinorVersion - buffer.write(&0u16); // BuildNumber - buffer.write(&0u16); // RevisionNumber - buffer.write(&0u32); // Flags (none) - buffer.write(&0u32); // PublicKeyOrToken (none) - buffer.write(&1u32); // Name (mscorelib) <-- TODO: this needs to point to an offset in the strings stream - buffer.write(&0u32); // Culture (none) - buffer.write(&0u32); // HashValue (none) - - buffer.resize(round(buffer.len(), 4), 0); - buffer - } -} - -// TODO: push into pe.rs and abstract this lib to deal only with the logical metadata -// in a layout independent way -#[repr(C)] -#[derive(Default)] -struct TableStreamHeader { - reserved1: u32, - major_version: u8, - minor_version: u8, - heap_sizes: u8, - reserved2: u8, - valid: u64, - sorted: u64, -} - -impl TableStreamHeader { - fn new() -> Self { - Self { - major_version: 2, - reserved2: 1, - heap_sizes: 0b111, // 4 byte indexes - valid: TableId::Module as u64 | TableId::AssemblyRef as u64, - ..Default::default() - } - } -} - -// TODO: just use constants -enum TableId { - Module = 1 << 0, - AssemblyRef = 1 << 0x23, -} diff --git a/crates/libs/metagen/src/pe.rs b/crates/libs/metagen/src/pe.rs index 467706e61c..f192591d15 100644 --- a/crates/libs/metagen/src/pe.rs +++ b/crates/libs/metagen/src/pe.rs @@ -3,7 +3,7 @@ use crate::*; use std::mem::*; -pub(crate) fn write(filename: &str, strings: Strings, blobs: &BTreeSet>, tables: &Tables) { +pub(crate) fn write(filename: &str, tables: Tables) { let dos = DosHeader::new(); let pe = PeHeader::new(); let mut optional = OptionalHeader::new(); @@ -11,10 +11,13 @@ pub(crate) fn write(filename: &str, strings: Strings, blobs: &BTreeSet>, let mut clr = ClrHeader::new(); let metadata = MetadataHeader::new(4); + let mut strings = Strings::new(); + let blobs = BTreeSet::>::new(); + + let mut tables = tables.into_stream(&mut strings); let mut guids = guid_stream(); let mut strings = strings.into_stream(); - let mut blobs = blob_stream(blobs); - let mut tables = tables.stream(); + let mut blobs = blob_stream(&blobs); type TablesHeader = StreamHeader<4>; type StringsHeader = StreamHeader<12>; diff --git a/crates/libs/metagen/src/strings.rs b/crates/libs/metagen/src/strings.rs index 23a827a674..bde22b30d0 100644 --- a/crates/libs/metagen/src/strings.rs +++ b/crates/libs/metagen/src/strings.rs @@ -1,6 +1,6 @@ use crate::*; -pub struct Strings { +pub(crate) struct Strings { set: BTreeMap, stream: Vec, } @@ -13,7 +13,7 @@ impl Strings { } } - pub fn insert(&mut self, value: String) -> u32 { + pub fn insert(&mut self, value: &str) -> u32 { let pos = self.stream.len(); let mut insert = false; diff --git a/crates/libs/metagen/src/tables.rs b/crates/libs/metagen/src/tables.rs new file mode 100644 index 0000000000..1720f6ccd3 --- /dev/null +++ b/crates/libs/metagen/src/tables.rs @@ -0,0 +1,76 @@ +use crate::*; + +pub(crate) struct Tables {} + +impl Tables { + pub fn new() -> Self { + Self { + + } + } + + pub fn into_stream(&self, strings: &mut Strings) -> Vec { + let mut buffer = Vec::new(); + let header = TableStreamHeader::new(); + buffer.write(&header); + + // row sizes + buffer.write(&1u32); // Module + buffer.write(&1u32); // AssemblyRef + + // Module table + buffer.write(&0u16); // Generation (reserved) + buffer.write(&0u32); // Name (none) + buffer.write(&1u32); // Mvid (zero guid) + buffer.write(&0u32); // EncId (reserved) + buffer.write(&0u32); // EncBaseId (reserved) + + // AssemblyRef table + // mscorelib entry only required by ILSpy + buffer.write(&0u16); // MajorVersion + buffer.write(&0u16); // MinorVersion + buffer.write(&0u16); // BuildNumber + buffer.write(&0u16); // RevisionNumber + buffer.write(&0u32); // Flags (none) + buffer.write(&0u32); // PublicKeyOrToken (none) + buffer.write(&strings.insert("mscorlib")); + buffer.write(&0u32); // Culture (none) + buffer.write(&0u32); // HashValue (none) + + buffer.resize(round(buffer.len(), 4), 0); + buffer + } +} + +// TODO: push into pe.rs and abstract this lib to deal only with the logical metadata +// in a layout independent way +#[repr(C)] +#[derive(Default)] +struct TableStreamHeader { + reserved1: u32, + major_version: u8, + minor_version: u8, + heap_sizes: u8, + reserved2: u8, + valid: u64, + sorted: u64, +} + +impl TableStreamHeader { + fn new() -> Self { + Self { + major_version: 2, + reserved2: 1, + heap_sizes: 0b111, // 4 byte indexes + valid: TableId::Module as u64 | TableId::AssemblyRef as u64, + ..Default::default() + } + } +} + +// TODO: just use constants +enum TableId { + Module = 1 << 0, + AssemblyRef = 1 << 0x23, +} + From bd7c771e8ca9ddd1012bfb734727fcc23841b8ac Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Mon, 21 Mar 2022 11:25:51 -0700 Subject: [PATCH 31/55] tables --- crates/libs/metagen/src/blobs.rs | 33 ++++++++++++++++++++++++++++++ crates/libs/metagen/src/lib.rs | 6 ++++-- crates/libs/metagen/src/pe.rs | 19 +++-------------- crates/libs/metagen/src/strings.rs | 8 +++----- crates/libs/metagen/src/tables.rs | 5 +---- 5 files changed, 44 insertions(+), 27 deletions(-) create mode 100644 crates/libs/metagen/src/blobs.rs diff --git a/crates/libs/metagen/src/blobs.rs b/crates/libs/metagen/src/blobs.rs new file mode 100644 index 0000000000..f0a00efde4 --- /dev/null +++ b/crates/libs/metagen/src/blobs.rs @@ -0,0 +1,33 @@ +use crate::*; + +pub(crate) struct Blobs { + set: BTreeMap, usize>, + stream: Vec, +} + +impl Blobs { + pub fn new() -> Self { + Self { set: BTreeMap::new(), stream: vec![0] } + } + + pub fn insert(&mut self, value: &[u8]) -> u32 { + let pos = self.stream.len(); + let mut insert = false; + + self.set.entry(value.to_vec()).or_insert_with(|| { + insert = true; + pos + }); + + if insert { + self.stream.extend_from_slice(value); + } + + pos as _ + } + + pub fn into_stream(mut self) -> Vec { + self.stream.resize(round(self.stream.len(), 4), 0); + self.stream + } +} diff --git a/crates/libs/metagen/src/lib.rs b/crates/libs/metagen/src/lib.rs index 3872e814c4..6f25c7b7fe 100644 --- a/crates/libs/metagen/src/lib.rs +++ b/crates/libs/metagen/src/lib.rs @@ -1,13 +1,15 @@ // https://docs.microsoft.com/en-us/windows/win32/debug/pe-format +mod blobs; mod pe; mod strings; mod tables; -use strings::*; -use tables::*; +use blobs::*; use std::collections::*; use std::mem::*; use std::slice::*; +use strings::*; +use tables::*; pub fn test() { let tables = Tables::new(); diff --git a/crates/libs/metagen/src/pe.rs b/crates/libs/metagen/src/pe.rs index f192591d15..eafa0be102 100644 --- a/crates/libs/metagen/src/pe.rs +++ b/crates/libs/metagen/src/pe.rs @@ -12,12 +12,12 @@ pub(crate) fn write(filename: &str, tables: Tables) { let metadata = MetadataHeader::new(4); let mut strings = Strings::new(); - let blobs = BTreeSet::>::new(); - + let blobs = Blobs::new(); + let mut tables = tables.into_stream(&mut strings); let mut guids = guid_stream(); let mut strings = strings.into_stream(); - let mut blobs = blob_stream(&blobs); + let mut blobs = blobs.into_stream(); type TablesHeader = StreamHeader<4>; type StringsHeader = StreamHeader<12>; @@ -283,16 +283,3 @@ fn guid_stream() -> Vec { buffer.resize(16, 0); // zero guid buffer } - -fn blob_stream(blobs: &BTreeSet>) -> Vec { - let mut buffer = Vec::new(); - buffer.push(0); // start with zero byte - - for value in blobs { - buffer.extend_from_slice(value); - } - - buffer.resize(round(buffer.len(), 4), 0); - buffer -} - diff --git a/crates/libs/metagen/src/strings.rs b/crates/libs/metagen/src/strings.rs index bde22b30d0..9d25b94eb6 100644 --- a/crates/libs/metagen/src/strings.rs +++ b/crates/libs/metagen/src/strings.rs @@ -7,10 +7,7 @@ pub(crate) struct Strings { impl Strings { pub fn new() -> Self { - Self { - set: BTreeMap::new(), - stream: vec![0], - } + Self { set: BTreeMap::new(), stream: vec![0] } } pub fn insert(&mut self, value: &str) -> u32 { @@ -30,7 +27,8 @@ impl Strings { pos as _ } - pub fn into_stream(self) -> Vec { + pub fn into_stream(mut self) -> Vec { + self.stream.resize(round(self.stream.len(), 4), 0); self.stream } } diff --git a/crates/libs/metagen/src/tables.rs b/crates/libs/metagen/src/tables.rs index 1720f6ccd3..e68f72aa4e 100644 --- a/crates/libs/metagen/src/tables.rs +++ b/crates/libs/metagen/src/tables.rs @@ -4,9 +4,7 @@ pub(crate) struct Tables {} impl Tables { pub fn new() -> Self { - Self { - - } + Self {} } pub fn into_stream(&self, strings: &mut Strings) -> Vec { @@ -73,4 +71,3 @@ enum TableId { Module = 1 << 0, AssemblyRef = 1 << 0x23, } - From 0c1417d47be671ac47149927c21071d237d9320e Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Mon, 21 Mar 2022 12:07:09 -0700 Subject: [PATCH 32/55] tables --- crates/libs/metagen/src/tables.rs | 65 ++++++++++++++++++------------- 1 file changed, 37 insertions(+), 28 deletions(-) diff --git a/crates/libs/metagen/src/tables.rs b/crates/libs/metagen/src/tables.rs index e68f72aa4e..692860578b 100644 --- a/crates/libs/metagen/src/tables.rs +++ b/crates/libs/metagen/src/tables.rs @@ -9,42 +9,24 @@ impl Tables { pub fn into_stream(&self, strings: &mut Strings) -> Vec { let mut buffer = Vec::new(); - let header = TableStreamHeader::new(); + let header = Header::new(); buffer.write(&header); // row sizes buffer.write(&1u32); // Module buffer.write(&1u32); // AssemblyRef - // Module table - buffer.write(&0u16); // Generation (reserved) - buffer.write(&0u32); // Name (none) - buffer.write(&1u32); // Mvid (zero guid) - buffer.write(&0u32); // EncId (reserved) - buffer.write(&0u32); // EncBaseId (reserved) - - // AssemblyRef table - // mscorelib entry only required by ILSpy - buffer.write(&0u16); // MajorVersion - buffer.write(&0u16); // MinorVersion - buffer.write(&0u16); // BuildNumber - buffer.write(&0u16); // RevisionNumber - buffer.write(&0u32); // Flags (none) - buffer.write(&0u32); // PublicKeyOrToken (none) - buffer.write(&strings.insert("mscorlib")); - buffer.write(&0u32); // Culture (none) - buffer.write(&0u32); // HashValue (none) + Module::write(&mut buffer); + AssemblyRef::write(&mut buffer, strings); buffer.resize(round(buffer.len(), 4), 0); buffer } } -// TODO: push into pe.rs and abstract this lib to deal only with the logical metadata -// in a layout independent way #[repr(C)] #[derive(Default)] -struct TableStreamHeader { +struct Header { reserved1: u32, major_version: u8, minor_version: u8, @@ -54,20 +36,47 @@ struct TableStreamHeader { sorted: u64, } -impl TableStreamHeader { +impl Header { fn new() -> Self { Self { major_version: 2, reserved2: 1, heap_sizes: 0b111, // 4 byte indexes - valid: TableId::Module as u64 | TableId::AssemblyRef as u64, + valid: Module::ID | AssemblyRef::ID, ..Default::default() } } } -// TODO: just use constants -enum TableId { - Module = 1 << 0, - AssemblyRef = 1 << 0x23, +struct Module; + +impl Module { + const ID: u64 = 1 << 0; + + fn write(buffer: &mut Vec) { + buffer.write(&0u16); // Generation (reserved) + buffer.write(&0u32); // Name (none) + buffer.write(&1u32); // Mvid (zero guid) + buffer.write(&0u32); // EncId (reserved) + buffer.write(&0u32); // EncBaseId (reserved) + } +} + +struct AssemblyRef; + +impl AssemblyRef { + const ID: u64 = 1 << 0x23; + + fn write(buffer: &mut Vec, strings: &mut Strings) { + // TODO: This is only required by ILSpy https://github.com/icsharpcode/ILSpy/issues/2657 + buffer.write(&0u16); // MajorVersion + buffer.write(&0u16); // MinorVersion + buffer.write(&0u16); // BuildNumber + buffer.write(&0u16); // RevisionNumber + buffer.write(&0u32); // Flags (none) + buffer.write(&0u32); // PublicKeyOrToken (none) + buffer.write(&strings.insert("mscorlib")); + buffer.write(&0u32); // Culture (none) + buffer.write(&0u32); // HashValue (none) + } } From c1d077eec515718621f334c28843e4919970f9fa Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Mon, 21 Mar 2022 12:25:33 -0700 Subject: [PATCH 33/55] TYpeDef --- crates/libs/metagen/src/tables.rs | 35 +++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/crates/libs/metagen/src/tables.rs b/crates/libs/metagen/src/tables.rs index 692860578b..0c9e69a86a 100644 --- a/crates/libs/metagen/src/tables.rs +++ b/crates/libs/metagen/src/tables.rs @@ -1,10 +1,15 @@ use crate::*; -pub(crate) struct Tables {} +pub(crate) struct Tables { + // TODO: probably need a map or tree + TypeDef: Vec, +} impl Tables { pub fn new() -> Self { - Self {} + Self { + TypeDef: vec![TypeDef { namespace: "Windows.Foundation".to_string(), name: "IStringable".to_string()}] + } } pub fn into_stream(&self, strings: &mut Strings) -> Vec { @@ -12,11 +17,15 @@ impl Tables { let header = Header::new(); buffer.write(&header); - // row sizes + // Row sizes (ordered by table ID) buffer.write(&1u32); // Module + buffer.write(&(self.TypeDef.len() as u32)); buffer.write(&1u32); // AssemblyRef Module::write(&mut buffer); + for row in &self.TypeDef { + row.write(&mut buffer, strings); + } AssemblyRef::write(&mut buffer, strings); buffer.resize(round(buffer.len(), 4), 0); @@ -42,7 +51,7 @@ impl Header { major_version: 2, reserved2: 1, heap_sizes: 0b111, // 4 byte indexes - valid: Module::ID | AssemblyRef::ID, + valid: Module::ID | TypeDef::ID | AssemblyRef::ID, ..Default::default() } } @@ -80,3 +89,21 @@ impl AssemblyRef { buffer.write(&0u32); // HashValue (none) } } + +struct TypeDef { + name: String, + namespace: String, +} + +impl TypeDef { + const ID: u64 = 1 << 0x02; + + fn write(&self, buffer: &mut Vec, strings: &mut Strings) { + buffer.write(&0u32); // Flags + buffer.write(&strings.insert(&self.name)); + buffer.write(&strings.insert(&self.namespace)); + buffer.write(&0u32); // Extends + buffer.write(&0u32); // FieldList + buffer.write(&0u32); // MethodList + } +} From 669fc6eea7902c73d4e658f7305839bb4a6db380 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Tue, 22 Mar 2022 12:12:45 -0700 Subject: [PATCH 34/55] tables --- crates/libs/metadata/src/file.rs | 2 +- crates/libs/metagen/src/strings.rs | 2 +- crates/libs/metagen/src/tables.rs | 109 ------------------ .../libs/metagen/src/tables/class_layout.rs | 11 ++ crates/libs/metagen/src/tables/constant.rs | 11 ++ .../metagen/src/tables/custom_attribute.rs | 11 ++ crates/libs/metagen/src/tables/field.rs | 11 ++ .../libs/metagen/src/tables/generic_param.rs | 12 ++ crates/libs/metagen/src/tables/impl_map.rs | 11 ++ .../libs/metagen/src/tables/interface_impl.rs | 11 ++ crates/libs/metagen/src/tables/member_ref.rs | 11 ++ crates/libs/metagen/src/tables/method_def.rs | 12 ++ crates/libs/metagen/src/tables/mod.rs | 92 +++++++++++++++ crates/libs/metagen/src/tables/module.rs | 17 +++ crates/libs/metagen/src/tables/module_ref.rs | 11 ++ .../libs/metagen/src/tables/nested_class.rs | 10 ++ crates/libs/metagen/src/tables/param.rs | 11 ++ crates/libs/metagen/src/tables/type_def.rs | 26 +++++ crates/libs/metagen/src/tables/type_ref.rs | 11 ++ crates/libs/metagen/src/tables/type_spec.rs | 11 ++ crates/tests/define/src/main.rs | 20 +++- 21 files changed, 311 insertions(+), 112 deletions(-) delete mode 100644 crates/libs/metagen/src/tables.rs create mode 100644 crates/libs/metagen/src/tables/class_layout.rs create mode 100644 crates/libs/metagen/src/tables/constant.rs create mode 100644 crates/libs/metagen/src/tables/custom_attribute.rs create mode 100644 crates/libs/metagen/src/tables/field.rs create mode 100644 crates/libs/metagen/src/tables/generic_param.rs create mode 100644 crates/libs/metagen/src/tables/impl_map.rs create mode 100644 crates/libs/metagen/src/tables/interface_impl.rs create mode 100644 crates/libs/metagen/src/tables/member_ref.rs create mode 100644 crates/libs/metagen/src/tables/method_def.rs create mode 100644 crates/libs/metagen/src/tables/mod.rs create mode 100644 crates/libs/metagen/src/tables/module.rs create mode 100644 crates/libs/metagen/src/tables/module_ref.rs create mode 100644 crates/libs/metagen/src/tables/nested_class.rs create mode 100644 crates/libs/metagen/src/tables/param.rs create mode 100644 crates/libs/metagen/src/tables/type_def.rs create mode 100644 crates/libs/metagen/src/tables/type_ref.rs create mode 100644 crates/libs/metagen/src/tables/type_spec.rs diff --git a/crates/libs/metadata/src/file.rs b/crates/libs/metadata/src/file.rs index 537a8c1f23..11b6279651 100644 --- a/crates/libs/metadata/src/file.rs +++ b/crates/libs/metadata/src/file.rs @@ -484,7 +484,7 @@ impl File { Self::from_bytes(filename.file_name().expect("Invalid .winmd path").to_string_lossy().to_string(), bytes) } - pub(crate) fn type_def_table(&self) -> &TableData { + pub fn type_def_table(&self) -> &TableData { &self.tables[TableIndex::TypeDef as usize] } diff --git a/crates/libs/metagen/src/strings.rs b/crates/libs/metagen/src/strings.rs index 9d25b94eb6..6fadb33c61 100644 --- a/crates/libs/metagen/src/strings.rs +++ b/crates/libs/metagen/src/strings.rs @@ -1,6 +1,6 @@ use crate::*; -pub(crate) struct Strings { +pub struct Strings { set: BTreeMap, stream: Vec, } diff --git a/crates/libs/metagen/src/tables.rs b/crates/libs/metagen/src/tables.rs deleted file mode 100644 index 0c9e69a86a..0000000000 --- a/crates/libs/metagen/src/tables.rs +++ /dev/null @@ -1,109 +0,0 @@ -use crate::*; - -pub(crate) struct Tables { - // TODO: probably need a map or tree - TypeDef: Vec, -} - -impl Tables { - pub fn new() -> Self { - Self { - TypeDef: vec![TypeDef { namespace: "Windows.Foundation".to_string(), name: "IStringable".to_string()}] - } - } - - pub fn into_stream(&self, strings: &mut Strings) -> Vec { - let mut buffer = Vec::new(); - let header = Header::new(); - buffer.write(&header); - - // Row sizes (ordered by table ID) - buffer.write(&1u32); // Module - buffer.write(&(self.TypeDef.len() as u32)); - buffer.write(&1u32); // AssemblyRef - - Module::write(&mut buffer); - for row in &self.TypeDef { - row.write(&mut buffer, strings); - } - AssemblyRef::write(&mut buffer, strings); - - buffer.resize(round(buffer.len(), 4), 0); - buffer - } -} - -#[repr(C)] -#[derive(Default)] -struct Header { - reserved1: u32, - major_version: u8, - minor_version: u8, - heap_sizes: u8, - reserved2: u8, - valid: u64, - sorted: u64, -} - -impl Header { - fn new() -> Self { - Self { - major_version: 2, - reserved2: 1, - heap_sizes: 0b111, // 4 byte indexes - valid: Module::ID | TypeDef::ID | AssemblyRef::ID, - ..Default::default() - } - } -} - -struct Module; - -impl Module { - const ID: u64 = 1 << 0; - - fn write(buffer: &mut Vec) { - buffer.write(&0u16); // Generation (reserved) - buffer.write(&0u32); // Name (none) - buffer.write(&1u32); // Mvid (zero guid) - buffer.write(&0u32); // EncId (reserved) - buffer.write(&0u32); // EncBaseId (reserved) - } -} - -struct AssemblyRef; - -impl AssemblyRef { - const ID: u64 = 1 << 0x23; - - fn write(buffer: &mut Vec, strings: &mut Strings) { - // TODO: This is only required by ILSpy https://github.com/icsharpcode/ILSpy/issues/2657 - buffer.write(&0u16); // MajorVersion - buffer.write(&0u16); // MinorVersion - buffer.write(&0u16); // BuildNumber - buffer.write(&0u16); // RevisionNumber - buffer.write(&0u32); // Flags (none) - buffer.write(&0u32); // PublicKeyOrToken (none) - buffer.write(&strings.insert("mscorlib")); - buffer.write(&0u32); // Culture (none) - buffer.write(&0u32); // HashValue (none) - } -} - -struct TypeDef { - name: String, - namespace: String, -} - -impl TypeDef { - const ID: u64 = 1 << 0x02; - - fn write(&self, buffer: &mut Vec, strings: &mut Strings) { - buffer.write(&0u32); // Flags - buffer.write(&strings.insert(&self.name)); - buffer.write(&strings.insert(&self.namespace)); - buffer.write(&0u32); // Extends - buffer.write(&0u32); // FieldList - buffer.write(&0u32); // MethodList - } -} diff --git a/crates/libs/metagen/src/tables/class_layout.rs b/crates/libs/metagen/src/tables/class_layout.rs new file mode 100644 index 0000000000..c3ea6e4241 --- /dev/null +++ b/crates/libs/metagen/src/tables/class_layout.rs @@ -0,0 +1,11 @@ +use super::*; + +pub struct ClassLayout { +} + +impl ClassLayout { + pub const ID: u64 = 1 << 0x0F; + + pub fn write(&self, _buffer: &mut Vec, _strings: &mut Strings) { + } +} diff --git a/crates/libs/metagen/src/tables/constant.rs b/crates/libs/metagen/src/tables/constant.rs new file mode 100644 index 0000000000..5762eebf2c --- /dev/null +++ b/crates/libs/metagen/src/tables/constant.rs @@ -0,0 +1,11 @@ +use super::*; + +pub struct Constant { +} + +impl Constant { + pub const ID: u64 = 1 << 0x0B; + + pub fn write(&self, _buffer: &mut Vec, _strings: &mut Strings) { + } +} diff --git a/crates/libs/metagen/src/tables/custom_attribute.rs b/crates/libs/metagen/src/tables/custom_attribute.rs new file mode 100644 index 0000000000..dda1d8a0b1 --- /dev/null +++ b/crates/libs/metagen/src/tables/custom_attribute.rs @@ -0,0 +1,11 @@ +use super::*; + +pub struct CustomAttribute { +} + +impl CustomAttribute { + pub const ID: u64 = 1 << 0x0C; + + pub fn write(&self, _buffer: &mut Vec, _strings: &mut Strings) { + } +} diff --git a/crates/libs/metagen/src/tables/field.rs b/crates/libs/metagen/src/tables/field.rs new file mode 100644 index 0000000000..55cf5ff244 --- /dev/null +++ b/crates/libs/metagen/src/tables/field.rs @@ -0,0 +1,11 @@ +use super::*; + +pub struct Field { +} + +impl Field{ + pub const ID: u64 = 1 << 0x04; + + pub fn write(&self, _buffer: &mut Vec, _strings: &mut Strings) { + } +} diff --git a/crates/libs/metagen/src/tables/generic_param.rs b/crates/libs/metagen/src/tables/generic_param.rs new file mode 100644 index 0000000000..2cb3453868 --- /dev/null +++ b/crates/libs/metagen/src/tables/generic_param.rs @@ -0,0 +1,12 @@ +use super::*; + +struct GenericParam{ + +} + +impl GenericParam { + pub const ID: u64 = 1 << 0x2A; + + pub fn write(&self, _buffer: &mut Vec, _strings: &mut Strings) { + } +} diff --git a/crates/libs/metagen/src/tables/impl_map.rs b/crates/libs/metagen/src/tables/impl_map.rs new file mode 100644 index 0000000000..414b43fe1e --- /dev/null +++ b/crates/libs/metagen/src/tables/impl_map.rs @@ -0,0 +1,11 @@ +use super::*; + +pub struct ImplMap { +} + +impl ImplMap { + pub const ID: u64 = 1 << 0x1C; + + pub fn write(&self, _buffer: &mut Vec, _strings: &mut Strings) { + } +} diff --git a/crates/libs/metagen/src/tables/interface_impl.rs b/crates/libs/metagen/src/tables/interface_impl.rs new file mode 100644 index 0000000000..90aaebaf97 --- /dev/null +++ b/crates/libs/metagen/src/tables/interface_impl.rs @@ -0,0 +1,11 @@ +use super::*; + +pub struct InterfaceImpl { +} + +impl InterfaceImpl { + pub const ID: u64 = 1 << 0x09; + + pub fn write(&self, _buffer: &mut Vec, _strings: &mut Strings) { + } +} diff --git a/crates/libs/metagen/src/tables/member_ref.rs b/crates/libs/metagen/src/tables/member_ref.rs new file mode 100644 index 0000000000..c8552e6d7b --- /dev/null +++ b/crates/libs/metagen/src/tables/member_ref.rs @@ -0,0 +1,11 @@ +use super::*; + +pub struct MemberRef { +} + +impl MemberRef { + pub const ID: u64 = 1 << 0x0A; + + pub fn write(&self, _buffer: &mut Vec, _strings: &mut Strings) { + } +} diff --git a/crates/libs/metagen/src/tables/method_def.rs b/crates/libs/metagen/src/tables/method_def.rs new file mode 100644 index 0000000000..acca7112e1 --- /dev/null +++ b/crates/libs/metagen/src/tables/method_def.rs @@ -0,0 +1,12 @@ +use super::*; + +struct MethodDef { +} + +impl MethodDef { + pub const ID: u64 = 1 << 0x06; + + pub fn write(&self, _buffer: &mut Vec, _strings: &mut Strings) { + todo!() + } +} diff --git a/crates/libs/metagen/src/tables/mod.rs b/crates/libs/metagen/src/tables/mod.rs new file mode 100644 index 0000000000..a1fef4d6a9 --- /dev/null +++ b/crates/libs/metagen/src/tables/mod.rs @@ -0,0 +1,92 @@ +pub use super::*; + +mod custom_attribute; +mod class_layout; +mod constant; +mod field; +mod generic_param; +mod impl_map; +mod interface_impl; +mod member_ref; +mod method_def; +mod module_ref; +mod nested_class; +mod param; +mod type_def; +mod type_ref; +mod type_spec; +mod module; + +pub use module::*; +pub use custom_attribute::*; +pub use class_layout::*; +pub use constant::*; +pub use field::*; +pub use generic_param::*; +pub use impl_map::*; +pub use interface_impl::*; +pub use member_ref::*; +pub use method_def::*; +pub use module_ref::*; +pub use nested_class::*; +pub use param::*; +pub use type_def::*; +pub use type_ref::*; +pub use type_spec::*; + +pub(crate) struct Tables { + // TODO: probably need a map or tree + TypeDef: Vec, +} + +impl Tables { + pub fn new() -> Self { + Self { + TypeDef: vec![TypeDef::new("IStringable", "Windows.Foundation")] + } + } + + pub fn into_stream(&self, _strings: &mut Strings) -> Vec { + let mut buffer = Vec::new(); + let header = Header::new(); + buffer.write(&header); + + // Row sizes (ordered by table ID) + buffer.write(&1u32); // Module + buffer.write(&(self.TypeDef.len() as u32)); + + Module::write(&mut buffer); + // for row in &self.TypeDef { + // row.write(&mut buffer, strings); + // } + + buffer.resize(round(buffer.len(), 4), 0); + buffer + } +} + +#[repr(C)] +#[derive(Default)] +struct Header { + reserved1: u32, + major_version: u8, + minor_version: u8, + heap_sizes: u8, + reserved2: u8, + valid: u64, + sorted: u64, +} + +impl Header { + fn new() -> Self { + Self { + major_version: 2, + reserved2: 1, + heap_sizes: 0b111, // 4 byte indexes + valid: Module::ID, + // TODO: mark sorted tables? + ..Default::default() + } + } +} + diff --git a/crates/libs/metagen/src/tables/module.rs b/crates/libs/metagen/src/tables/module.rs new file mode 100644 index 0000000000..07ab329164 --- /dev/null +++ b/crates/libs/metagen/src/tables/module.rs @@ -0,0 +1,17 @@ +use super::*; + +pub struct Module; + +impl Module { + pub const ID: u64 = 1 << 0; + + pub fn write(buffer: &mut Vec) { + buffer.write(&0u16); // Generation (reserved) + buffer.write(&0u32); // Name (none) + buffer.write(&1u32); // Mvid (zero guid) + buffer.write(&0u32); // EncId (reserved) + buffer.write(&0u32); // EncBaseId (reserved) + } +} + + diff --git a/crates/libs/metagen/src/tables/module_ref.rs b/crates/libs/metagen/src/tables/module_ref.rs new file mode 100644 index 0000000000..c3eca15c2b --- /dev/null +++ b/crates/libs/metagen/src/tables/module_ref.rs @@ -0,0 +1,11 @@ +use super::*; + +pub struct ModuleRef { +} + +impl ModuleRef { + pub const ID: u64 = 1 << 0x1A; + + pub fn write(&self, _buffer: &mut Vec, _strings: &mut Strings) { + } +} diff --git a/crates/libs/metagen/src/tables/nested_class.rs b/crates/libs/metagen/src/tables/nested_class.rs new file mode 100644 index 0000000000..4b52c2da66 --- /dev/null +++ b/crates/libs/metagen/src/tables/nested_class.rs @@ -0,0 +1,10 @@ +use super::*; + +struct NestedClass; + +impl NestedClass { + pub const ID: u64 = 1 << 0x29; + + pub fn write(&self, _buffer: &mut Vec, _strings: &mut Strings) { + } +} diff --git a/crates/libs/metagen/src/tables/param.rs b/crates/libs/metagen/src/tables/param.rs new file mode 100644 index 0000000000..f550feff47 --- /dev/null +++ b/crates/libs/metagen/src/tables/param.rs @@ -0,0 +1,11 @@ +use super::*; + +pub struct Param { +} + +impl Param { + pub const ID: u64 = 1 << 0x08; + + pub fn write(&self, _buffer: &mut Vec, _strings: &mut Strings) { + } +} diff --git a/crates/libs/metagen/src/tables/type_def.rs b/crates/libs/metagen/src/tables/type_def.rs new file mode 100644 index 0000000000..ad66e88f17 --- /dev/null +++ b/crates/libs/metagen/src/tables/type_def.rs @@ -0,0 +1,26 @@ +use super::*; + +pub struct TypeDef { + name: String, + namespace: String, +} + +impl TypeDef { + pub const ID: u64 = 1 << 0x02; + + pub fn new(name: &str, namespace: &str) -> Self { + Self { + name: name.to_string(), + namespace: namespace.to_string(), + } + } + + pub fn write(&self, buffer: &mut Vec, strings: &mut Strings) { + buffer.write(&0u32); // Flags + buffer.write(&strings.insert(&self.name)); + buffer.write(&strings.insert(&self.namespace)); + buffer.write(&0u32); // Extends // TODO: use composite_index_size to work out size of TypeDefOrRef + buffer.write(&1u32); // FieldList // TODO: use Field->TableData::index_size to work this out + buffer.write(&1u32); // MethodList // TODO: use MethodDef->TableData::index_size to work this out + } +} diff --git a/crates/libs/metagen/src/tables/type_ref.rs b/crates/libs/metagen/src/tables/type_ref.rs new file mode 100644 index 0000000000..e5493beedf --- /dev/null +++ b/crates/libs/metagen/src/tables/type_ref.rs @@ -0,0 +1,11 @@ +use super::*; + +pub struct TypeRef { +} + +impl TypeRef { + pub const ID: u64 = 1 << 0x01; + + pub fn write(&self, _buffer: &mut Vec, _strings: &mut Strings) { + } +} diff --git a/crates/libs/metagen/src/tables/type_spec.rs b/crates/libs/metagen/src/tables/type_spec.rs new file mode 100644 index 0000000000..d64982e174 --- /dev/null +++ b/crates/libs/metagen/src/tables/type_spec.rs @@ -0,0 +1,11 @@ +use super::*; + +pub struct TypeSpec { +} + +impl TypeSpec { + pub const ID: u64 = 1 << 0x1B; + + pub fn write(&self, _buffer: &mut Vec, _strings: &mut Strings) { + } +} diff --git a/crates/tests/define/src/main.rs b/crates/tests/define/src/main.rs index 3f0a00587a..508443b1f0 100644 --- a/crates/tests/define/src/main.rs +++ b/crates/tests/define/src/main.rs @@ -1,5 +1,23 @@ +use windows_metadata::*; + fn main() { windows_metagen::test(); - windows_metadata::File::new("/git/test.winmd"); + let file = windows_metadata::File::new("/git/test.winmd"); + let row_count = file.type_def_table().row_count; + for row in 0..row_count { + let def: TypeDef = Row::new(row, TableIndex::TypeDef, unsafe { &*(&file as *const _) }).into(); + let type_name = def.type_name(); + println!("{}", type_name); + for field in def.fields() { + let name = field.name(); + println!("field: {}", name); + } + + for method in def.methods() { + let name = method.name(); + println!("field: {}", name); + } + } + //windows_metadata::File::new(r#"D:\git\windows-rs\crates\libs\metadata\default\windows.winmd"#); } From d2e1382610de1d5c41037d41902156a983c8c0ba Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Tue, 22 Mar 2022 15:05:17 -0700 Subject: [PATCH 35/55] derive --- crates/libs/metagen/Cargo.toml | 2 +- crates/libs/metagen/src/lib.rs | 3 +- .../libs/metagen/src/tables/class_layout.rs | 1 + crates/libs/metagen/src/tables/constant.rs | 1 + .../metagen/src/tables/custom_attribute.rs | 1 + crates/libs/metagen/src/tables/field.rs | 1 + .../libs/metagen/src/tables/generic_param.rs | 1 + crates/libs/metagen/src/tables/impl_map.rs | 1 + .../libs/metagen/src/tables/interface_impl.rs | 1 + crates/libs/metagen/src/tables/member_ref.rs | 1 + crates/libs/metagen/src/tables/method_def.rs | 1 + crates/libs/metagen/src/tables/mod.rs | 92 ++++++++++++++++--- crates/libs/metagen/src/tables/module.rs | 1 + crates/libs/metagen/src/tables/module_ref.rs | 1 + .../libs/metagen/src/tables/nested_class.rs | 5 +- crates/libs/metagen/src/tables/param.rs | 1 + crates/libs/metagen/src/tables/type_def.rs | 5 +- crates/libs/metagen/src/tables/type_ref.rs | 1 + crates/libs/metagen/src/tables/type_spec.rs | 1 + 19 files changed, 105 insertions(+), 16 deletions(-) diff --git a/crates/libs/metagen/Cargo.toml b/crates/libs/metagen/Cargo.toml index 9d1be536a7..d0835c8bf1 100644 --- a/crates/libs/metagen/Cargo.toml +++ b/crates/libs/metagen/Cargo.toml @@ -2,7 +2,7 @@ name = "windows-metagen" version = "0.34.0" authors = ["Microsoft"] -edition = "2018" +edition = "2021" license = "MIT OR Apache-2.0" description = "Metadata generation support for the windows crate" repository = "https://github.com/microsoft/windows-rs" diff --git a/crates/libs/metagen/src/lib.rs b/crates/libs/metagen/src/lib.rs index 6f25c7b7fe..f8b24da5ec 100644 --- a/crates/libs/metagen/src/lib.rs +++ b/crates/libs/metagen/src/lib.rs @@ -12,7 +12,8 @@ use strings::*; use tables::*; pub fn test() { - let tables = Tables::new(); + let mut tables = Tables::new(); + tables.add_type_def(TypeDef::new("Hello", "World")); pe::write("/git/test.winmd", tables); } diff --git a/crates/libs/metagen/src/tables/class_layout.rs b/crates/libs/metagen/src/tables/class_layout.rs index c3ea6e4241..84cd1f62b3 100644 --- a/crates/libs/metagen/src/tables/class_layout.rs +++ b/crates/libs/metagen/src/tables/class_layout.rs @@ -1,5 +1,6 @@ use super::*; +#[derive(Default)] pub struct ClassLayout { } diff --git a/crates/libs/metagen/src/tables/constant.rs b/crates/libs/metagen/src/tables/constant.rs index 5762eebf2c..82be6b0994 100644 --- a/crates/libs/metagen/src/tables/constant.rs +++ b/crates/libs/metagen/src/tables/constant.rs @@ -1,5 +1,6 @@ use super::*; +#[derive(Default)] pub struct Constant { } diff --git a/crates/libs/metagen/src/tables/custom_attribute.rs b/crates/libs/metagen/src/tables/custom_attribute.rs index dda1d8a0b1..9dcfaad2ef 100644 --- a/crates/libs/metagen/src/tables/custom_attribute.rs +++ b/crates/libs/metagen/src/tables/custom_attribute.rs @@ -1,5 +1,6 @@ use super::*; +#[derive(Default)] pub struct CustomAttribute { } diff --git a/crates/libs/metagen/src/tables/field.rs b/crates/libs/metagen/src/tables/field.rs index 55cf5ff244..6922e867c7 100644 --- a/crates/libs/metagen/src/tables/field.rs +++ b/crates/libs/metagen/src/tables/field.rs @@ -1,5 +1,6 @@ use super::*; +#[derive(Default)] pub struct Field { } diff --git a/crates/libs/metagen/src/tables/generic_param.rs b/crates/libs/metagen/src/tables/generic_param.rs index 2cb3453868..af5085f961 100644 --- a/crates/libs/metagen/src/tables/generic_param.rs +++ b/crates/libs/metagen/src/tables/generic_param.rs @@ -1,5 +1,6 @@ use super::*; +#[derive(Default)] struct GenericParam{ } diff --git a/crates/libs/metagen/src/tables/impl_map.rs b/crates/libs/metagen/src/tables/impl_map.rs index 414b43fe1e..5e14f6894b 100644 --- a/crates/libs/metagen/src/tables/impl_map.rs +++ b/crates/libs/metagen/src/tables/impl_map.rs @@ -1,5 +1,6 @@ use super::*; +#[derive(Default)] pub struct ImplMap { } diff --git a/crates/libs/metagen/src/tables/interface_impl.rs b/crates/libs/metagen/src/tables/interface_impl.rs index 90aaebaf97..506f37b956 100644 --- a/crates/libs/metagen/src/tables/interface_impl.rs +++ b/crates/libs/metagen/src/tables/interface_impl.rs @@ -1,5 +1,6 @@ use super::*; +#[derive(Default)] pub struct InterfaceImpl { } diff --git a/crates/libs/metagen/src/tables/member_ref.rs b/crates/libs/metagen/src/tables/member_ref.rs index c8552e6d7b..c98dbaba4a 100644 --- a/crates/libs/metagen/src/tables/member_ref.rs +++ b/crates/libs/metagen/src/tables/member_ref.rs @@ -1,5 +1,6 @@ use super::*; +#[derive(Default)] pub struct MemberRef { } diff --git a/crates/libs/metagen/src/tables/method_def.rs b/crates/libs/metagen/src/tables/method_def.rs index acca7112e1..90b68892f4 100644 --- a/crates/libs/metagen/src/tables/method_def.rs +++ b/crates/libs/metagen/src/tables/method_def.rs @@ -1,5 +1,6 @@ use super::*; +#[derive(Default)] struct MethodDef { } diff --git a/crates/libs/metagen/src/tables/mod.rs b/crates/libs/metagen/src/tables/mod.rs index a1fef4d6a9..db44b4df1a 100644 --- a/crates/libs/metagen/src/tables/mod.rs +++ b/crates/libs/metagen/src/tables/mod.rs @@ -34,31 +34,44 @@ pub use type_def::*; pub use type_ref::*; pub use type_spec::*; +#[derive(Default)] pub(crate) struct Tables { - // TODO: probably need a map or tree - TypeDef: Vec, + type_ref: Vec, + type_def: Vec, + type_spec: Vec, } impl Tables { pub fn new() -> Self { - Self { - TypeDef: vec![TypeDef::new("IStringable", "Windows.Foundation")] - } + Self::default() } - pub fn into_stream(&self, _strings: &mut Strings) -> Vec { + pub fn add_type_def(&mut self, type_def: TypeDef) { + self.type_def.push(type_def); + } + + pub fn into_stream(&self, strings: &mut Strings) -> Vec { let mut buffer = Vec::new(); let header = Header::new(); buffer.write(&header); // Row sizes (ordered by table ID) buffer.write(&1u32); // Module - buffer.write(&(self.TypeDef.len() as u32)); + buffer.write(&(self.type_ref.len() as u32)); + buffer.write(&(self.type_def.len() as u32)); + buffer.write(&(self.type_spec.len() as u32)); Module::write(&mut buffer); - // for row in &self.TypeDef { - // row.write(&mut buffer, strings); - // } + self.type_ref.iter().for_each(|row|row.write(&mut buffer, strings)); + for type_def in &self.type_def { + buffer.write(&0u32); // Flags + buffer.write(&strings.insert(&type_def.name)); + buffer.write(&strings.insert(&type_def.namespace)); + buffer.write(&0u16); // Extends // TODO: use composite_index_size to work out size of TypeDefOrRef + buffer.write(&1u16); // FieldList // TODO: use Field->TableData::index_size to work this out + buffer.write(&1u16); // MethodList // TODO: use MethodDef->TableData::index_size to work this out + } + self.type_spec.iter().for_each(|row|row.write(&mut buffer, strings)); buffer.resize(round(buffer.len(), 4), 0); buffer @@ -83,10 +96,67 @@ impl Header { major_version: 2, reserved2: 1, heap_sizes: 0b111, // 4 byte indexes - valid: Module::ID, + valid: Module::ID | TypeRef::ID | TypeDef::ID | TypeSpec::ID, // TODO: mark sorted tables? ..Default::default() } } } +fn index_size(len: usize) -> u32 { + if len < (1 << 16) { + 2 + } else { + 4 + } +} + +enum Index { + U16(u16), + U32(u32) +} + +impl Index{ + fn index(index: usize, len: usize) -> Self { + if len < (1 << 16) { + Self::U16(index as _) + } else { + Self::U32(index as _) + } + } + + fn write(&self, buffer: &mut Vec) { + match self { + Self::U16(index) => buffer.write(&index), + Self::U32(index) => buffer.write(&index), + } + } +} + +// TODO: use CodedIndex enum? +fn coded_index_size(tables: &[usize]) -> u32 { + fn small(row_count: usize, bits: u8) -> bool { + (row_count as u64) < (1u64 << (16 - bits)) + } + + fn bits_needed(value: usize) -> u8 { + let mut value = value - 1; + let mut bits: u8 = 1; + loop { + value >>= 1; + if value == 0 { + break; + } + bits += 1; + } + bits + } + + let bits_needed = bits_needed(tables.len()); + + if tables.iter().all(|len| small(*len, bits_needed)) { + 2 + } else { + 4 + } +} diff --git a/crates/libs/metagen/src/tables/module.rs b/crates/libs/metagen/src/tables/module.rs index 07ab329164..4665c17ede 100644 --- a/crates/libs/metagen/src/tables/module.rs +++ b/crates/libs/metagen/src/tables/module.rs @@ -1,5 +1,6 @@ use super::*; +#[derive(Default)] pub struct Module; impl Module { diff --git a/crates/libs/metagen/src/tables/module_ref.rs b/crates/libs/metagen/src/tables/module_ref.rs index c3eca15c2b..97bdddfc0a 100644 --- a/crates/libs/metagen/src/tables/module_ref.rs +++ b/crates/libs/metagen/src/tables/module_ref.rs @@ -1,5 +1,6 @@ use super::*; +#[derive(Default)] pub struct ModuleRef { } diff --git a/crates/libs/metagen/src/tables/nested_class.rs b/crates/libs/metagen/src/tables/nested_class.rs index 4b52c2da66..2a75da84fd 100644 --- a/crates/libs/metagen/src/tables/nested_class.rs +++ b/crates/libs/metagen/src/tables/nested_class.rs @@ -1,6 +1,9 @@ use super::*; -struct NestedClass; +#[derive(Default)] +struct NestedClass{ + +} impl NestedClass { pub const ID: u64 = 1 << 0x29; diff --git a/crates/libs/metagen/src/tables/param.rs b/crates/libs/metagen/src/tables/param.rs index f550feff47..25cf28a5d0 100644 --- a/crates/libs/metagen/src/tables/param.rs +++ b/crates/libs/metagen/src/tables/param.rs @@ -1,5 +1,6 @@ use super::*; +#[derive(Default)] pub struct Param { } diff --git a/crates/libs/metagen/src/tables/type_def.rs b/crates/libs/metagen/src/tables/type_def.rs index ad66e88f17..45f749ca78 100644 --- a/crates/libs/metagen/src/tables/type_def.rs +++ b/crates/libs/metagen/src/tables/type_def.rs @@ -1,8 +1,9 @@ use super::*; +#[derive(Default)] pub struct TypeDef { - name: String, - namespace: String, + pub name: String, + pub namespace: String, } impl TypeDef { diff --git a/crates/libs/metagen/src/tables/type_ref.rs b/crates/libs/metagen/src/tables/type_ref.rs index e5493beedf..36bcc6380d 100644 --- a/crates/libs/metagen/src/tables/type_ref.rs +++ b/crates/libs/metagen/src/tables/type_ref.rs @@ -1,5 +1,6 @@ use super::*; +#[derive(Default)] pub struct TypeRef { } diff --git a/crates/libs/metagen/src/tables/type_spec.rs b/crates/libs/metagen/src/tables/type_spec.rs index d64982e174..a2976cccc4 100644 --- a/crates/libs/metagen/src/tables/type_spec.rs +++ b/crates/libs/metagen/src/tables/type_spec.rs @@ -1,5 +1,6 @@ use super::*; +#[derive(Default)] pub struct TypeSpec { } From 26ceb9f2699fae64b1ad459753b0eb16564deb6b Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Tue, 22 Mar 2022 16:14:22 -0700 Subject: [PATCH 36/55] strings --- crates/libs/metagen/src/lib.rs | 3 ++- crates/libs/metagen/src/strings.rs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/libs/metagen/src/lib.rs b/crates/libs/metagen/src/lib.rs index f8b24da5ec..d323c937e9 100644 --- a/crates/libs/metagen/src/lib.rs +++ b/crates/libs/metagen/src/lib.rs @@ -13,7 +13,8 @@ use tables::*; pub fn test() { let mut tables = Tables::new(); - tables.add_type_def(TypeDef::new("Hello", "World")); + tables.add_type_def(TypeDef::new("IStringable", "Windows.Foundation")); + tables.add_type_def(TypeDef::new("IClosable", "Windows.Foundation")); pe::write("/git/test.winmd", tables); } diff --git a/crates/libs/metagen/src/strings.rs b/crates/libs/metagen/src/strings.rs index 6fadb33c61..4b1c5bfb83 100644 --- a/crates/libs/metagen/src/strings.rs +++ b/crates/libs/metagen/src/strings.rs @@ -14,7 +14,7 @@ impl Strings { let pos = self.stream.len(); let mut insert = false; - self.set.entry(value.to_string()).or_insert_with(|| { + let pos = *self.set.entry(value.to_string()).or_insert_with(|| { insert = true; pos }); From 54f5aef83cd2341dfa87a57bedcfbca139a623bd Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Wed, 23 Mar 2022 15:23:57 -0700 Subject: [PATCH 37/55] tables --- crates/libs/metagen/src/lib.rs | 6 +- .../libs/metagen/src/tables/class_layout.rs | 10 +-- crates/libs/metagen/src/tables/constant.rs | 10 +-- .../metagen/src/tables/custom_attribute.rs | 10 +-- crates/libs/metagen/src/tables/field.rs | 10 +-- .../libs/metagen/src/tables/generic_param.rs | 11 +-- crates/libs/metagen/src/tables/impl_map.rs | 10 +-- .../libs/metagen/src/tables/interface_impl.rs | 10 +-- crates/libs/metagen/src/tables/member_ref.rs | 10 +-- crates/libs/metagen/src/tables/method_def.rs | 11 +-- crates/libs/metagen/src/tables/mod.rs | 89 ++++++++++++++----- crates/libs/metagen/src/tables/module.rs | 18 ++-- crates/libs/metagen/src/tables/module_ref.rs | 10 +-- .../libs/metagen/src/tables/nested_class.rs | 11 +-- crates/libs/metagen/src/tables/param.rs | 10 +-- crates/libs/metagen/src/tables/type_def.rs | 16 +--- crates/libs/metagen/src/tables/type_ref.rs | 10 +-- crates/libs/metagen/src/tables/type_spec.rs | 10 +-- 18 files changed, 95 insertions(+), 177 deletions(-) diff --git a/crates/libs/metagen/src/lib.rs b/crates/libs/metagen/src/lib.rs index d323c937e9..0b697b811e 100644 --- a/crates/libs/metagen/src/lib.rs +++ b/crates/libs/metagen/src/lib.rs @@ -13,8 +13,10 @@ use tables::*; pub fn test() { let mut tables = Tables::new(); - tables.add_type_def(TypeDef::new("IStringable", "Windows.Foundation")); - tables.add_type_def(TypeDef::new("IClosable", "Windows.Foundation")); + tables.module.push(Module::new("test.winmd")); + // tables.add_type_def(TypeDef::new("IFirst", "Windows.Foundation")); + // tables.add_type_def(TypeDef::new("ISecond", "Windows.Foundation")); + // tables.add_type_def(TypeDef::new("IThird", "Windows.Foundation")); pe::write("/git/test.winmd", tables); } diff --git a/crates/libs/metagen/src/tables/class_layout.rs b/crates/libs/metagen/src/tables/class_layout.rs index 84cd1f62b3..914fbb76d1 100644 --- a/crates/libs/metagen/src/tables/class_layout.rs +++ b/crates/libs/metagen/src/tables/class_layout.rs @@ -1,12 +1,4 @@ use super::*; #[derive(Default)] -pub struct ClassLayout { -} - -impl ClassLayout { - pub const ID: u64 = 1 << 0x0F; - - pub fn write(&self, _buffer: &mut Vec, _strings: &mut Strings) { - } -} +pub struct ClassLayout {} diff --git a/crates/libs/metagen/src/tables/constant.rs b/crates/libs/metagen/src/tables/constant.rs index 82be6b0994..71142703af 100644 --- a/crates/libs/metagen/src/tables/constant.rs +++ b/crates/libs/metagen/src/tables/constant.rs @@ -1,12 +1,4 @@ use super::*; #[derive(Default)] -pub struct Constant { -} - -impl Constant { - pub const ID: u64 = 1 << 0x0B; - - pub fn write(&self, _buffer: &mut Vec, _strings: &mut Strings) { - } -} +pub struct Constant {} diff --git a/crates/libs/metagen/src/tables/custom_attribute.rs b/crates/libs/metagen/src/tables/custom_attribute.rs index 9dcfaad2ef..a920204058 100644 --- a/crates/libs/metagen/src/tables/custom_attribute.rs +++ b/crates/libs/metagen/src/tables/custom_attribute.rs @@ -1,12 +1,4 @@ use super::*; #[derive(Default)] -pub struct CustomAttribute { -} - -impl CustomAttribute { - pub const ID: u64 = 1 << 0x0C; - - pub fn write(&self, _buffer: &mut Vec, _strings: &mut Strings) { - } -} +pub struct CustomAttribute {} diff --git a/crates/libs/metagen/src/tables/field.rs b/crates/libs/metagen/src/tables/field.rs index 6922e867c7..63ee6e7a53 100644 --- a/crates/libs/metagen/src/tables/field.rs +++ b/crates/libs/metagen/src/tables/field.rs @@ -1,12 +1,4 @@ use super::*; #[derive(Default)] -pub struct Field { -} - -impl Field{ - pub const ID: u64 = 1 << 0x04; - - pub fn write(&self, _buffer: &mut Vec, _strings: &mut Strings) { - } -} +pub struct Field {} diff --git a/crates/libs/metagen/src/tables/generic_param.rs b/crates/libs/metagen/src/tables/generic_param.rs index af5085f961..86ed9c0cfe 100644 --- a/crates/libs/metagen/src/tables/generic_param.rs +++ b/crates/libs/metagen/src/tables/generic_param.rs @@ -1,13 +1,4 @@ use super::*; #[derive(Default)] -struct GenericParam{ - -} - -impl GenericParam { - pub const ID: u64 = 1 << 0x2A; - - pub fn write(&self, _buffer: &mut Vec, _strings: &mut Strings) { - } -} +pub struct GenericParam {} diff --git a/crates/libs/metagen/src/tables/impl_map.rs b/crates/libs/metagen/src/tables/impl_map.rs index 5e14f6894b..e4653365c4 100644 --- a/crates/libs/metagen/src/tables/impl_map.rs +++ b/crates/libs/metagen/src/tables/impl_map.rs @@ -1,12 +1,4 @@ use super::*; #[derive(Default)] -pub struct ImplMap { -} - -impl ImplMap { - pub const ID: u64 = 1 << 0x1C; - - pub fn write(&self, _buffer: &mut Vec, _strings: &mut Strings) { - } -} +pub struct ImplMap {} diff --git a/crates/libs/metagen/src/tables/interface_impl.rs b/crates/libs/metagen/src/tables/interface_impl.rs index 506f37b956..7fb7cb33c3 100644 --- a/crates/libs/metagen/src/tables/interface_impl.rs +++ b/crates/libs/metagen/src/tables/interface_impl.rs @@ -1,12 +1,4 @@ use super::*; #[derive(Default)] -pub struct InterfaceImpl { -} - -impl InterfaceImpl { - pub const ID: u64 = 1 << 0x09; - - pub fn write(&self, _buffer: &mut Vec, _strings: &mut Strings) { - } -} +pub struct InterfaceImpl {} diff --git a/crates/libs/metagen/src/tables/member_ref.rs b/crates/libs/metagen/src/tables/member_ref.rs index c98dbaba4a..7cfd12c424 100644 --- a/crates/libs/metagen/src/tables/member_ref.rs +++ b/crates/libs/metagen/src/tables/member_ref.rs @@ -1,12 +1,4 @@ use super::*; #[derive(Default)] -pub struct MemberRef { -} - -impl MemberRef { - pub const ID: u64 = 1 << 0x0A; - - pub fn write(&self, _buffer: &mut Vec, _strings: &mut Strings) { - } -} +pub struct MemberRef {} diff --git a/crates/libs/metagen/src/tables/method_def.rs b/crates/libs/metagen/src/tables/method_def.rs index 90b68892f4..6e66511f46 100644 --- a/crates/libs/metagen/src/tables/method_def.rs +++ b/crates/libs/metagen/src/tables/method_def.rs @@ -1,13 +1,4 @@ use super::*; #[derive(Default)] -struct MethodDef { -} - -impl MethodDef { - pub const ID: u64 = 1 << 0x06; - - pub fn write(&self, _buffer: &mut Vec, _strings: &mut Strings) { - todo!() - } -} +pub struct MethodDef {} diff --git a/crates/libs/metagen/src/tables/mod.rs b/crates/libs/metagen/src/tables/mod.rs index db44b4df1a..5c718764fb 100644 --- a/crates/libs/metagen/src/tables/mod.rs +++ b/crates/libs/metagen/src/tables/mod.rs @@ -1,32 +1,32 @@ pub use super::*; -mod custom_attribute; mod class_layout; mod constant; +mod custom_attribute; mod field; mod generic_param; mod impl_map; mod interface_impl; mod member_ref; mod method_def; +mod module; mod module_ref; mod nested_class; mod param; mod type_def; mod type_ref; mod type_spec; -mod module; -pub use module::*; -pub use custom_attribute::*; pub use class_layout::*; pub use constant::*; +pub use custom_attribute::*; pub use field::*; pub use generic_param::*; pub use impl_map::*; pub use interface_impl::*; pub use member_ref::*; pub use method_def::*; +pub use module::*; pub use module_ref::*; pub use nested_class::*; pub use param::*; @@ -35,10 +35,23 @@ pub use type_ref::*; pub use type_spec::*; #[derive(Default)] -pub(crate) struct Tables { - type_ref: Vec, - type_def: Vec, - type_spec: Vec, +pub struct Tables { + pub module: Vec, + pub type_ref: Vec, + pub type_def: Vec, + pub field: Vec, + pub method_def: Vec, + pub param: Vec, + pub interface_impl: Vec, + pub member_ref: Vec, + pub constant: Vec, + pub custom_attribute: Vec, + pub class_layout: Vec, + pub module_ref: Vec, + pub type_spec: Vec, + pub impl_map: Vec, + pub nested_class:Vec, + pub generic_param:Vec, } impl Tables { @@ -46,32 +59,53 @@ impl Tables { Self::default() } - pub fn add_type_def(&mut self, type_def: TypeDef) { - self.type_def.push(type_def); - } - pub fn into_stream(&self, strings: &mut Strings) -> Vec { let mut buffer = Vec::new(); let header = Header::new(); buffer.write(&header); // Row sizes (ordered by table ID) - buffer.write(&1u32); // Module + buffer.write(&(self.module.len() as u32)); buffer.write(&(self.type_ref.len() as u32)); buffer.write(&(self.type_def.len() as u32)); + buffer.write(&(self.field.len() as u32)); + buffer.write(&(self.method_def.len() as u32)); + buffer.write(&(self.param.len() as u32)); + buffer.write(&(self.interface_impl.len() as u32)); + buffer.write(&(self.member_ref.len() as u32)); + buffer.write(&(self.constant.len() as u32)); + buffer.write(&(self.custom_attribute.len() as u32)); + buffer.write(&(self.class_layout.len() as u32)); + buffer.write(&(self.module_ref.len() as u32)); buffer.write(&(self.type_spec.len() as u32)); + buffer.write(&(self.impl_map.len() as u32)); + buffer.write(&(self.nested_class.len() as u32)); + buffer.write(&(self.generic_param.len() as u32)); + + for module in &self.module { + buffer.write(&0u16); // Generation (reserved) + buffer.write(&strings.insert(&module.name)); + buffer.write(&1u32); // Mvid (zero guid) + buffer.write(&0u32); // EncId (reserved) + buffer.write(&0u32); // EncBaseId (reserved) + } + + // ILDASM needs to be present and the first TypeDef row. + buffer.write(&0u32); + buffer.write(&strings.insert("")); + buffer.write(&0u32); + buffer.write(&0u16); + buffer.write(&1u16); + buffer.write(&1u16); - Module::write(&mut buffer); - self.type_ref.iter().for_each(|row|row.write(&mut buffer, strings)); for type_def in &self.type_def { - buffer.write(&0u32); // Flags + buffer.write(&0x40A1u32); // Flags buffer.write(&strings.insert(&type_def.name)); buffer.write(&strings.insert(&type_def.namespace)); buffer.write(&0u16); // Extends // TODO: use composite_index_size to work out size of TypeDefOrRef buffer.write(&1u16); // FieldList // TODO: use Field->TableData::index_size to work this out buffer.write(&1u16); // MethodList // TODO: use MethodDef->TableData::index_size to work this out } - self.type_spec.iter().for_each(|row|row.write(&mut buffer, strings)); buffer.resize(round(buffer.len(), 4), 0); buffer @@ -96,7 +130,22 @@ impl Header { major_version: 2, reserved2: 1, heap_sizes: 0b111, // 4 byte indexes - valid: Module::ID | TypeRef::ID | TypeDef::ID | TypeSpec::ID, + valid: 1 << 0 | // Module + 1 << 0x01 | // TypeRef + 1 << 0x02 | // TypeDef + 1 << 0x04 | // Field + 1 << 0x06 | // MethodDef + 1 << 0x08 | // Param + 1 << 0x09 | // InterfaceImpl + 1 << 0x0A | // MemberRef + 1 << 0x0B | // Constant + 1 << 0x0C | // CustomAttribute + 1 << 0x0F | // ClassLayout + 1 << 0x1A | // ModuleRef + 1 << 0x1B | // TypeSpec, + 1 << 0x1C | // ImplMap + 1 << 0x29 | // NestedClass + 1 << 0x2A, // GenericParam // TODO: mark sorted tables? ..Default::default() } @@ -113,10 +162,10 @@ fn index_size(len: usize) -> u32 { enum Index { U16(u16), - U32(u32) + U32(u32), } -impl Index{ +impl Index { fn index(index: usize, len: usize) -> Self { if len < (1 << 16) { Self::U16(index as _) diff --git a/crates/libs/metagen/src/tables/module.rs b/crates/libs/metagen/src/tables/module.rs index 4665c17ede..ad8e35a091 100644 --- a/crates/libs/metagen/src/tables/module.rs +++ b/crates/libs/metagen/src/tables/module.rs @@ -1,18 +1,14 @@ use super::*; #[derive(Default)] -pub struct Module; +pub struct Module { + pub name: String, +} impl Module { - pub const ID: u64 = 1 << 0; - - pub fn write(buffer: &mut Vec) { - buffer.write(&0u16); // Generation (reserved) - buffer.write(&0u32); // Name (none) - buffer.write(&1u32); // Mvid (zero guid) - buffer.write(&0u32); // EncId (reserved) - buffer.write(&0u32); // EncBaseId (reserved) + pub fn new(name: &str) -> Self { + Self { + name: name.to_string(), + } } } - - diff --git a/crates/libs/metagen/src/tables/module_ref.rs b/crates/libs/metagen/src/tables/module_ref.rs index 97bdddfc0a..9388670ecf 100644 --- a/crates/libs/metagen/src/tables/module_ref.rs +++ b/crates/libs/metagen/src/tables/module_ref.rs @@ -1,12 +1,4 @@ use super::*; #[derive(Default)] -pub struct ModuleRef { -} - -impl ModuleRef { - pub const ID: u64 = 1 << 0x1A; - - pub fn write(&self, _buffer: &mut Vec, _strings: &mut Strings) { - } -} +pub struct ModuleRef {} diff --git a/crates/libs/metagen/src/tables/nested_class.rs b/crates/libs/metagen/src/tables/nested_class.rs index 2a75da84fd..50736ed37c 100644 --- a/crates/libs/metagen/src/tables/nested_class.rs +++ b/crates/libs/metagen/src/tables/nested_class.rs @@ -1,13 +1,4 @@ use super::*; #[derive(Default)] -struct NestedClass{ - -} - -impl NestedClass { - pub const ID: u64 = 1 << 0x29; - - pub fn write(&self, _buffer: &mut Vec, _strings: &mut Strings) { - } -} +pub struct NestedClass {} diff --git a/crates/libs/metagen/src/tables/param.rs b/crates/libs/metagen/src/tables/param.rs index 25cf28a5d0..7bc954fa25 100644 --- a/crates/libs/metagen/src/tables/param.rs +++ b/crates/libs/metagen/src/tables/param.rs @@ -1,12 +1,4 @@ use super::*; #[derive(Default)] -pub struct Param { -} - -impl Param { - pub const ID: u64 = 1 << 0x08; - - pub fn write(&self, _buffer: &mut Vec, _strings: &mut Strings) { - } -} +pub struct Param {} diff --git a/crates/libs/metagen/src/tables/type_def.rs b/crates/libs/metagen/src/tables/type_def.rs index 45f749ca78..c01473c4ef 100644 --- a/crates/libs/metagen/src/tables/type_def.rs +++ b/crates/libs/metagen/src/tables/type_def.rs @@ -7,21 +7,7 @@ pub struct TypeDef { } impl TypeDef { - pub const ID: u64 = 1 << 0x02; - pub fn new(name: &str, namespace: &str) -> Self { - Self { - name: name.to_string(), - namespace: namespace.to_string(), - } - } - - pub fn write(&self, buffer: &mut Vec, strings: &mut Strings) { - buffer.write(&0u32); // Flags - buffer.write(&strings.insert(&self.name)); - buffer.write(&strings.insert(&self.namespace)); - buffer.write(&0u32); // Extends // TODO: use composite_index_size to work out size of TypeDefOrRef - buffer.write(&1u32); // FieldList // TODO: use Field->TableData::index_size to work this out - buffer.write(&1u32); // MethodList // TODO: use MethodDef->TableData::index_size to work this out + Self { name: name.to_string(), namespace: namespace.to_string(), ..Default::default() } } } diff --git a/crates/libs/metagen/src/tables/type_ref.rs b/crates/libs/metagen/src/tables/type_ref.rs index 36bcc6380d..4f21f046d0 100644 --- a/crates/libs/metagen/src/tables/type_ref.rs +++ b/crates/libs/metagen/src/tables/type_ref.rs @@ -1,12 +1,4 @@ use super::*; #[derive(Default)] -pub struct TypeRef { -} - -impl TypeRef { - pub const ID: u64 = 1 << 0x01; - - pub fn write(&self, _buffer: &mut Vec, _strings: &mut Strings) { - } -} +pub struct TypeRef {} diff --git a/crates/libs/metagen/src/tables/type_spec.rs b/crates/libs/metagen/src/tables/type_spec.rs index a2976cccc4..b88c983f97 100644 --- a/crates/libs/metagen/src/tables/type_spec.rs +++ b/crates/libs/metagen/src/tables/type_spec.rs @@ -1,12 +1,4 @@ use super::*; #[derive(Default)] -pub struct TypeSpec { -} - -impl TypeSpec { - pub const ID: u64 = 1 << 0x1B; - - pub fn write(&self, _buffer: &mut Vec, _strings: &mut Strings) { - } -} +pub struct TypeSpec {} From 8d5a3a8ace25780f4c3350002dfd943eeeaca200 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Wed, 23 Mar 2022 15:26:37 -0700 Subject: [PATCH 38/55] clippy --- crates/libs/metagen/src/tables/class_layout.rs | 2 +- crates/libs/metagen/src/tables/constant.rs | 2 +- crates/libs/metagen/src/tables/custom_attribute.rs | 2 +- crates/libs/metagen/src/tables/field.rs | 2 +- crates/libs/metagen/src/tables/generic_param.rs | 2 +- crates/libs/metagen/src/tables/impl_map.rs | 2 +- crates/libs/metagen/src/tables/interface_impl.rs | 2 +- crates/libs/metagen/src/tables/member_ref.rs | 2 +- crates/libs/metagen/src/tables/method_def.rs | 2 +- crates/libs/metagen/src/tables/module.rs | 2 +- crates/libs/metagen/src/tables/module_ref.rs | 2 +- crates/libs/metagen/src/tables/nested_class.rs | 2 +- crates/libs/metagen/src/tables/param.rs | 2 +- crates/libs/metagen/src/tables/type_def.rs | 2 +- crates/libs/metagen/src/tables/type_ref.rs | 2 +- crates/libs/metagen/src/tables/type_spec.rs | 2 +- 16 files changed, 16 insertions(+), 16 deletions(-) diff --git a/crates/libs/metagen/src/tables/class_layout.rs b/crates/libs/metagen/src/tables/class_layout.rs index 914fbb76d1..eb362b4c83 100644 --- a/crates/libs/metagen/src/tables/class_layout.rs +++ b/crates/libs/metagen/src/tables/class_layout.rs @@ -1,4 +1,4 @@ -use super::*; + #[derive(Default)] pub struct ClassLayout {} diff --git a/crates/libs/metagen/src/tables/constant.rs b/crates/libs/metagen/src/tables/constant.rs index 71142703af..6e0d1df8a2 100644 --- a/crates/libs/metagen/src/tables/constant.rs +++ b/crates/libs/metagen/src/tables/constant.rs @@ -1,4 +1,4 @@ -use super::*; + #[derive(Default)] pub struct Constant {} diff --git a/crates/libs/metagen/src/tables/custom_attribute.rs b/crates/libs/metagen/src/tables/custom_attribute.rs index a920204058..3279b27c78 100644 --- a/crates/libs/metagen/src/tables/custom_attribute.rs +++ b/crates/libs/metagen/src/tables/custom_attribute.rs @@ -1,4 +1,4 @@ -use super::*; + #[derive(Default)] pub struct CustomAttribute {} diff --git a/crates/libs/metagen/src/tables/field.rs b/crates/libs/metagen/src/tables/field.rs index 63ee6e7a53..3d01f50b92 100644 --- a/crates/libs/metagen/src/tables/field.rs +++ b/crates/libs/metagen/src/tables/field.rs @@ -1,4 +1,4 @@ -use super::*; + #[derive(Default)] pub struct Field {} diff --git a/crates/libs/metagen/src/tables/generic_param.rs b/crates/libs/metagen/src/tables/generic_param.rs index 86ed9c0cfe..556224bc6f 100644 --- a/crates/libs/metagen/src/tables/generic_param.rs +++ b/crates/libs/metagen/src/tables/generic_param.rs @@ -1,4 +1,4 @@ -use super::*; + #[derive(Default)] pub struct GenericParam {} diff --git a/crates/libs/metagen/src/tables/impl_map.rs b/crates/libs/metagen/src/tables/impl_map.rs index e4653365c4..534a0c6418 100644 --- a/crates/libs/metagen/src/tables/impl_map.rs +++ b/crates/libs/metagen/src/tables/impl_map.rs @@ -1,4 +1,4 @@ -use super::*; + #[derive(Default)] pub struct ImplMap {} diff --git a/crates/libs/metagen/src/tables/interface_impl.rs b/crates/libs/metagen/src/tables/interface_impl.rs index 7fb7cb33c3..406b03a019 100644 --- a/crates/libs/metagen/src/tables/interface_impl.rs +++ b/crates/libs/metagen/src/tables/interface_impl.rs @@ -1,4 +1,4 @@ -use super::*; + #[derive(Default)] pub struct InterfaceImpl {} diff --git a/crates/libs/metagen/src/tables/member_ref.rs b/crates/libs/metagen/src/tables/member_ref.rs index 7cfd12c424..8c053070f3 100644 --- a/crates/libs/metagen/src/tables/member_ref.rs +++ b/crates/libs/metagen/src/tables/member_ref.rs @@ -1,4 +1,4 @@ -use super::*; + #[derive(Default)] pub struct MemberRef {} diff --git a/crates/libs/metagen/src/tables/method_def.rs b/crates/libs/metagen/src/tables/method_def.rs index 6e66511f46..4104692f71 100644 --- a/crates/libs/metagen/src/tables/method_def.rs +++ b/crates/libs/metagen/src/tables/method_def.rs @@ -1,4 +1,4 @@ -use super::*; + #[derive(Default)] pub struct MethodDef {} diff --git a/crates/libs/metagen/src/tables/module.rs b/crates/libs/metagen/src/tables/module.rs index ad8e35a091..bc485ba0fa 100644 --- a/crates/libs/metagen/src/tables/module.rs +++ b/crates/libs/metagen/src/tables/module.rs @@ -1,4 +1,4 @@ -use super::*; + #[derive(Default)] pub struct Module { diff --git a/crates/libs/metagen/src/tables/module_ref.rs b/crates/libs/metagen/src/tables/module_ref.rs index 9388670ecf..54856d3547 100644 --- a/crates/libs/metagen/src/tables/module_ref.rs +++ b/crates/libs/metagen/src/tables/module_ref.rs @@ -1,4 +1,4 @@ -use super::*; + #[derive(Default)] pub struct ModuleRef {} diff --git a/crates/libs/metagen/src/tables/nested_class.rs b/crates/libs/metagen/src/tables/nested_class.rs index 50736ed37c..cec7303cd3 100644 --- a/crates/libs/metagen/src/tables/nested_class.rs +++ b/crates/libs/metagen/src/tables/nested_class.rs @@ -1,4 +1,4 @@ -use super::*; + #[derive(Default)] pub struct NestedClass {} diff --git a/crates/libs/metagen/src/tables/param.rs b/crates/libs/metagen/src/tables/param.rs index 7bc954fa25..619973bf79 100644 --- a/crates/libs/metagen/src/tables/param.rs +++ b/crates/libs/metagen/src/tables/param.rs @@ -1,4 +1,4 @@ -use super::*; + #[derive(Default)] pub struct Param {} diff --git a/crates/libs/metagen/src/tables/type_def.rs b/crates/libs/metagen/src/tables/type_def.rs index c01473c4ef..77d8d9d106 100644 --- a/crates/libs/metagen/src/tables/type_def.rs +++ b/crates/libs/metagen/src/tables/type_def.rs @@ -1,4 +1,4 @@ -use super::*; + #[derive(Default)] pub struct TypeDef { diff --git a/crates/libs/metagen/src/tables/type_ref.rs b/crates/libs/metagen/src/tables/type_ref.rs index 4f21f046d0..2454474a0d 100644 --- a/crates/libs/metagen/src/tables/type_ref.rs +++ b/crates/libs/metagen/src/tables/type_ref.rs @@ -1,4 +1,4 @@ -use super::*; + #[derive(Default)] pub struct TypeRef {} diff --git a/crates/libs/metagen/src/tables/type_spec.rs b/crates/libs/metagen/src/tables/type_spec.rs index b88c983f97..40193075cd 100644 --- a/crates/libs/metagen/src/tables/type_spec.rs +++ b/crates/libs/metagen/src/tables/type_spec.rs @@ -1,4 +1,4 @@ -use super::*; + #[derive(Default)] pub struct TypeSpec {} From 49b470b6208ad05209e67ddb36488525e4ccd790 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Wed, 23 Mar 2022 15:38:04 -0700 Subject: [PATCH 39/55] tables --- crates/libs/metagen/src/lib.rs | 4 +--- crates/libs/metagen/src/strings.rs | 4 ++++ crates/libs/metagen/src/tables/mod.rs | 12 ++---------- crates/libs/metagen/src/tables/type_def.rs | 12 ++++++++++-- 4 files changed, 17 insertions(+), 15 deletions(-) diff --git a/crates/libs/metagen/src/lib.rs b/crates/libs/metagen/src/lib.rs index 0b697b811e..35c244b794 100644 --- a/crates/libs/metagen/src/lib.rs +++ b/crates/libs/metagen/src/lib.rs @@ -14,9 +14,7 @@ use tables::*; pub fn test() { let mut tables = Tables::new(); tables.module.push(Module::new("test.winmd")); - // tables.add_type_def(TypeDef::new("IFirst", "Windows.Foundation")); - // tables.add_type_def(TypeDef::new("ISecond", "Windows.Foundation")); - // tables.add_type_def(TypeDef::new("IThird", "Windows.Foundation")); + tables.type_def.push(TypeDef::module()); pe::write("/git/test.winmd", tables); } diff --git a/crates/libs/metagen/src/strings.rs b/crates/libs/metagen/src/strings.rs index 4b1c5bfb83..ddc34d609d 100644 --- a/crates/libs/metagen/src/strings.rs +++ b/crates/libs/metagen/src/strings.rs @@ -11,6 +11,10 @@ impl Strings { } pub fn insert(&mut self, value: &str) -> u32 { + if value.is_empty() { + return 0; + } + let pos = self.stream.len(); let mut insert = false; diff --git a/crates/libs/metagen/src/tables/mod.rs b/crates/libs/metagen/src/tables/mod.rs index 5c718764fb..4edfdc2f8d 100644 --- a/crates/libs/metagen/src/tables/mod.rs +++ b/crates/libs/metagen/src/tables/mod.rs @@ -90,16 +90,8 @@ impl Tables { buffer.write(&0u32); // EncBaseId (reserved) } - // ILDASM needs to be present and the first TypeDef row. - buffer.write(&0u32); - buffer.write(&strings.insert("")); - buffer.write(&0u32); - buffer.write(&0u16); - buffer.write(&1u16); - buffer.write(&1u16); - for type_def in &self.type_def { - buffer.write(&0x40A1u32); // Flags + buffer.write(&type_def.flags); buffer.write(&strings.insert(&type_def.name)); buffer.write(&strings.insert(&type_def.namespace)); buffer.write(&0u16); // Extends // TODO: use composite_index_size to work out size of TypeDefOrRef @@ -166,7 +158,7 @@ enum Index { } impl Index { - fn index(index: usize, len: usize) -> Self { + fn new(index: usize, len: usize) -> Self { if len < (1 << 16) { Self::U16(index as _) } else { diff --git a/crates/libs/metagen/src/tables/type_def.rs b/crates/libs/metagen/src/tables/type_def.rs index 77d8d9d106..0a50956f13 100644 --- a/crates/libs/metagen/src/tables/type_def.rs +++ b/crates/libs/metagen/src/tables/type_def.rs @@ -2,12 +2,20 @@ #[derive(Default)] pub struct TypeDef { + pub flags: u32, pub name: String, pub namespace: String, } impl TypeDef { - pub fn new(name: &str, namespace: &str) -> Self { - Self { name: name.to_string(), namespace: namespace.to_string(), ..Default::default() } + pub fn module() -> Self { + Self { + name: "".to_string(), + ..Default::default() + } } + + // pub fn winrt_interface(name: &str, namespace: &str) -> Self { + // Self { name: name.to_string(), namespace: namespace.to_string(), ..Default::default() } + // } } From cf26057e24de9bfdb73d4348997ef49e78787610 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Wed, 23 Mar 2022 16:17:58 -0700 Subject: [PATCH 40/55] methods --- crates/libs/metagen/src/lib.rs | 8 +++ .../libs/metagen/src/tables/class_layout.rs | 2 - crates/libs/metagen/src/tables/constant.rs | 2 - .../metagen/src/tables/custom_attribute.rs | 2 - crates/libs/metagen/src/tables/field.rs | 2 - .../libs/metagen/src/tables/generic_param.rs | 2 - crates/libs/metagen/src/tables/impl_map.rs | 2 - .../libs/metagen/src/tables/interface_impl.rs | 2 - crates/libs/metagen/src/tables/member_ref.rs | 2 - crates/libs/metagen/src/tables/method_def.rs | 12 +++- crates/libs/metagen/src/tables/mod.rs | 56 ++++++++----------- crates/libs/metagen/src/tables/module.rs | 6 +- crates/libs/metagen/src/tables/module_ref.rs | 2 - .../libs/metagen/src/tables/nested_class.rs | 2 - crates/libs/metagen/src/tables/param.rs | 2 - crates/libs/metagen/src/tables/type_def.rs | 17 +++--- crates/libs/metagen/src/tables/type_ref.rs | 2 - crates/libs/metagen/src/tables/type_spec.rs | 2 - crates/tests/define/src/main.rs | 2 +- 19 files changed, 52 insertions(+), 75 deletions(-) diff --git a/crates/libs/metagen/src/lib.rs b/crates/libs/metagen/src/lib.rs index 35c244b794..633f80b769 100644 --- a/crates/libs/metagen/src/lib.rs +++ b/crates/libs/metagen/src/lib.rs @@ -16,6 +16,14 @@ pub fn test() { tables.module.push(Module::new("test.winmd")); tables.type_def.push(TypeDef::module()); + let mut stringable = TypeDef::winrt_interface("IStringable", "Windows.Foundation"); + stringable.method_list.push(MethodDef::new("ToString")); + tables.type_def.push(stringable); + + let mut closable = TypeDef::winrt_interface("IClosable", "Windows.Foundation"); + closable.method_list.push(MethodDef::new("Close")); + tables.type_def.push(closable); + pe::write("/git/test.winmd", tables); } diff --git a/crates/libs/metagen/src/tables/class_layout.rs b/crates/libs/metagen/src/tables/class_layout.rs index eb362b4c83..9d59038c0a 100644 --- a/crates/libs/metagen/src/tables/class_layout.rs +++ b/crates/libs/metagen/src/tables/class_layout.rs @@ -1,4 +1,2 @@ - - #[derive(Default)] pub struct ClassLayout {} diff --git a/crates/libs/metagen/src/tables/constant.rs b/crates/libs/metagen/src/tables/constant.rs index 6e0d1df8a2..efd25e11f1 100644 --- a/crates/libs/metagen/src/tables/constant.rs +++ b/crates/libs/metagen/src/tables/constant.rs @@ -1,4 +1,2 @@ - - #[derive(Default)] pub struct Constant {} diff --git a/crates/libs/metagen/src/tables/custom_attribute.rs b/crates/libs/metagen/src/tables/custom_attribute.rs index 3279b27c78..3d691987e8 100644 --- a/crates/libs/metagen/src/tables/custom_attribute.rs +++ b/crates/libs/metagen/src/tables/custom_attribute.rs @@ -1,4 +1,2 @@ - - #[derive(Default)] pub struct CustomAttribute {} diff --git a/crates/libs/metagen/src/tables/field.rs b/crates/libs/metagen/src/tables/field.rs index 3d01f50b92..5a17501890 100644 --- a/crates/libs/metagen/src/tables/field.rs +++ b/crates/libs/metagen/src/tables/field.rs @@ -1,4 +1,2 @@ - - #[derive(Default)] pub struct Field {} diff --git a/crates/libs/metagen/src/tables/generic_param.rs b/crates/libs/metagen/src/tables/generic_param.rs index 556224bc6f..4b0ac645b0 100644 --- a/crates/libs/metagen/src/tables/generic_param.rs +++ b/crates/libs/metagen/src/tables/generic_param.rs @@ -1,4 +1,2 @@ - - #[derive(Default)] pub struct GenericParam {} diff --git a/crates/libs/metagen/src/tables/impl_map.rs b/crates/libs/metagen/src/tables/impl_map.rs index 534a0c6418..7806292e72 100644 --- a/crates/libs/metagen/src/tables/impl_map.rs +++ b/crates/libs/metagen/src/tables/impl_map.rs @@ -1,4 +1,2 @@ - - #[derive(Default)] pub struct ImplMap {} diff --git a/crates/libs/metagen/src/tables/interface_impl.rs b/crates/libs/metagen/src/tables/interface_impl.rs index 406b03a019..85b9e73f98 100644 --- a/crates/libs/metagen/src/tables/interface_impl.rs +++ b/crates/libs/metagen/src/tables/interface_impl.rs @@ -1,4 +1,2 @@ - - #[derive(Default)] pub struct InterfaceImpl {} diff --git a/crates/libs/metagen/src/tables/member_ref.rs b/crates/libs/metagen/src/tables/member_ref.rs index 8c053070f3..8ed0f17674 100644 --- a/crates/libs/metagen/src/tables/member_ref.rs +++ b/crates/libs/metagen/src/tables/member_ref.rs @@ -1,4 +1,2 @@ - - #[derive(Default)] pub struct MemberRef {} diff --git a/crates/libs/metagen/src/tables/method_def.rs b/crates/libs/metagen/src/tables/method_def.rs index 4104692f71..ec72758c1f 100644 --- a/crates/libs/metagen/src/tables/method_def.rs +++ b/crates/libs/metagen/src/tables/method_def.rs @@ -1,4 +1,10 @@ - - #[derive(Default)] -pub struct MethodDef {} +pub struct MethodDef { + pub name: String, +} + +impl MethodDef { + pub fn new(name: &str) -> Self { + Self { name: name.to_string() } + } +} diff --git a/crates/libs/metagen/src/tables/mod.rs b/crates/libs/metagen/src/tables/mod.rs index 4edfdc2f8d..6ac4fedc57 100644 --- a/crates/libs/metagen/src/tables/mod.rs +++ b/crates/libs/metagen/src/tables/mod.rs @@ -50,8 +50,8 @@ pub struct Tables { pub module_ref: Vec, pub type_spec: Vec, pub impl_map: Vec, - pub nested_class:Vec, - pub generic_param:Vec, + pub nested_class: Vec, + pub generic_param: Vec, } impl Tables { @@ -59,12 +59,18 @@ impl Tables { Self::default() } - pub fn into_stream(&self, strings: &mut Strings) -> Vec { + pub fn into_stream(mut self, strings: &mut Strings) -> Vec { + for type_def in &mut self.type_def { + type_def.field_index = self.field.len(); + type_def.method_index = self.method_def.len(); + self.field.append(&mut type_def.field_list); + self.method_def.append(&mut type_def.method_list); + } + let mut buffer = Vec::new(); let header = Header::new(); buffer.write(&header); - // Row sizes (ordered by table ID) buffer.write(&(self.module.len() as u32)); buffer.write(&(self.type_ref.len() as u32)); buffer.write(&(self.type_def.len() as u32)); @@ -95,8 +101,17 @@ impl Tables { buffer.write(&strings.insert(&type_def.name)); buffer.write(&strings.insert(&type_def.namespace)); buffer.write(&0u16); // Extends // TODO: use composite_index_size to work out size of TypeDefOrRef - buffer.write(&1u16); // FieldList // TODO: use Field->TableData::index_size to work this out - buffer.write(&1u16); // MethodList // TODO: use MethodDef->TableData::index_size to work this out + write_index(&mut buffer, type_def.field_index, self.field.len()); + write_index(&mut buffer, type_def.method_index, self.method_def.len()); + } + + for method_def in &self.method_def { + buffer.write(&0u32); // RVA + buffer.write(&0u16); // ImplFlags + buffer.write(&0u16); // Flags + buffer.write(&strings.insert(&method_def.name)); + buffer.write(&0u32); // Signature + buffer.write(&1u16); // ParamList } buffer.resize(round(buffer.len(), 4), 0); @@ -144,37 +159,14 @@ impl Header { } } -fn index_size(len: usize) -> u32 { +fn write_index(buffer: &mut Vec, index: usize, len: usize) { if len < (1 << 16) { - 2 + buffer.write(&(index as u16 + 1)) } else { - 4 - } -} - -enum Index { - U16(u16), - U32(u32), -} - -impl Index { - fn new(index: usize, len: usize) -> Self { - if len < (1 << 16) { - Self::U16(index as _) - } else { - Self::U32(index as _) - } - } - - fn write(&self, buffer: &mut Vec) { - match self { - Self::U16(index) => buffer.write(&index), - Self::U32(index) => buffer.write(&index), - } + buffer.write(&(index as u32 + 1)) } } -// TODO: use CodedIndex enum? fn coded_index_size(tables: &[usize]) -> u32 { fn small(row_count: usize, bits: u8) -> bool { (row_count as u64) < (1u64 << (16 - bits)) diff --git a/crates/libs/metagen/src/tables/module.rs b/crates/libs/metagen/src/tables/module.rs index bc485ba0fa..1b13527ed0 100644 --- a/crates/libs/metagen/src/tables/module.rs +++ b/crates/libs/metagen/src/tables/module.rs @@ -1,5 +1,3 @@ - - #[derive(Default)] pub struct Module { pub name: String, @@ -7,8 +5,6 @@ pub struct Module { impl Module { pub fn new(name: &str) -> Self { - Self { - name: name.to_string(), - } + Self { name: name.to_string() } } } diff --git a/crates/libs/metagen/src/tables/module_ref.rs b/crates/libs/metagen/src/tables/module_ref.rs index 54856d3547..f7558774c1 100644 --- a/crates/libs/metagen/src/tables/module_ref.rs +++ b/crates/libs/metagen/src/tables/module_ref.rs @@ -1,4 +1,2 @@ - - #[derive(Default)] pub struct ModuleRef {} diff --git a/crates/libs/metagen/src/tables/nested_class.rs b/crates/libs/metagen/src/tables/nested_class.rs index cec7303cd3..91a8ebbd1f 100644 --- a/crates/libs/metagen/src/tables/nested_class.rs +++ b/crates/libs/metagen/src/tables/nested_class.rs @@ -1,4 +1,2 @@ - - #[derive(Default)] pub struct NestedClass {} diff --git a/crates/libs/metagen/src/tables/param.rs b/crates/libs/metagen/src/tables/param.rs index 619973bf79..378740b387 100644 --- a/crates/libs/metagen/src/tables/param.rs +++ b/crates/libs/metagen/src/tables/param.rs @@ -1,4 +1,2 @@ - - #[derive(Default)] pub struct Param {} diff --git a/crates/libs/metagen/src/tables/type_def.rs b/crates/libs/metagen/src/tables/type_def.rs index 0a50956f13..4624e97746 100644 --- a/crates/libs/metagen/src/tables/type_def.rs +++ b/crates/libs/metagen/src/tables/type_def.rs @@ -1,21 +1,22 @@ - +use super::*; #[derive(Default)] pub struct TypeDef { pub flags: u32, pub name: String, pub namespace: String, + pub field_list: Vec, + pub method_list: Vec, + pub(crate) field_index: usize, + pub(crate) method_index: usize, } impl TypeDef { pub fn module() -> Self { - Self { - name: "".to_string(), - ..Default::default() - } + Self { name: "".to_string(), ..Default::default() } } - // pub fn winrt_interface(name: &str, namespace: &str) -> Self { - // Self { name: name.to_string(), namespace: namespace.to_string(), ..Default::default() } - // } + pub fn winrt_interface(name: &str, namespace: &str) -> Self { + Self { name: name.to_string(), namespace: namespace.to_string(), ..Default::default() } + } } diff --git a/crates/libs/metagen/src/tables/type_ref.rs b/crates/libs/metagen/src/tables/type_ref.rs index 2454474a0d..aa019e521b 100644 --- a/crates/libs/metagen/src/tables/type_ref.rs +++ b/crates/libs/metagen/src/tables/type_ref.rs @@ -1,4 +1,2 @@ - - #[derive(Default)] pub struct TypeRef {} diff --git a/crates/libs/metagen/src/tables/type_spec.rs b/crates/libs/metagen/src/tables/type_spec.rs index 40193075cd..f5b2e35551 100644 --- a/crates/libs/metagen/src/tables/type_spec.rs +++ b/crates/libs/metagen/src/tables/type_spec.rs @@ -1,4 +1,2 @@ - - #[derive(Default)] pub struct TypeSpec {} diff --git a/crates/tests/define/src/main.rs b/crates/tests/define/src/main.rs index 508443b1f0..7f6512fb4c 100644 --- a/crates/tests/define/src/main.rs +++ b/crates/tests/define/src/main.rs @@ -15,7 +15,7 @@ fn main() { for method in def.methods() { let name = method.name(); - println!("field: {}", name); + println!("method: {}", name); } } From c0df140068f7a033b4206d3d17368c84a1d2915b Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Wed, 23 Mar 2022 16:32:42 -0700 Subject: [PATCH 41/55] signature --- crates/libs/metagen/src/lib.rs | 2 ++ crates/libs/metagen/src/signature.rs | 9 +++++++++ crates/libs/metagen/src/tables/mod.rs | 2 +- 3 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 crates/libs/metagen/src/signature.rs diff --git a/crates/libs/metagen/src/lib.rs b/crates/libs/metagen/src/lib.rs index 633f80b769..a6d8ba291e 100644 --- a/crates/libs/metagen/src/lib.rs +++ b/crates/libs/metagen/src/lib.rs @@ -2,9 +2,11 @@ mod blobs; mod pe; +mod signature; mod strings; mod tables; use blobs::*; +use signature::*; use std::collections::*; use std::mem::*; use std::slice::*; diff --git a/crates/libs/metagen/src/signature.rs b/crates/libs/metagen/src/signature.rs new file mode 100644 index 0000000000..b39801eb68 --- /dev/null +++ b/crates/libs/metagen/src/signature.rs @@ -0,0 +1,9 @@ +use crate::*; + +pub struct Signature {} + +impl Signature { + pub fn into_stream(mut self) -> Vec { + vec![] + } +} diff --git a/crates/libs/metagen/src/tables/mod.rs b/crates/libs/metagen/src/tables/mod.rs index 6ac4fedc57..8ed68e7c76 100644 --- a/crates/libs/metagen/src/tables/mod.rs +++ b/crates/libs/metagen/src/tables/mod.rs @@ -100,7 +100,7 @@ impl Tables { buffer.write(&type_def.flags); buffer.write(&strings.insert(&type_def.name)); buffer.write(&strings.insert(&type_def.namespace)); - buffer.write(&0u16); // Extends // TODO: use composite_index_size to work out size of TypeDefOrRef + buffer.write(&0u16); // Extends write_index(&mut buffer, type_def.field_index, self.field.len()); write_index(&mut buffer, type_def.method_index, self.method_def.len()); } From 284ab96b44923389a7e802172d70d30ddf113af9 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Wed, 23 Mar 2022 16:40:43 -0700 Subject: [PATCH 42/55] params --- crates/libs/metagen/src/tables/method_def.rs | 6 +++++- crates/libs/metagen/src/tables/mod.rs | 11 +++++++++++ crates/libs/metagen/src/tables/param.rs | 6 +++++- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/crates/libs/metagen/src/tables/method_def.rs b/crates/libs/metagen/src/tables/method_def.rs index ec72758c1f..07a2650df8 100644 --- a/crates/libs/metagen/src/tables/method_def.rs +++ b/crates/libs/metagen/src/tables/method_def.rs @@ -1,10 +1,14 @@ +use super::*; + #[derive(Default)] pub struct MethodDef { pub name: String, + pub param_list: Vec, + pub(crate) param_index: usize, } impl MethodDef { pub fn new(name: &str) -> Self { - Self { name: name.to_string() } + Self { name: name.to_string(), ..Default::default() } } } diff --git a/crates/libs/metagen/src/tables/mod.rs b/crates/libs/metagen/src/tables/mod.rs index 8ed68e7c76..9a33349716 100644 --- a/crates/libs/metagen/src/tables/mod.rs +++ b/crates/libs/metagen/src/tables/mod.rs @@ -67,6 +67,11 @@ impl Tables { self.method_def.append(&mut type_def.method_list); } + for method_def in &mut self.method_def { + method_def.param_index = self.param.len(); + self.param.append(&mut method_def.param_list); + } + let mut buffer = Vec::new(); let header = Header::new(); buffer.write(&header); @@ -114,6 +119,12 @@ impl Tables { buffer.write(&1u16); // ParamList } + for param in &self.param { + buffer.write(¶m.flags); + buffer.write(¶m.sequence); + buffer.write(&strings.insert(¶m.name)); + } + buffer.resize(round(buffer.len(), 4), 0); buffer } diff --git a/crates/libs/metagen/src/tables/param.rs b/crates/libs/metagen/src/tables/param.rs index 378740b387..d9611d3155 100644 --- a/crates/libs/metagen/src/tables/param.rs +++ b/crates/libs/metagen/src/tables/param.rs @@ -1,2 +1,6 @@ #[derive(Default)] -pub struct Param {} +pub struct Param { + pub flags: u16, + pub sequence: u16, + pub name: String, +} From 3576136cf7bbaaef40b78c37b387804cd257763e Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Thu, 24 Mar 2022 11:23:13 -0700 Subject: [PATCH 43/55] normalize --- crates/libs/metagen/src/tables/mod.rs | 28 ++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/crates/libs/metagen/src/tables/mod.rs b/crates/libs/metagen/src/tables/mod.rs index 9a33349716..4fc486a6f2 100644 --- a/crates/libs/metagen/src/tables/mod.rs +++ b/crates/libs/metagen/src/tables/mod.rs @@ -60,17 +60,7 @@ impl Tables { } pub fn into_stream(mut self, strings: &mut Strings) -> Vec { - for type_def in &mut self.type_def { - type_def.field_index = self.field.len(); - type_def.method_index = self.method_def.len(); - self.field.append(&mut type_def.field_list); - self.method_def.append(&mut type_def.method_list); - } - - for method_def in &mut self.method_def { - method_def.param_index = self.param.len(); - self.param.append(&mut method_def.param_list); - } + self.normalize(); let mut buffer = Vec::new(); let header = Header::new(); @@ -128,6 +118,22 @@ impl Tables { buffer.resize(round(buffer.len(), 4), 0); buffer } + + // Once all of the type information has been added, normalization is the process of packing + // the various relational records into their respective tables and leaving only index behind. + fn normalize(&mut self) { + for type_def in &mut self.type_def { + type_def.field_index = self.field.len(); + type_def.method_index = self.method_def.len(); + self.field.append(&mut type_def.field_list); + self.method_def.append(&mut type_def.method_list); + } + + for method_def in &mut self.method_def { + method_def.param_index = self.param.len(); + self.param.append(&mut method_def.param_list); + } + } } #[repr(C)] From 656b18fe23d765c71ad5cf002cd5251315324269 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Thu, 24 Mar 2022 13:26:27 -0700 Subject: [PATCH 44/55] cli and api --- crates/libs/metagen/src/blobs.rs | 2 +- crates/libs/metagen/src/gen.rs | 22 ++++++++++++++++++++++ crates/libs/metagen/src/helpers.rs | 19 +++++++++++++++++++ crates/libs/metagen/src/lib.rs | 23 ++++------------------- crates/libs/metagen/src/pe.rs | 2 +- crates/libs/metagen/src/signature.rs | 2 +- crates/libs/metagen/src/strings.rs | 2 +- crates/tools/ilrs/Cargo.toml | 7 +++++++ crates/tools/ilrs/src/main.rs | 2 ++ usize | 0 10 files changed, 58 insertions(+), 23 deletions(-) create mode 100644 crates/libs/metagen/src/gen.rs create mode 100644 crates/libs/metagen/src/helpers.rs create mode 100644 crates/tools/ilrs/Cargo.toml create mode 100644 crates/tools/ilrs/src/main.rs create mode 100644 usize diff --git a/crates/libs/metagen/src/blobs.rs b/crates/libs/metagen/src/blobs.rs index f0a00efde4..dc08e356eb 100644 --- a/crates/libs/metagen/src/blobs.rs +++ b/crates/libs/metagen/src/blobs.rs @@ -1,4 +1,4 @@ -use crate::*; +use super::*; pub(crate) struct Blobs { set: BTreeMap, usize>, diff --git a/crates/libs/metagen/src/gen.rs b/crates/libs/metagen/src/gen.rs new file mode 100644 index 0000000000..05a7679e32 --- /dev/null +++ b/crates/libs/metagen/src/gen.rs @@ -0,0 +1,22 @@ +use super::*; + +// TODO: should be able to write a trivial CLI for this, call it ridl. :) + +#[derive(Default)] +pub struct Gen<'a> { + // Source files to include + pub source: Vec<&'a str>, + + // Winmd files to include. + pub input: Vec<&'a str>, + + // Winmd files to reference. + pub reference: Vec<&'a str>, + + // Name of resulting winmd file. + pub output: &'a str, +} + +pub fn gen(gen: &Gen) { + +} diff --git a/crates/libs/metagen/src/helpers.rs b/crates/libs/metagen/src/helpers.rs new file mode 100644 index 0000000000..d202fbf3a1 --- /dev/null +++ b/crates/libs/metagen/src/helpers.rs @@ -0,0 +1,19 @@ +use std::slice::*; +use std::mem::*; + +pub fn round(size: usize, round: usize) -> usize { + let round = round - 1; + (size + round) & !round +} + +pub trait Write { + fn write(&mut self, value: &T); +} + +impl Write for Vec { + fn write(&mut self, value: &T) { + unsafe { + self.extend_from_slice(from_raw_parts(value as *const _ as _, size_of::())); + } + } +} diff --git a/crates/libs/metagen/src/lib.rs b/crates/libs/metagen/src/lib.rs index a6d8ba291e..b57dba051b 100644 --- a/crates/libs/metagen/src/lib.rs +++ b/crates/libs/metagen/src/lib.rs @@ -5,13 +5,15 @@ mod pe; mod signature; mod strings; mod tables; +mod gen; +mod helpers; use blobs::*; use signature::*; use std::collections::*; -use std::mem::*; -use std::slice::*; use strings::*; use tables::*; +use helpers::*; +pub use gen::*; pub fn test() { let mut tables = Tables::new(); @@ -28,20 +30,3 @@ pub fn test() { pe::write("/git/test.winmd", tables); } - -fn round(size: usize, round: usize) -> usize { - let round = round - 1; - (size + round) & !round -} - -trait Write { - fn write(&mut self, value: &T); -} - -impl Write for Vec { - fn write(&mut self, value: &T) { - unsafe { - self.extend_from_slice(from_raw_parts(value as *const _ as _, size_of::())); - } - } -} diff --git a/crates/libs/metagen/src/pe.rs b/crates/libs/metagen/src/pe.rs index eafa0be102..3de9aedb14 100644 --- a/crates/libs/metagen/src/pe.rs +++ b/crates/libs/metagen/src/pe.rs @@ -1,6 +1,6 @@ // https://docs.microsoft.com/en-us/windows/win32/debug/pe-format -use crate::*; +use super::*; use std::mem::*; pub(crate) fn write(filename: &str, tables: Tables) { diff --git a/crates/libs/metagen/src/signature.rs b/crates/libs/metagen/src/signature.rs index b39801eb68..37c0e2818d 100644 --- a/crates/libs/metagen/src/signature.rs +++ b/crates/libs/metagen/src/signature.rs @@ -1,4 +1,4 @@ -use crate::*; +use super::*; pub struct Signature {} diff --git a/crates/libs/metagen/src/strings.rs b/crates/libs/metagen/src/strings.rs index ddc34d609d..969478d53e 100644 --- a/crates/libs/metagen/src/strings.rs +++ b/crates/libs/metagen/src/strings.rs @@ -1,4 +1,4 @@ -use crate::*; +use super::*; pub struct Strings { set: BTreeMap, diff --git a/crates/tools/ilrs/Cargo.toml b/crates/tools/ilrs/Cargo.toml new file mode 100644 index 0000000000..0826296f81 --- /dev/null +++ b/crates/tools/ilrs/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "ilrs" +version = "0.0.0" +edition = "2018" +publish = false + +[dependencies] diff --git a/crates/tools/ilrs/src/main.rs b/crates/tools/ilrs/src/main.rs new file mode 100644 index 0000000000..f79c691f08 --- /dev/null +++ b/crates/tools/ilrs/src/main.rs @@ -0,0 +1,2 @@ +fn main() { +} diff --git a/usize b/usize new file mode 100644 index 0000000000..e69de29bb2 From cafa734985ff996fb2de23fb613b5b67908bc40f Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Thu, 24 Mar 2022 14:06:14 -0700 Subject: [PATCH 45/55] ilrs --- crates/libs/metagen/src/gen.rs | 18 ++++++++----- crates/tools/ilrs/Cargo.toml | 1 + crates/tools/ilrs/src/main.rs | 48 ++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 6 deletions(-) diff --git a/crates/libs/metagen/src/gen.rs b/crates/libs/metagen/src/gen.rs index 05a7679e32..3a2fc5745b 100644 --- a/crates/libs/metagen/src/gen.rs +++ b/crates/libs/metagen/src/gen.rs @@ -3,20 +3,26 @@ use super::*; // TODO: should be able to write a trivial CLI for this, call it ridl. :) #[derive(Default)] -pub struct Gen<'a> { +pub struct Gen { // Source files to include - pub source: Vec<&'a str>, + pub sources: Vec, // Winmd files to include. - pub input: Vec<&'a str>, + pub inputs: Vec, // Winmd files to reference. - pub reference: Vec<&'a str>, + pub references: Vec, // Name of resulting winmd file. - pub output: &'a str, + pub output: String, } -pub fn gen(gen: &Gen) { +impl Gen { + pub fn new() -> Self { + Self::default() + } +} +pub fn gen(gen: &Gen) -> std::io::Result<()> { + Ok(()) } diff --git a/crates/tools/ilrs/Cargo.toml b/crates/tools/ilrs/Cargo.toml index 0826296f81..14eb59b31f 100644 --- a/crates/tools/ilrs/Cargo.toml +++ b/crates/tools/ilrs/Cargo.toml @@ -5,3 +5,4 @@ edition = "2018" publish = false [dependencies] +metagen = { package = "windows-metagen", path = "../../libs/metagen", version = "0.34.0" } diff --git a/crates/tools/ilrs/src/main.rs b/crates/tools/ilrs/src/main.rs index f79c691f08..9f1d84dbfb 100644 --- a/crates/tools/ilrs/src/main.rs +++ b/crates/tools/ilrs/src/main.rs @@ -1,2 +1,50 @@ +use metagen::*; +use std::env::*; + fn main() { + let mut gen = metagen::Gen::new(); + let mut kind = ArgKind::None; + + for arg in args() { + match kind { + ArgKind::None => { + match arg.as_str() { + "-s" => kind = ArgKind::Source, + "-i" => kind = ArgKind::Input, + "-r" => kind = ArgKind::Reference, + "-o" => kind = ArgKind::Output, + _ => return print_help(), + } + } + ArgKind::Source => gen.sources.push(arg), + ArgKind::Input => gen.inputs.push(arg), + ArgKind::Reference => gen.references.push(arg), + ArgKind::Output => { + if gen.output.is_empty() { + gen.output = arg; + } else { + return print_help(); + } + } + } + } + + if (gen.sources.is_empty() || gen.inputs.is_empty()) || gen.output.is_empty() { + return print_help(); + } + + let _ = metagen::gen(&gen); + // TODO: print error report +} + +fn print_help() { + println!("help"); +} + +enum ArgKind { + None, + Source, + Input, + Reference, + Output } From 0658e26780e6bca1ecc753517459ef1947612ce9 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Thu, 24 Mar 2022 14:37:24 -0700 Subject: [PATCH 46/55] ilrs --- crates/libs/metagen/src/blobs.rs | 6 ++- crates/libs/metagen/src/gen.rs | 8 +-- crates/libs/metagen/src/lib.rs | 3 +- crates/libs/metagen/src/pe.rs | 4 +- crates/libs/metagen/src/signature.rs | 9 ---- crates/libs/metagen/src/tables/method_def.rs | 1 + crates/libs/metagen/src/tables/mod.rs | 56 ++++++++++---------- crates/tools/ilrs/src/main.rs | 1 - 8 files changed, 39 insertions(+), 49 deletions(-) delete mode 100644 crates/libs/metagen/src/signature.rs diff --git a/crates/libs/metagen/src/blobs.rs b/crates/libs/metagen/src/blobs.rs index dc08e356eb..2754376924 100644 --- a/crates/libs/metagen/src/blobs.rs +++ b/crates/libs/metagen/src/blobs.rs @@ -11,10 +11,14 @@ impl Blobs { } pub fn insert(&mut self, value: &[u8]) -> u32 { + if value.is_empty() { + return 0; + } + let pos = self.stream.len(); let mut insert = false; - self.set.entry(value.to_vec()).or_insert_with(|| { + let pos = *self.set.entry(value.to_vec()).or_insert_with(|| { insert = true; pos }); diff --git a/crates/libs/metagen/src/gen.rs b/crates/libs/metagen/src/gen.rs index 3a2fc5745b..6ea54b3099 100644 --- a/crates/libs/metagen/src/gen.rs +++ b/crates/libs/metagen/src/gen.rs @@ -1,10 +1,6 @@ -use super::*; - -// TODO: should be able to write a trivial CLI for this, call it ridl. :) - #[derive(Default)] pub struct Gen { - // Source files to include + // Source files to include. pub sources: Vec, // Winmd files to include. @@ -23,6 +19,6 @@ impl Gen { } } -pub fn gen(gen: &Gen) -> std::io::Result<()> { +pub fn gen(_gen: &Gen) -> std::io::Result<()> { Ok(()) } diff --git a/crates/libs/metagen/src/lib.rs b/crates/libs/metagen/src/lib.rs index b57dba051b..97a7ef69c5 100644 --- a/crates/libs/metagen/src/lib.rs +++ b/crates/libs/metagen/src/lib.rs @@ -2,13 +2,12 @@ mod blobs; mod pe; -mod signature; mod strings; mod tables; mod gen; mod helpers; use blobs::*; -use signature::*; + use std::collections::*; use strings::*; use tables::*; diff --git a/crates/libs/metagen/src/pe.rs b/crates/libs/metagen/src/pe.rs index 3de9aedb14..6d0667e9ed 100644 --- a/crates/libs/metagen/src/pe.rs +++ b/crates/libs/metagen/src/pe.rs @@ -12,9 +12,9 @@ pub(crate) fn write(filename: &str, tables: Tables) { let metadata = MetadataHeader::new(4); let mut strings = Strings::new(); - let blobs = Blobs::new(); + let mut blobs = Blobs::new(); - let mut tables = tables.into_stream(&mut strings); + let mut tables = tables.into_stream(&mut strings, &mut blobs); let mut guids = guid_stream(); let mut strings = strings.into_stream(); let mut blobs = blobs.into_stream(); diff --git a/crates/libs/metagen/src/signature.rs b/crates/libs/metagen/src/signature.rs deleted file mode 100644 index 37c0e2818d..0000000000 --- a/crates/libs/metagen/src/signature.rs +++ /dev/null @@ -1,9 +0,0 @@ -use super::*; - -pub struct Signature {} - -impl Signature { - pub fn into_stream(mut self) -> Vec { - vec![] - } -} diff --git a/crates/libs/metagen/src/tables/method_def.rs b/crates/libs/metagen/src/tables/method_def.rs index 07a2650df8..6be3d105b1 100644 --- a/crates/libs/metagen/src/tables/method_def.rs +++ b/crates/libs/metagen/src/tables/method_def.rs @@ -3,6 +3,7 @@ use super::*; #[derive(Default)] pub struct MethodDef { pub name: String, + pub signature: Vec, pub param_list: Vec, pub(crate) param_index: usize, } diff --git a/crates/libs/metagen/src/tables/mod.rs b/crates/libs/metagen/src/tables/mod.rs index 4fc486a6f2..2ea8330eca 100644 --- a/crates/libs/metagen/src/tables/mod.rs +++ b/crates/libs/metagen/src/tables/mod.rs @@ -59,7 +59,7 @@ impl Tables { Self::default() } - pub fn into_stream(mut self, strings: &mut Strings) -> Vec { + pub(crate) fn into_stream(mut self, strings: &mut Strings, blobs: &mut Blobs) -> Vec { self.normalize(); let mut buffer = Vec::new(); @@ -105,7 +105,7 @@ impl Tables { buffer.write(&0u16); // ImplFlags buffer.write(&0u16); // Flags buffer.write(&strings.insert(&method_def.name)); - buffer.write(&0u32); // Signature + buffer.write(&blobs.insert(&method_def.signature)); buffer.write(&1u16); // ParamList } @@ -184,29 +184,29 @@ fn write_index(buffer: &mut Vec, index: usize, len: usize) { } } -fn coded_index_size(tables: &[usize]) -> u32 { - fn small(row_count: usize, bits: u8) -> bool { - (row_count as u64) < (1u64 << (16 - bits)) - } - - fn bits_needed(value: usize) -> u8 { - let mut value = value - 1; - let mut bits: u8 = 1; - loop { - value >>= 1; - if value == 0 { - break; - } - bits += 1; - } - bits - } - - let bits_needed = bits_needed(tables.len()); - - if tables.iter().all(|len| small(*len, bits_needed)) { - 2 - } else { - 4 - } -} +// fn coded_index_size(tables: &[usize]) -> u32 { +// fn small(row_count: usize, bits: u8) -> bool { +// (row_count as u64) < (1u64 << (16 - bits)) +// } + +// fn bits_needed(value: usize) -> u8 { +// let mut value = value - 1; +// let mut bits: u8 = 1; +// loop { +// value >>= 1; +// if value == 0 { +// break; +// } +// bits += 1; +// } +// bits +// } + +// let bits_needed = bits_needed(tables.len()); + +// if tables.iter().all(|len| small(*len, bits_needed)) { +// 2 +// } else { +// 4 +// } +// } diff --git a/crates/tools/ilrs/src/main.rs b/crates/tools/ilrs/src/main.rs index 9f1d84dbfb..5541c07566 100644 --- a/crates/tools/ilrs/src/main.rs +++ b/crates/tools/ilrs/src/main.rs @@ -1,4 +1,3 @@ -use metagen::*; use std::env::*; fn main() { From a69bf24671c804874015edd5d81085467025587e Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Thu, 24 Mar 2022 14:41:54 -0700 Subject: [PATCH 47/55] fmt --- crates/libs/metagen/src/helpers.rs | 2 +- crates/libs/metagen/src/lib.rs | 8 ++++---- crates/tools/ilrs/src/main.rs | 20 +++++++++----------- 3 files changed, 14 insertions(+), 16 deletions(-) diff --git a/crates/libs/metagen/src/helpers.rs b/crates/libs/metagen/src/helpers.rs index d202fbf3a1..080c108d25 100644 --- a/crates/libs/metagen/src/helpers.rs +++ b/crates/libs/metagen/src/helpers.rs @@ -1,5 +1,5 @@ -use std::slice::*; use std::mem::*; +use std::slice::*; pub fn round(size: usize, round: usize) -> usize { let round = round - 1; diff --git a/crates/libs/metagen/src/lib.rs b/crates/libs/metagen/src/lib.rs index 97a7ef69c5..254dc69f48 100644 --- a/crates/libs/metagen/src/lib.rs +++ b/crates/libs/metagen/src/lib.rs @@ -1,18 +1,18 @@ // https://docs.microsoft.com/en-us/windows/win32/debug/pe-format mod blobs; +mod gen; +mod helpers; mod pe; mod strings; mod tables; -mod gen; -mod helpers; use blobs::*; +pub use gen::*; +use helpers::*; use std::collections::*; use strings::*; use tables::*; -use helpers::*; -pub use gen::*; pub fn test() { let mut tables = Tables::new(); diff --git a/crates/tools/ilrs/src/main.rs b/crates/tools/ilrs/src/main.rs index 5541c07566..f421f89465 100644 --- a/crates/tools/ilrs/src/main.rs +++ b/crates/tools/ilrs/src/main.rs @@ -6,15 +6,13 @@ fn main() { for arg in args() { match kind { - ArgKind::None => { - match arg.as_str() { - "-s" => kind = ArgKind::Source, - "-i" => kind = ArgKind::Input, - "-r" => kind = ArgKind::Reference, - "-o" => kind = ArgKind::Output, - _ => return print_help(), - } - } + ArgKind::None => match arg.as_str() { + "-s" => kind = ArgKind::Source, + "-i" => kind = ArgKind::Input, + "-r" => kind = ArgKind::Reference, + "-o" => kind = ArgKind::Output, + _ => return print_help(), + }, ArgKind::Source => gen.sources.push(arg), ArgKind::Input => gen.inputs.push(arg), ArgKind::Reference => gen.references.push(arg), @@ -33,7 +31,7 @@ fn main() { } let _ = metagen::gen(&gen); - // TODO: print error report + // TODO: print error report } fn print_help() { @@ -45,5 +43,5 @@ enum ArgKind { Source, Input, Reference, - Output + Output, } From e13da7367622554789501f05c2efd67ca96c27b0 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Thu, 24 Mar 2022 15:27:18 -0700 Subject: [PATCH 48/55] merged --- crates/libs/bindgen/src/lib.rs | 2 +- crates/libs/define/Cargo.toml | 17 ------- crates/libs/define/src/lib.rs | 7 --- crates/libs/metadata/src/lib.rs | 45 +------------------ .../metadata/src/{ => reader}/array_info.rs | 0 .../metadata/src/{ => reader}/async_kind.rs | 0 crates/libs/metadata/src/{ => reader}/blob.rs | 0 crates/libs/metadata/src/{ => reader}/cfg.rs | 0 .../libs/metadata/src/{ => reader}/codes.rs | 0 .../src/{ => reader}/constant_value.rs | 0 crates/libs/metadata/src/{ => reader}/file.rs | 5 +-- crates/libs/metadata/src/{ => reader}/guid.rs | 0 .../src/{ => reader}/interface_kind.rs | 0 crates/libs/metadata/src/reader/mod.rs | 43 ++++++++++++++++++ .../metadata/src/{ => reader}/param_flags.rs | 0 crates/libs/metadata/src/{ => reader}/row.rs | 0 .../metadata/src/{ => reader}/signature.rs | 0 .../src/{ => reader}/signature_kind.rs | 0 .../src/{ => reader}/tables/assembly_ref.rs | 0 .../src/{ => reader}/tables/attribute.rs | 0 .../src/{ => reader}/tables/class_layout.rs | 0 .../src/{ => reader}/tables/constant.rs | 0 .../metadata/src/{ => reader}/tables/field.rs | 0 .../src/{ => reader}/tables/generic_param.rs | 0 .../src/{ => reader}/tables/impl_map.rs | 0 .../src/{ => reader}/tables/interface_impl.rs | 0 .../src/{ => reader}/tables/member_ref.rs | 0 .../src/{ => reader}/tables/method_def.rs | 0 .../metadata/src/{ => reader}/tables/mod.rs | 0 .../src/{ => reader}/tables/module_ref.rs | 0 .../src/{ => reader}/tables/nested_class.rs | 0 .../metadata/src/{ => reader}/tables/param.rs | 0 .../src/{ => reader}/tables/type_def.rs | 0 .../src/{ => reader}/tables/type_ref.rs | 0 .../src/{ => reader}/tables/type_spec.rs | 0 .../libs/metadata/src/{ => reader}/traits.rs | 0 crates/libs/metadata/src/{ => reader}/type.rs | 0 .../metadata/src/{ => reader}/type_kind.rs | 0 .../metadata/src/{ => reader}/type_name.rs | 0 .../metadata/src/{ => reader}/type_reader.rs | 0 .../metadata/src/{ => reader}/type_tree.rs | 0 .../metadata/src/{ => reader}/workspace.rs | 6 +-- .../src => metadata/src/writer}/blobs.rs | 0 .../src => metadata/src/writer}/gen.rs | 0 .../src => metadata/src/writer}/helpers.rs | 0 .../src/lib.rs => metadata/src/writer/mod.rs} | 0 .../src => metadata/src/writer}/pe.rs | 0 .../src => metadata/src/writer}/strings.rs | 0 .../src/writer}/tables/class_layout.rs | 0 .../src/writer}/tables/constant.rs | 0 .../src/writer}/tables/custom_attribute.rs | 0 .../src/writer}/tables/field.rs | 0 .../src/writer}/tables/generic_param.rs | 0 .../src/writer}/tables/impl_map.rs | 0 .../src/writer}/tables/interface_impl.rs | 0 .../src/writer}/tables/member_ref.rs | 0 .../src/writer}/tables/method_def.rs | 0 .../src => metadata/src/writer}/tables/mod.rs | 0 .../src/writer}/tables/module.rs | 0 .../src/writer}/tables/module_ref.rs | 0 .../src/writer}/tables/nested_class.rs | 0 .../src/writer}/tables/param.rs | 0 .../src/writer}/tables/type_def.rs | 0 .../src/writer}/tables/type_ref.rs | 0 .../src/writer}/tables/type_spec.rs | 0 crates/libs/metagen/Cargo.toml | 8 ---- crates/libs/windows/Cargo.toml | 2 - crates/libs/windows/src/core/mod.rs | 4 -- crates/tests/define/Cargo.toml | 17 ------- crates/tests/define/src/main.rs | 23 ---------- crates/tests/define/tests/test.rs | 22 --------- crates/tests/writer/Cargo.toml | 8 ++++ crates/tests/writer/src/main.rs | 3 ++ crates/tests/writer/tests/test.rs | 4 ++ crates/tools/gnu/src/main.rs | 2 +- crates/tools/ilrs/Cargo.toml | 2 +- crates/tools/ilrs/src/main.rs | 4 +- crates/tools/msvc/src/main.rs | 2 +- crates/tools/sys/src/main.rs | 7 +-- crates/tools/windows/src/main.rs | 9 ++-- crates/tools/yml/src/main.rs | 4 +- 81 files changed, 80 insertions(+), 166 deletions(-) delete mode 100644 crates/libs/define/Cargo.toml delete mode 100644 crates/libs/define/src/lib.rs rename crates/libs/metadata/src/{ => reader}/array_info.rs (100%) rename crates/libs/metadata/src/{ => reader}/async_kind.rs (100%) rename crates/libs/metadata/src/{ => reader}/blob.rs (100%) rename crates/libs/metadata/src/{ => reader}/cfg.rs (100%) rename crates/libs/metadata/src/{ => reader}/codes.rs (100%) rename crates/libs/metadata/src/{ => reader}/constant_value.rs (100%) rename crates/libs/metadata/src/{ => reader}/file.rs (99%) rename crates/libs/metadata/src/{ => reader}/guid.rs (100%) rename crates/libs/metadata/src/{ => reader}/interface_kind.rs (100%) create mode 100644 crates/libs/metadata/src/reader/mod.rs rename crates/libs/metadata/src/{ => reader}/param_flags.rs (100%) rename crates/libs/metadata/src/{ => reader}/row.rs (100%) rename crates/libs/metadata/src/{ => reader}/signature.rs (100%) rename crates/libs/metadata/src/{ => reader}/signature_kind.rs (100%) rename crates/libs/metadata/src/{ => reader}/tables/assembly_ref.rs (100%) rename crates/libs/metadata/src/{ => reader}/tables/attribute.rs (100%) rename crates/libs/metadata/src/{ => reader}/tables/class_layout.rs (100%) rename crates/libs/metadata/src/{ => reader}/tables/constant.rs (100%) rename crates/libs/metadata/src/{ => reader}/tables/field.rs (100%) rename crates/libs/metadata/src/{ => reader}/tables/generic_param.rs (100%) rename crates/libs/metadata/src/{ => reader}/tables/impl_map.rs (100%) rename crates/libs/metadata/src/{ => reader}/tables/interface_impl.rs (100%) rename crates/libs/metadata/src/{ => reader}/tables/member_ref.rs (100%) rename crates/libs/metadata/src/{ => reader}/tables/method_def.rs (100%) rename crates/libs/metadata/src/{ => reader}/tables/mod.rs (100%) rename crates/libs/metadata/src/{ => reader}/tables/module_ref.rs (100%) rename crates/libs/metadata/src/{ => reader}/tables/nested_class.rs (100%) rename crates/libs/metadata/src/{ => reader}/tables/param.rs (100%) rename crates/libs/metadata/src/{ => reader}/tables/type_def.rs (100%) rename crates/libs/metadata/src/{ => reader}/tables/type_ref.rs (100%) rename crates/libs/metadata/src/{ => reader}/tables/type_spec.rs (100%) rename crates/libs/metadata/src/{ => reader}/traits.rs (100%) rename crates/libs/metadata/src/{ => reader}/type.rs (100%) rename crates/libs/metadata/src/{ => reader}/type_kind.rs (100%) rename crates/libs/metadata/src/{ => reader}/type_name.rs (100%) rename crates/libs/metadata/src/{ => reader}/type_reader.rs (100%) rename crates/libs/metadata/src/{ => reader}/type_tree.rs (100%) rename crates/libs/metadata/src/{ => reader}/workspace.rs (92%) rename crates/libs/{metagen/src => metadata/src/writer}/blobs.rs (100%) rename crates/libs/{metagen/src => metadata/src/writer}/gen.rs (100%) rename crates/libs/{metagen/src => metadata/src/writer}/helpers.rs (100%) rename crates/libs/{metagen/src/lib.rs => metadata/src/writer/mod.rs} (100%) rename crates/libs/{metagen/src => metadata/src/writer}/pe.rs (100%) rename crates/libs/{metagen/src => metadata/src/writer}/strings.rs (100%) rename crates/libs/{metagen/src => metadata/src/writer}/tables/class_layout.rs (100%) rename crates/libs/{metagen/src => metadata/src/writer}/tables/constant.rs (100%) rename crates/libs/{metagen/src => metadata/src/writer}/tables/custom_attribute.rs (100%) rename crates/libs/{metagen/src => metadata/src/writer}/tables/field.rs (100%) rename crates/libs/{metagen/src => metadata/src/writer}/tables/generic_param.rs (100%) rename crates/libs/{metagen/src => metadata/src/writer}/tables/impl_map.rs (100%) rename crates/libs/{metagen/src => metadata/src/writer}/tables/interface_impl.rs (100%) rename crates/libs/{metagen/src => metadata/src/writer}/tables/member_ref.rs (100%) rename crates/libs/{metagen/src => metadata/src/writer}/tables/method_def.rs (100%) rename crates/libs/{metagen/src => metadata/src/writer}/tables/mod.rs (100%) rename crates/libs/{metagen/src => metadata/src/writer}/tables/module.rs (100%) rename crates/libs/{metagen/src => metadata/src/writer}/tables/module_ref.rs (100%) rename crates/libs/{metagen/src => metadata/src/writer}/tables/nested_class.rs (100%) rename crates/libs/{metagen/src => metadata/src/writer}/tables/param.rs (100%) rename crates/libs/{metagen/src => metadata/src/writer}/tables/type_def.rs (100%) rename crates/libs/{metagen/src => metadata/src/writer}/tables/type_ref.rs (100%) rename crates/libs/{metagen/src => metadata/src/writer}/tables/type_spec.rs (100%) delete mode 100644 crates/libs/metagen/Cargo.toml delete mode 100644 crates/tests/define/Cargo.toml delete mode 100644 crates/tests/define/src/main.rs delete mode 100644 crates/tests/define/tests/test.rs create mode 100644 crates/tests/writer/Cargo.toml create mode 100644 crates/tests/writer/src/main.rs create mode 100644 crates/tests/writer/tests/test.rs diff --git a/crates/libs/bindgen/src/lib.rs b/crates/libs/bindgen/src/lib.rs index cc745b1449..d800262692 100644 --- a/crates/libs/bindgen/src/lib.rs +++ b/crates/libs/bindgen/src/lib.rs @@ -23,7 +23,7 @@ use functions::*; pub use gen::*; use helpers::*; use iterator::*; -use metadata::*; +use metadata::reader::*; use method_names::*; use methods::*; use names::*; diff --git a/crates/libs/define/Cargo.toml b/crates/libs/define/Cargo.toml deleted file mode 100644 index c3097b2a2c..0000000000 --- a/crates/libs/define/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -name = "windows-define" -version = "0.34.0" -authors = ["Microsoft"] -edition = "2018" -license = "MIT OR Apache-2.0" -description = "The define macro for the windows crate" -repository = "https://github.com/microsoft/windows-rs" - -[package.metadata.docs.rs] -default-target = "x86_64-pc-windows-msvc" -targets = [] - -[lib] -proc-macro = true - -[dependencies] diff --git a/crates/libs/define/src/lib.rs b/crates/libs/define/src/lib.rs deleted file mode 100644 index 1ed84a7250..0000000000 --- a/crates/libs/define/src/lib.rs +++ /dev/null @@ -1,7 +0,0 @@ -// The define macro should be called by a build script to define types and -// generate a corresponding OUT_DIR/crate_name.rs and OUT_DIR/crate_name.winmd - -#[proc_macro] -pub fn define(_stream: proc_macro::TokenStream) -> proc_macro::TokenStream { - proc_macro::TokenStream::new() -} diff --git a/crates/libs/metadata/src/lib.rs b/crates/libs/metadata/src/lib.rs index 3534ee8945..c9134a0edb 100644 --- a/crates/libs/metadata/src/lib.rs +++ b/crates/libs/metadata/src/lib.rs @@ -1,43 +1,2 @@ -mod array_info; -mod async_kind; -mod blob; -mod cfg; -mod codes; -mod constant_value; -mod file; -mod guid; -mod interface_kind; -mod param_flags; -mod row; -mod signature; -mod signature_kind; -mod tables; -mod traits; -mod r#type; -mod type_kind; -mod type_name; -mod type_reader; -mod type_tree; -mod workspace; - -pub use array_info::*; -pub use async_kind::*; -pub use blob::*; -pub use cfg::*; -pub use codes::*; -pub use constant_value::*; -pub use file::*; -pub use guid::*; -pub use interface_kind::*; -pub use param_flags::*; -pub use r#type::*; -pub use row::*; -pub use signature::*; -pub use signature_kind::*; -pub use tables::*; -pub use traits::*; -pub use type_kind::*; -pub use type_name::*; -pub use type_reader::*; -pub use type_tree::*; -pub use workspace::*; +pub mod reader; +pub mod writer; diff --git a/crates/libs/metadata/src/array_info.rs b/crates/libs/metadata/src/reader/array_info.rs similarity index 100% rename from crates/libs/metadata/src/array_info.rs rename to crates/libs/metadata/src/reader/array_info.rs diff --git a/crates/libs/metadata/src/async_kind.rs b/crates/libs/metadata/src/reader/async_kind.rs similarity index 100% rename from crates/libs/metadata/src/async_kind.rs rename to crates/libs/metadata/src/reader/async_kind.rs diff --git a/crates/libs/metadata/src/blob.rs b/crates/libs/metadata/src/reader/blob.rs similarity index 100% rename from crates/libs/metadata/src/blob.rs rename to crates/libs/metadata/src/reader/blob.rs diff --git a/crates/libs/metadata/src/cfg.rs b/crates/libs/metadata/src/reader/cfg.rs similarity index 100% rename from crates/libs/metadata/src/cfg.rs rename to crates/libs/metadata/src/reader/cfg.rs diff --git a/crates/libs/metadata/src/codes.rs b/crates/libs/metadata/src/reader/codes.rs similarity index 100% rename from crates/libs/metadata/src/codes.rs rename to crates/libs/metadata/src/reader/codes.rs diff --git a/crates/libs/metadata/src/constant_value.rs b/crates/libs/metadata/src/reader/constant_value.rs similarity index 100% rename from crates/libs/metadata/src/constant_value.rs rename to crates/libs/metadata/src/reader/constant_value.rs diff --git a/crates/libs/metadata/src/file.rs b/crates/libs/metadata/src/reader/file.rs similarity index 99% rename from crates/libs/metadata/src/file.rs rename to crates/libs/metadata/src/reader/file.rs index 11b6279651..fa262b92e7 100644 --- a/crates/libs/metadata/src/file.rs +++ b/crates/libs/metadata/src/reader/file.rs @@ -215,7 +215,7 @@ impl File { (first, last) } - pub fn from_bytes(name: String, bytes: Vec) -> Self { + pub(crate) fn from_bytes(name: String, bytes: Vec) -> Self { let mut file = Self { name, bytes, ..Default::default() }; let dos = file.bytes.view_as::(0); @@ -269,9 +269,6 @@ impl File { let string_index_size = if (heap_sizes & 1) == 1 { 4 } else { 2 }; let guid_index_size = if (heap_sizes >> 1 & 1) == 1 { 4 } else { 2 }; let blob_index_size = if (heap_sizes >> 2 & 1) == 1 { 4 } else { 2 }; - println!("string_index_size {}", string_index_size); - println!("guid_index_size {}", guid_index_size); - println!("blob_index_size {}", blob_index_size); let valid_bits = file.bytes.copy_as::(tables_data.0 + 8); view = tables_data.0 + 24; diff --git a/crates/libs/metadata/src/guid.rs b/crates/libs/metadata/src/reader/guid.rs similarity index 100% rename from crates/libs/metadata/src/guid.rs rename to crates/libs/metadata/src/reader/guid.rs diff --git a/crates/libs/metadata/src/interface_kind.rs b/crates/libs/metadata/src/reader/interface_kind.rs similarity index 100% rename from crates/libs/metadata/src/interface_kind.rs rename to crates/libs/metadata/src/reader/interface_kind.rs diff --git a/crates/libs/metadata/src/reader/mod.rs b/crates/libs/metadata/src/reader/mod.rs new file mode 100644 index 0000000000..3534ee8945 --- /dev/null +++ b/crates/libs/metadata/src/reader/mod.rs @@ -0,0 +1,43 @@ +mod array_info; +mod async_kind; +mod blob; +mod cfg; +mod codes; +mod constant_value; +mod file; +mod guid; +mod interface_kind; +mod param_flags; +mod row; +mod signature; +mod signature_kind; +mod tables; +mod traits; +mod r#type; +mod type_kind; +mod type_name; +mod type_reader; +mod type_tree; +mod workspace; + +pub use array_info::*; +pub use async_kind::*; +pub use blob::*; +pub use cfg::*; +pub use codes::*; +pub use constant_value::*; +pub use file::*; +pub use guid::*; +pub use interface_kind::*; +pub use param_flags::*; +pub use r#type::*; +pub use row::*; +pub use signature::*; +pub use signature_kind::*; +pub use tables::*; +pub use traits::*; +pub use type_kind::*; +pub use type_name::*; +pub use type_reader::*; +pub use type_tree::*; +pub use workspace::*; diff --git a/crates/libs/metadata/src/param_flags.rs b/crates/libs/metadata/src/reader/param_flags.rs similarity index 100% rename from crates/libs/metadata/src/param_flags.rs rename to crates/libs/metadata/src/reader/param_flags.rs diff --git a/crates/libs/metadata/src/row.rs b/crates/libs/metadata/src/reader/row.rs similarity index 100% rename from crates/libs/metadata/src/row.rs rename to crates/libs/metadata/src/reader/row.rs diff --git a/crates/libs/metadata/src/signature.rs b/crates/libs/metadata/src/reader/signature.rs similarity index 100% rename from crates/libs/metadata/src/signature.rs rename to crates/libs/metadata/src/reader/signature.rs diff --git a/crates/libs/metadata/src/signature_kind.rs b/crates/libs/metadata/src/reader/signature_kind.rs similarity index 100% rename from crates/libs/metadata/src/signature_kind.rs rename to crates/libs/metadata/src/reader/signature_kind.rs diff --git a/crates/libs/metadata/src/tables/assembly_ref.rs b/crates/libs/metadata/src/reader/tables/assembly_ref.rs similarity index 100% rename from crates/libs/metadata/src/tables/assembly_ref.rs rename to crates/libs/metadata/src/reader/tables/assembly_ref.rs diff --git a/crates/libs/metadata/src/tables/attribute.rs b/crates/libs/metadata/src/reader/tables/attribute.rs similarity index 100% rename from crates/libs/metadata/src/tables/attribute.rs rename to crates/libs/metadata/src/reader/tables/attribute.rs diff --git a/crates/libs/metadata/src/tables/class_layout.rs b/crates/libs/metadata/src/reader/tables/class_layout.rs similarity index 100% rename from crates/libs/metadata/src/tables/class_layout.rs rename to crates/libs/metadata/src/reader/tables/class_layout.rs diff --git a/crates/libs/metadata/src/tables/constant.rs b/crates/libs/metadata/src/reader/tables/constant.rs similarity index 100% rename from crates/libs/metadata/src/tables/constant.rs rename to crates/libs/metadata/src/reader/tables/constant.rs diff --git a/crates/libs/metadata/src/tables/field.rs b/crates/libs/metadata/src/reader/tables/field.rs similarity index 100% rename from crates/libs/metadata/src/tables/field.rs rename to crates/libs/metadata/src/reader/tables/field.rs diff --git a/crates/libs/metadata/src/tables/generic_param.rs b/crates/libs/metadata/src/reader/tables/generic_param.rs similarity index 100% rename from crates/libs/metadata/src/tables/generic_param.rs rename to crates/libs/metadata/src/reader/tables/generic_param.rs diff --git a/crates/libs/metadata/src/tables/impl_map.rs b/crates/libs/metadata/src/reader/tables/impl_map.rs similarity index 100% rename from crates/libs/metadata/src/tables/impl_map.rs rename to crates/libs/metadata/src/reader/tables/impl_map.rs diff --git a/crates/libs/metadata/src/tables/interface_impl.rs b/crates/libs/metadata/src/reader/tables/interface_impl.rs similarity index 100% rename from crates/libs/metadata/src/tables/interface_impl.rs rename to crates/libs/metadata/src/reader/tables/interface_impl.rs diff --git a/crates/libs/metadata/src/tables/member_ref.rs b/crates/libs/metadata/src/reader/tables/member_ref.rs similarity index 100% rename from crates/libs/metadata/src/tables/member_ref.rs rename to crates/libs/metadata/src/reader/tables/member_ref.rs diff --git a/crates/libs/metadata/src/tables/method_def.rs b/crates/libs/metadata/src/reader/tables/method_def.rs similarity index 100% rename from crates/libs/metadata/src/tables/method_def.rs rename to crates/libs/metadata/src/reader/tables/method_def.rs diff --git a/crates/libs/metadata/src/tables/mod.rs b/crates/libs/metadata/src/reader/tables/mod.rs similarity index 100% rename from crates/libs/metadata/src/tables/mod.rs rename to crates/libs/metadata/src/reader/tables/mod.rs diff --git a/crates/libs/metadata/src/tables/module_ref.rs b/crates/libs/metadata/src/reader/tables/module_ref.rs similarity index 100% rename from crates/libs/metadata/src/tables/module_ref.rs rename to crates/libs/metadata/src/reader/tables/module_ref.rs diff --git a/crates/libs/metadata/src/tables/nested_class.rs b/crates/libs/metadata/src/reader/tables/nested_class.rs similarity index 100% rename from crates/libs/metadata/src/tables/nested_class.rs rename to crates/libs/metadata/src/reader/tables/nested_class.rs diff --git a/crates/libs/metadata/src/tables/param.rs b/crates/libs/metadata/src/reader/tables/param.rs similarity index 100% rename from crates/libs/metadata/src/tables/param.rs rename to crates/libs/metadata/src/reader/tables/param.rs diff --git a/crates/libs/metadata/src/tables/type_def.rs b/crates/libs/metadata/src/reader/tables/type_def.rs similarity index 100% rename from crates/libs/metadata/src/tables/type_def.rs rename to crates/libs/metadata/src/reader/tables/type_def.rs diff --git a/crates/libs/metadata/src/tables/type_ref.rs b/crates/libs/metadata/src/reader/tables/type_ref.rs similarity index 100% rename from crates/libs/metadata/src/tables/type_ref.rs rename to crates/libs/metadata/src/reader/tables/type_ref.rs diff --git a/crates/libs/metadata/src/tables/type_spec.rs b/crates/libs/metadata/src/reader/tables/type_spec.rs similarity index 100% rename from crates/libs/metadata/src/tables/type_spec.rs rename to crates/libs/metadata/src/reader/tables/type_spec.rs diff --git a/crates/libs/metadata/src/traits.rs b/crates/libs/metadata/src/reader/traits.rs similarity index 100% rename from crates/libs/metadata/src/traits.rs rename to crates/libs/metadata/src/reader/traits.rs diff --git a/crates/libs/metadata/src/type.rs b/crates/libs/metadata/src/reader/type.rs similarity index 100% rename from crates/libs/metadata/src/type.rs rename to crates/libs/metadata/src/reader/type.rs diff --git a/crates/libs/metadata/src/type_kind.rs b/crates/libs/metadata/src/reader/type_kind.rs similarity index 100% rename from crates/libs/metadata/src/type_kind.rs rename to crates/libs/metadata/src/reader/type_kind.rs diff --git a/crates/libs/metadata/src/type_name.rs b/crates/libs/metadata/src/reader/type_name.rs similarity index 100% rename from crates/libs/metadata/src/type_name.rs rename to crates/libs/metadata/src/reader/type_name.rs diff --git a/crates/libs/metadata/src/type_reader.rs b/crates/libs/metadata/src/reader/type_reader.rs similarity index 100% rename from crates/libs/metadata/src/type_reader.rs rename to crates/libs/metadata/src/reader/type_reader.rs diff --git a/crates/libs/metadata/src/type_tree.rs b/crates/libs/metadata/src/reader/type_tree.rs similarity index 100% rename from crates/libs/metadata/src/type_tree.rs rename to crates/libs/metadata/src/reader/type_tree.rs diff --git a/crates/libs/metadata/src/workspace.rs b/crates/libs/metadata/src/reader/workspace.rs similarity index 92% rename from crates/libs/metadata/src/workspace.rs rename to crates/libs/metadata/src/reader/workspace.rs index 36b863568d..75a6d0abe2 100644 --- a/crates/libs/metadata/src/workspace.rs +++ b/crates/libs/metadata/src/reader/workspace.rs @@ -69,9 +69,9 @@ fn get_workspace_winmds() -> Vec { push_dir(&mut result, &dir); if !result.iter().any(|file| file.name.starts_with("Windows.")) { - result.push(File::from_bytes("Windows.winmd".to_string(), include_bytes!("../default/Windows.winmd").to_vec())); - result.push(File::from_bytes("Windows.Win32.winmd".to_string(), include_bytes!("../default/Windows.Win32.winmd").to_vec())); - result.push(File::from_bytes("Windows.Win32.Interop.winmd".to_string(), include_bytes!("../default/Windows.Win32.Interop.winmd").to_vec())); + result.push(File::from_bytes("Windows.winmd".to_string(), include_bytes!("../../default/Windows.winmd").to_vec())); + result.push(File::from_bytes("Windows.Win32.winmd".to_string(), include_bytes!("../../default/Windows.Win32.winmd").to_vec())); + result.push(File::from_bytes("Windows.Win32.Interop.winmd".to_string(), include_bytes!("../../default/Windows.Win32.Interop.winmd").to_vec())); } result diff --git a/crates/libs/metagen/src/blobs.rs b/crates/libs/metadata/src/writer/blobs.rs similarity index 100% rename from crates/libs/metagen/src/blobs.rs rename to crates/libs/metadata/src/writer/blobs.rs diff --git a/crates/libs/metagen/src/gen.rs b/crates/libs/metadata/src/writer/gen.rs similarity index 100% rename from crates/libs/metagen/src/gen.rs rename to crates/libs/metadata/src/writer/gen.rs diff --git a/crates/libs/metagen/src/helpers.rs b/crates/libs/metadata/src/writer/helpers.rs similarity index 100% rename from crates/libs/metagen/src/helpers.rs rename to crates/libs/metadata/src/writer/helpers.rs diff --git a/crates/libs/metagen/src/lib.rs b/crates/libs/metadata/src/writer/mod.rs similarity index 100% rename from crates/libs/metagen/src/lib.rs rename to crates/libs/metadata/src/writer/mod.rs diff --git a/crates/libs/metagen/src/pe.rs b/crates/libs/metadata/src/writer/pe.rs similarity index 100% rename from crates/libs/metagen/src/pe.rs rename to crates/libs/metadata/src/writer/pe.rs diff --git a/crates/libs/metagen/src/strings.rs b/crates/libs/metadata/src/writer/strings.rs similarity index 100% rename from crates/libs/metagen/src/strings.rs rename to crates/libs/metadata/src/writer/strings.rs diff --git a/crates/libs/metagen/src/tables/class_layout.rs b/crates/libs/metadata/src/writer/tables/class_layout.rs similarity index 100% rename from crates/libs/metagen/src/tables/class_layout.rs rename to crates/libs/metadata/src/writer/tables/class_layout.rs diff --git a/crates/libs/metagen/src/tables/constant.rs b/crates/libs/metadata/src/writer/tables/constant.rs similarity index 100% rename from crates/libs/metagen/src/tables/constant.rs rename to crates/libs/metadata/src/writer/tables/constant.rs diff --git a/crates/libs/metagen/src/tables/custom_attribute.rs b/crates/libs/metadata/src/writer/tables/custom_attribute.rs similarity index 100% rename from crates/libs/metagen/src/tables/custom_attribute.rs rename to crates/libs/metadata/src/writer/tables/custom_attribute.rs diff --git a/crates/libs/metagen/src/tables/field.rs b/crates/libs/metadata/src/writer/tables/field.rs similarity index 100% rename from crates/libs/metagen/src/tables/field.rs rename to crates/libs/metadata/src/writer/tables/field.rs diff --git a/crates/libs/metagen/src/tables/generic_param.rs b/crates/libs/metadata/src/writer/tables/generic_param.rs similarity index 100% rename from crates/libs/metagen/src/tables/generic_param.rs rename to crates/libs/metadata/src/writer/tables/generic_param.rs diff --git a/crates/libs/metagen/src/tables/impl_map.rs b/crates/libs/metadata/src/writer/tables/impl_map.rs similarity index 100% rename from crates/libs/metagen/src/tables/impl_map.rs rename to crates/libs/metadata/src/writer/tables/impl_map.rs diff --git a/crates/libs/metagen/src/tables/interface_impl.rs b/crates/libs/metadata/src/writer/tables/interface_impl.rs similarity index 100% rename from crates/libs/metagen/src/tables/interface_impl.rs rename to crates/libs/metadata/src/writer/tables/interface_impl.rs diff --git a/crates/libs/metagen/src/tables/member_ref.rs b/crates/libs/metadata/src/writer/tables/member_ref.rs similarity index 100% rename from crates/libs/metagen/src/tables/member_ref.rs rename to crates/libs/metadata/src/writer/tables/member_ref.rs diff --git a/crates/libs/metagen/src/tables/method_def.rs b/crates/libs/metadata/src/writer/tables/method_def.rs similarity index 100% rename from crates/libs/metagen/src/tables/method_def.rs rename to crates/libs/metadata/src/writer/tables/method_def.rs diff --git a/crates/libs/metagen/src/tables/mod.rs b/crates/libs/metadata/src/writer/tables/mod.rs similarity index 100% rename from crates/libs/metagen/src/tables/mod.rs rename to crates/libs/metadata/src/writer/tables/mod.rs diff --git a/crates/libs/metagen/src/tables/module.rs b/crates/libs/metadata/src/writer/tables/module.rs similarity index 100% rename from crates/libs/metagen/src/tables/module.rs rename to crates/libs/metadata/src/writer/tables/module.rs diff --git a/crates/libs/metagen/src/tables/module_ref.rs b/crates/libs/metadata/src/writer/tables/module_ref.rs similarity index 100% rename from crates/libs/metagen/src/tables/module_ref.rs rename to crates/libs/metadata/src/writer/tables/module_ref.rs diff --git a/crates/libs/metagen/src/tables/nested_class.rs b/crates/libs/metadata/src/writer/tables/nested_class.rs similarity index 100% rename from crates/libs/metagen/src/tables/nested_class.rs rename to crates/libs/metadata/src/writer/tables/nested_class.rs diff --git a/crates/libs/metagen/src/tables/param.rs b/crates/libs/metadata/src/writer/tables/param.rs similarity index 100% rename from crates/libs/metagen/src/tables/param.rs rename to crates/libs/metadata/src/writer/tables/param.rs diff --git a/crates/libs/metagen/src/tables/type_def.rs b/crates/libs/metadata/src/writer/tables/type_def.rs similarity index 100% rename from crates/libs/metagen/src/tables/type_def.rs rename to crates/libs/metadata/src/writer/tables/type_def.rs diff --git a/crates/libs/metagen/src/tables/type_ref.rs b/crates/libs/metadata/src/writer/tables/type_ref.rs similarity index 100% rename from crates/libs/metagen/src/tables/type_ref.rs rename to crates/libs/metadata/src/writer/tables/type_ref.rs diff --git a/crates/libs/metagen/src/tables/type_spec.rs b/crates/libs/metadata/src/writer/tables/type_spec.rs similarity index 100% rename from crates/libs/metagen/src/tables/type_spec.rs rename to crates/libs/metadata/src/writer/tables/type_spec.rs diff --git a/crates/libs/metagen/Cargo.toml b/crates/libs/metagen/Cargo.toml deleted file mode 100644 index d0835c8bf1..0000000000 --- a/crates/libs/metagen/Cargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "windows-metagen" -version = "0.34.0" -authors = ["Microsoft"] -edition = "2021" -license = "MIT OR Apache-2.0" -description = "Metadata generation support for the windows crate" -repository = "https://github.com/microsoft/windows-rs" diff --git a/crates/libs/windows/Cargo.toml b/crates/libs/windows/Cargo.toml index 584297609f..29e8caaabb 100644 --- a/crates/libs/windows/Cargo.toml +++ b/crates/libs/windows/Cargo.toml @@ -47,7 +47,6 @@ windows_x86_64_gnu = { path = "../../targets/x86_64_gnu", version = "0.34.0" } [dependencies] windows-implement = { path = "../implement", version = "0.34.0", optional = true } windows-interface = { path = "../interface", version = "0.34.0", optional = true } -windows-define = { path = "../define", version = "0.34.0", optional = true } [features] default = [] @@ -55,7 +54,6 @@ deprecated = [] alloc = [] implement = ["windows-implement"] interface = ["windows-interface"] -define = ["windows-define"] AI = [] AI_MachineLearning = ["AI"] AI_MachineLearning_Preview = ["AI_MachineLearning"] diff --git a/crates/libs/windows/src/core/mod.rs b/crates/libs/windows/src/core/mod.rs index 2f3a6d2de7..6bbb68e1b1 100644 --- a/crates/libs/windows/src/core/mod.rs +++ b/crates/libs/windows/src/core/mod.rs @@ -91,10 +91,6 @@ pub use windows_implement::implement; #[cfg(feature = "interface")] pub use windows_interface::interface; -#[doc(hidden)] -#[cfg(feature = "define")] -pub use windows_define::define; - extern "C" { #[doc(hidden)] pub fn memcmp(left: *const core::ffi::c_void, right: *const core::ffi::c_void, len: usize) -> i32; diff --git a/crates/tests/define/Cargo.toml b/crates/tests/define/Cargo.toml deleted file mode 100644 index 97d976f79f..0000000000 --- a/crates/tests/define/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -name = "test_define" -version = "0.0.0" -authors = ["Microsoft"] -edition = "2018" - -[dependencies.windows] -path = "../../libs/windows" -features = [ - "define", -] - -[dependencies.windows-metagen] -path = "../../libs/metagen" - -[dependencies.windows-metadata] -path = "../../libs/metadata" diff --git a/crates/tests/define/src/main.rs b/crates/tests/define/src/main.rs deleted file mode 100644 index 7f6512fb4c..0000000000 --- a/crates/tests/define/src/main.rs +++ /dev/null @@ -1,23 +0,0 @@ -use windows_metadata::*; - -fn main() { - windows_metagen::test(); - let file = windows_metadata::File::new("/git/test.winmd"); - let row_count = file.type_def_table().row_count; - for row in 0..row_count { - let def: TypeDef = Row::new(row, TableIndex::TypeDef, unsafe { &*(&file as *const _) }).into(); - let type_name = def.type_name(); - println!("{}", type_name); - for field in def.fields() { - let name = field.name(); - println!("field: {}", name); - } - - for method in def.methods() { - let name = method.name(); - println!("method: {}", name); - } - } - - //windows_metadata::File::new(r#"D:\git\windows-rs\crates\libs\metadata\default\windows.winmd"#); -} diff --git a/crates/tests/define/tests/test.rs b/crates/tests/define/tests/test.rs deleted file mode 100644 index 5db9620a37..0000000000 --- a/crates/tests/define/tests/test.rs +++ /dev/null @@ -1,22 +0,0 @@ -#[test] -fn define() { - windows::core::define! { - mod Microsoft { - mod Windows { - struct StructType { x: i32, y: i32 } - - interface IInterfaceType { - fn Method(&self) -> StructType; - } - - class ClassType : IInterfaceType; - } - } - } -} - -#[test] -fn metagen() { - windows_metagen::test(); - windows_metadata::File::new("/git/test.winmd"); -} diff --git a/crates/tests/writer/Cargo.toml b/crates/tests/writer/Cargo.toml new file mode 100644 index 0000000000..06eff24f3b --- /dev/null +++ b/crates/tests/writer/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "test_writer" +version = "0.0.0" +authors = ["Microsoft"] +edition = "2018" + +[dependencies.windows-metadata] +path = "../../libs/metadata" diff --git a/crates/tests/writer/src/main.rs b/crates/tests/writer/src/main.rs new file mode 100644 index 0000000000..d11f6952af --- /dev/null +++ b/crates/tests/writer/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + windows_metagen::writer::test(); +} diff --git a/crates/tests/writer/tests/test.rs b/crates/tests/writer/tests/test.rs new file mode 100644 index 0000000000..c3238855c1 --- /dev/null +++ b/crates/tests/writer/tests/test.rs @@ -0,0 +1,4 @@ +#[test] +fn metagen() { + windows_metagen::writer::test(); +} diff --git a/crates/tools/gnu/src/main.rs b/crates/tools/gnu/src/main.rs index b5340e7ff4..fdc5670f25 100644 --- a/crates/tools/gnu/src/main.rs +++ b/crates/tools/gnu/src/main.rs @@ -1,4 +1,4 @@ -use metadata::*; +use metadata::reader::*; use std::collections::BTreeMap; use std::io::prelude::*; diff --git a/crates/tools/ilrs/Cargo.toml b/crates/tools/ilrs/Cargo.toml index 14eb59b31f..e47e5a9630 100644 --- a/crates/tools/ilrs/Cargo.toml +++ b/crates/tools/ilrs/Cargo.toml @@ -5,4 +5,4 @@ edition = "2018" publish = false [dependencies] -metagen = { package = "windows-metagen", path = "../../libs/metagen", version = "0.34.0" } +metadata = { package = "windows-metadata", path = "../../libs/metadata", version = "0.34.0" } diff --git a/crates/tools/ilrs/src/main.rs b/crates/tools/ilrs/src/main.rs index f421f89465..acbdbd55f3 100644 --- a/crates/tools/ilrs/src/main.rs +++ b/crates/tools/ilrs/src/main.rs @@ -1,7 +1,7 @@ use std::env::*; fn main() { - let mut gen = metagen::Gen::new(); + let mut gen = metadata::writer::Gen::new(); let mut kind = ArgKind::None; for arg in args() { @@ -30,7 +30,7 @@ fn main() { return print_help(); } - let _ = metagen::gen(&gen); + let _ = metadata::writer::gen(&gen); // TODO: print error report } diff --git a/crates/tools/msvc/src/main.rs b/crates/tools/msvc/src/main.rs index ee22b8d9ba..9bfd1dd097 100644 --- a/crates/tools/msvc/src/main.rs +++ b/crates/tools/msvc/src/main.rs @@ -1,4 +1,4 @@ -use metadata::*; +use metadata::reader::*; use std::collections::BTreeMap; use std::io::prelude::*; diff --git a/crates/tools/sys/src/main.rs b/crates/tools/sys/src/main.rs index eaf2b1a7e6..492caeca16 100644 --- a/crates/tools/sys/src/main.rs +++ b/crates/tools/sys/src/main.rs @@ -1,5 +1,6 @@ use rayon::prelude::*; use std::io::prelude::*; +use metadata::reader::*; const EXCLUDE_NAMESPACES: [&str; 1] = ["Windows.Win32.Interop"]; @@ -8,7 +9,7 @@ fn main() { let _ = std::fs::remove_dir_all(&output); output.pop(); - let reader = metadata::TypeReader::get(); + let reader = TypeReader::get(); let root = reader.types.get_namespace("Windows").unwrap(); let mut trees = Vec::new(); @@ -92,7 +93,7 @@ deprecated = [] std::fs::copy(".github/license-apache", "crates/libs/sys/license-apache").unwrap(); } -fn collect_trees<'a>(output: &std::path::Path, tree: &'a metadata::TypeTree, trees: &mut Vec<&'a metadata::TypeTree>) { +fn collect_trees<'a>(output: &std::path::Path, tree: &'a TypeTree, trees: &mut Vec<&'a TypeTree>) { if EXCLUDE_NAMESPACES.iter().any(|&x| x == tree.namespace) { return; } @@ -104,7 +105,7 @@ fn collect_trees<'a>(output: &std::path::Path, tree: &'a metadata::TypeTree, tre std::fs::create_dir_all(&path).unwrap(); } -fn gen_tree(output: &std::path::Path, _root: &'static str, tree: &metadata::TypeTree) { +fn gen_tree(output: &std::path::Path, _root: &'static str, tree: &TypeTree) { let mut path = std::path::PathBuf::from(output); path.push(tree.namespace.replace('.', "/")); diff --git a/crates/tools/windows/src/main.rs b/crates/tools/windows/src/main.rs index 73628303d3..a663d9a475 100644 --- a/crates/tools/windows/src/main.rs +++ b/crates/tools/windows/src/main.rs @@ -1,5 +1,6 @@ use rayon::prelude::*; use std::io::prelude::*; +use metadata::reader::*; const EXCLUDE_NAMESPACES: [&str; 1] = ["Windows.Win32.Interop"]; @@ -8,7 +9,7 @@ fn main() { let _ = std::fs::remove_dir_all(&output); output.pop(); - let reader = metadata::TypeReader::get(); + let reader = TypeReader::get(); let root = reader.types.get_namespace("Windows").unwrap(); let mut trees = Vec::new(); @@ -70,7 +71,6 @@ windows_x86_64_gnu = { path = "../../targets/x86_64_gnu", version = "0.34.0" } [dependencies] windows-implement = { path = "../implement", version = "0.34.0", optional = true } windows-interface = { path = "../interface", version = "0.34.0", optional = true } -windows-define = { path = "../define", version = "0.34.0", optional = true } [features] default = [] @@ -78,7 +78,6 @@ deprecated = [] alloc = [] implement = ["windows-implement"] interface = ["windows-interface"] -define = ["windows-define"] "# .as_bytes(), ) @@ -101,7 +100,7 @@ define = ["windows-define"] std::fs::copy(".github/license-apache", "crates/libs/windows/license-apache").unwrap(); } -fn collect_trees<'a>(output: &std::path::Path, tree: &'a metadata::TypeTree, trees: &mut Vec<&'a metadata::TypeTree>) { +fn collect_trees<'a>(output: &std::path::Path, tree: &'a TypeTree, trees: &mut Vec<&'a TypeTree>) { if EXCLUDE_NAMESPACES.iter().any(|&x| x == tree.namespace) { return; } @@ -113,7 +112,7 @@ fn collect_trees<'a>(output: &std::path::Path, tree: &'a metadata::TypeTree, tre std::fs::create_dir_all(&path).unwrap(); } -fn gen_tree(output: &std::path::Path, _root: &'static str, tree: &metadata::TypeTree) { +fn gen_tree(output: &std::path::Path, _root: &'static str, tree: &TypeTree) { println!("{}", tree.namespace); let path = std::path::PathBuf::from(output).join(tree.namespace.replace('.', "/")); diff --git a/crates/tools/yml/src/main.rs b/crates/tools/yml/src/main.rs index eba08f9c42..213b887721 100644 --- a/crates/tools/yml/src/main.rs +++ b/crates/tools/yml/src/main.rs @@ -4,7 +4,7 @@ fn main() { } fn test_yml() { - let root = std::path::PathBuf::from(metadata::workspace_dir()); + let root = std::path::PathBuf::from(metadata::reader::workspace_dir()); let mut yml = r#"name: Test on: @@ -124,7 +124,7 @@ jobs: } fn build_yml() { - let root = std::path::PathBuf::from(metadata::workspace_dir()); + let root = std::path::PathBuf::from(metadata::reader::workspace_dir()); let mut yml = r#"name: Build on: From 2a620016b06b72ef4d7bfc9fd69657f9fbc34fee Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Thu, 24 Mar 2022 15:28:41 -0700 Subject: [PATCH 49/55] fmt --- crates/tools/sys/src/main.rs | 2 +- crates/tools/windows/src/main.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/tools/sys/src/main.rs b/crates/tools/sys/src/main.rs index 492caeca16..921ab7c77d 100644 --- a/crates/tools/sys/src/main.rs +++ b/crates/tools/sys/src/main.rs @@ -1,6 +1,6 @@ +use metadata::reader::*; use rayon::prelude::*; use std::io::prelude::*; -use metadata::reader::*; const EXCLUDE_NAMESPACES: [&str; 1] = ["Windows.Win32.Interop"]; diff --git a/crates/tools/windows/src/main.rs b/crates/tools/windows/src/main.rs index a663d9a475..d7726a2738 100644 --- a/crates/tools/windows/src/main.rs +++ b/crates/tools/windows/src/main.rs @@ -1,6 +1,6 @@ +use metadata::reader::*; use rayon::prelude::*; use std::io::prelude::*; -use metadata::reader::*; const EXCLUDE_NAMESPACES: [&str; 1] = ["Windows.Win32.Interop"]; From c90bbf4ba614d7f8bd89f7354ba10b02ba10bade Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Thu, 24 Mar 2022 15:29:32 -0700 Subject: [PATCH 50/55] test --- crates/tests/writer/src/main.rs | 2 +- crates/tests/writer/tests/test.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/tests/writer/src/main.rs b/crates/tests/writer/src/main.rs index d11f6952af..67550a40e5 100644 --- a/crates/tests/writer/src/main.rs +++ b/crates/tests/writer/src/main.rs @@ -1,3 +1,3 @@ fn main() { - windows_metagen::writer::test(); + windows_metadata::writer::test(); } diff --git a/crates/tests/writer/tests/test.rs b/crates/tests/writer/tests/test.rs index c3238855c1..dad2a5822a 100644 --- a/crates/tests/writer/tests/test.rs +++ b/crates/tests/writer/tests/test.rs @@ -1,4 +1,4 @@ #[test] fn metagen() { - windows_metagen::writer::test(); + windows_metadata::writer::test(); } From 4b6eacc7e2d999e9c938c8de34d871c1089e3c56 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Thu, 24 Mar 2022 15:32:21 -0700 Subject: [PATCH 51/55] comments --- crates/libs/metadata/src/writer/mod.rs | 2 -- crates/libs/metadata/src/writer/pe.rs | 2 -- 2 files changed, 4 deletions(-) diff --git a/crates/libs/metadata/src/writer/mod.rs b/crates/libs/metadata/src/writer/mod.rs index 254dc69f48..49ca0b7ab5 100644 --- a/crates/libs/metadata/src/writer/mod.rs +++ b/crates/libs/metadata/src/writer/mod.rs @@ -1,5 +1,3 @@ -// https://docs.microsoft.com/en-us/windows/win32/debug/pe-format - mod blobs; mod gen; mod helpers; diff --git a/crates/libs/metadata/src/writer/pe.rs b/crates/libs/metadata/src/writer/pe.rs index 6d0667e9ed..a8bbb51d8b 100644 --- a/crates/libs/metadata/src/writer/pe.rs +++ b/crates/libs/metadata/src/writer/pe.rs @@ -1,5 +1,3 @@ -// https://docs.microsoft.com/en-us/windows/win32/debug/pe-format - use super::*; use std::mem::*; From adff14e887f8baf69ea3096eee43808d0e2d6e61 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Thu, 24 Mar 2022 15:33:57 -0700 Subject: [PATCH 52/55] usize --- usize | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 usize diff --git a/usize b/usize deleted file mode 100644 index e69de29bb2..0000000000 From efa7c4401f3aef7fd02ce43ccfd5b1a201d530ef Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Thu, 24 Mar 2022 15:45:10 -0700 Subject: [PATCH 53/55] yml --- .github/workflows/build.yml | 2 ++ .github/workflows/test.yml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8a22186dae..9be8e7f3c9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -145,8 +145,10 @@ jobs: cargo clippy -p test_weak_ref && cargo clippy -p test_win32 && cargo clippy -p test_win32_arrays && + cargo clippy -p test_writer && cargo clippy -p tool_bindings && cargo clippy -p tool_gnu && + cargo clippy -p tool_ilrs && cargo clippy -p tool_msvc && cargo clippy -p tool_sys && cargo clippy -p tool_windows && diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b6db49e741..2bb3b6592a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -100,8 +100,10 @@ jobs: cargo test --target ${{ matrix.target }} -p test_weak_ref && cargo test --target ${{ matrix.target }} -p test_win32 && cargo test --target ${{ matrix.target }} -p test_win32_arrays && + cargo test --target ${{ matrix.target }} -p test_writer && cargo test --target ${{ matrix.target }} -p tool_bindings && cargo test --target ${{ matrix.target }} -p tool_gnu && + cargo test --target ${{ matrix.target }} -p tool_ilrs && cargo test --target ${{ matrix.target }} -p tool_msvc && cargo test --target ${{ matrix.target }} -p tool_sys && cargo test --target ${{ matrix.target }} -p tool_windows && From c15ede5663d6f6a5b66ffa3ab870ab7288cab14f Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Thu, 24 Mar 2022 15:57:02 -0700 Subject: [PATCH 54/55] test --- crates/tests/writer/tests/test.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/tests/writer/tests/test.rs b/crates/tests/writer/tests/test.rs index dad2a5822a..ca4a06a17a 100644 --- a/crates/tests/writer/tests/test.rs +++ b/crates/tests/writer/tests/test.rs @@ -1,4 +1,4 @@ #[test] fn metagen() { - windows_metadata::writer::test(); + // windows_metadata::writer::test(); } From c27af5f829ee6dc954ef179062fbbbc96886e5d8 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Thu, 24 Mar 2022 16:49:36 -0700 Subject: [PATCH 55/55] build --- crates/tools/ilrs/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/tools/ilrs/Cargo.toml b/crates/tools/ilrs/Cargo.toml index e47e5a9630..38f1ce6cfa 100644 --- a/crates/tools/ilrs/Cargo.toml +++ b/crates/tools/ilrs/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "ilrs" +name = "tool_ilrs" version = "0.0.0" edition = "2018" publish = false