-
Notifications
You must be signed in to change notification settings - Fork 495
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Basic metadata generation #1820
Changes from all commits
89cf3ad
928588c
49fc829
dab1f1a
470adf7
01c5023
21d6c9a
f9855ee
131a2d4
8e886ad
8625eef
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,45 @@ | ||||||||||||||||||||||
#[repr(C)] | ||||||||||||||||||||||
#[derive(Default)] | ||||||||||||||||||||||
pub struct METADATA_HEADER { | ||||||||||||||||||||||
pub signature: u32, | ||||||||||||||||||||||
pub major_version: u16, | ||||||||||||||||||||||
pub minor_version: u16, | ||||||||||||||||||||||
pub reserved: u32, | ||||||||||||||||||||||
pub length: u32, | ||||||||||||||||||||||
pub version: [u8; 20], | ||||||||||||||||||||||
pub flags: u16, | ||||||||||||||||||||||
pub streams: u16, | ||||||||||||||||||||||
} | ||||||||||||||||||||||
|
||||||||||||||||||||||
pub const METADATA_SIGNATURE: u32 = 0x424A_5342; | ||||||||||||||||||||||
|
||||||||||||||||||||||
extern "C" { | ||||||||||||||||||||||
pub fn strlen(cs: *const u8) -> usize; | ||||||||||||||||||||||
} | ||||||||||||||||||||||
|
||||||||||||||||||||||
pub fn composite_index_size(tables: &[usize]) -> usize { | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I know this function requires a deep understanding of the metadata file format, but I do think some small comments could make this much easier to understand. |
||||||||||||||||||||||
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; | ||||||||||||||||||||||
} | ||||||||||||||||||||||
Comment on lines
+28
to
+34
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. wow that's cool |
||||||||||||||||||||||
bits | ||||||||||||||||||||||
} | ||||||||||||||||||||||
|
||||||||||||||||||||||
let bits_needed = bits_needed(tables.len()); | ||||||||||||||||||||||
|
||||||||||||||||||||||
if tables.iter().all(|table| small(*table, bits_needed)) { | ||||||||||||||||||||||
2 | ||||||||||||||||||||||
} else { | ||||||||||||||||||||||
4 | ||||||||||||||||||||||
} | ||||||||||||||||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,55 +1,13 @@ | ||
#![allow(dead_code)] | ||
|
||
use std::collections::*; | ||
mod flags; | ||
mod imp; | ||
pub mod reader; | ||
pub mod writer; | ||
|
||
pub use flags::*; | ||
use imp::*; | ||
use std::io::*; | ||
use std::mem::*; | ||
use std::ptr::*; | ||
|
||
#[repr(C)] | ||
#[derive(Default)] | ||
struct METADATA_HEADER { | ||
signature: u32, | ||
major_version: u16, | ||
minor_version: u16, | ||
reserved: u32, | ||
length: u32, | ||
version: [u8; 20], | ||
flags: u16, | ||
streams: u16, | ||
} | ||
|
||
const METADATA_SIGNATURE: u32 = 0x424A_5342; | ||
|
||
extern "C" { | ||
fn strlen(cs: *const u8) -> usize; | ||
} | ||
|
||
fn composite_index_size(tables: &[usize]) -> usize { | ||
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(|table| small(*table, bits_needed)) { | ||
2 | ||
} else { | ||
4 | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
#[derive(Clone, Copy)] | ||
pub enum ResolutionScope { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems like it would benefit from a short doc about what it's used for. |
||
None, | ||
Module(usize), | ||
ModuleRef(usize), | ||
AssemblyRef(usize), | ||
TypeRef(usize), | ||
} | ||
|
||
impl ResolutionScope { | ||
pub fn encode(&self) -> usize { | ||
match self { | ||
Self::Module(row) => ((row + 1) << 2), | ||
Self::ModuleRef(row) => ((row + 1) << 2) + 1, | ||
Self::AssemblyRef(row) => ((row + 1) << 2) + 2, | ||
Self::TypeRef(row) => ((row + 1) << 2) + 3, | ||
_ => unimplemented!(), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this unimplemented or merely unexpected? Using a |
||
} | ||
} | ||
} | ||
|
||
impl Default for ResolutionScope { | ||
fn default() -> Self { | ||
Self::None | ||
} | ||
} | ||
|
||
#[derive(Clone, Copy)] | ||
pub enum TypeDefOrRef { | ||
None, | ||
TypeDef(usize), | ||
TypeRef(usize), | ||
TypeSpec(usize), | ||
} | ||
|
||
impl TypeDefOrRef { | ||
pub fn encode(&self) -> usize { | ||
match self { | ||
Self::TypeDef(row) => ((row + 1) << 2), | ||
Self::TypeRef(row) => ((row + 1) << 2) + 1, | ||
Self::TypeSpec(row) => ((row + 1) << 2) + 2, | ||
_ => 0, | ||
} | ||
} | ||
} | ||
|
||
impl Default for TypeDefOrRef { | ||
fn default() -> Self { | ||
Self::None | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,29 +1,17 @@ | ||
mod blobs; | ||
mod codes; | ||
mod gen; | ||
mod helpers; | ||
mod pe; | ||
pub mod pe; | ||
mod strings; | ||
mod tables; | ||
use blobs::*; | ||
mod type_name; | ||
|
||
use super::*; | ||
use blobs::*; | ||
use codes::*; | ||
pub use gen::*; | ||
use helpers::*; | ||
pub use helpers::*; | ||
use strings::*; | ||
use tables::*; | ||
|
||
pub fn test() { | ||
let mut tables = Tables::new(); | ||
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); | ||
} | ||
pub use tables::*; | ||
pub use type_name::*; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the difference between
gen.reader.type_def_has_explicit_layout(def)
andgen.reader.type_def_flags(def).explicit_layout()
. If they're equivalent, could we stick with using just one?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
explicit_layout
flag just checks the bit in theTypeDef
record. Thetype_def_has_explicit_layout
is a much more comprehensive inspection that checks not only theTypeDef
itself, but also its fields recursively, and also any otherTypeDef
s of the same type but for different architectures. The latter depends on the former.