///|
/// Names and resolution state for the 16 data directories.
///
/// The optional header only stores an RVA and a size per slot. Naming them and
/// reporting whether the range actually maps to file bytes turns "there are 16
/// numbers" into something a caller can act on.
///|
pub fn directory_name(index : Int32) -> String {
match index {
0 => "Export"
1 => "Import"
2 => "Resource"
3 => "Exception"
4 => "Security"
5 => "BaseReloc"
6 => "Debug"
7 => "Architecture"
8 => "GlobalPtr"
9 => "TLS"
10 => "LoadConfig"
11 => "BoundImport"
12 => "IAT"
13 => "DelayImport"
14 => "CLR"
_ => "Reserved"
}
}
///|
/// One data directory together with its name and file mapping.
pub(all) struct ResolvedDirectory {
index : Int32
name : String
virtual_address : Int32
size : Int32
// `None` when the directory is empty or its RVA is not backed by file bytes.
file_offset : Int32?
} derive(@debug.Debug)
///|
/// Every declared data directory, in slot order.
pub fn Pe::resolved_directories(self : Pe) -> Array[ResolvedDirectory] {
let out : Array[ResolvedDirectory] = []
for directory in self.optional.directories {
let file_offset = if directory.virtual_address == 0 || directory.size == 0 {
None
} else {
self.rva_to_offset(directory.virtual_address)
}
out.push({
index: directory.index,
name: directory_name(directory.index),
virtual_address: directory.virtual_address,
size: directory.size,
file_offset,
})
}
out
}