///|
/// The exception directory (slot 3).
///
/// On x64 and ARM64 this is a table of `IMAGE_RUNTIME_FUNCTION_ENTRY` records
/// (12 bytes: begin RVA, end RVA, unwind-info RVA). Its entry count is a good
/// proxy for "how much unwind information this image carries", and the same
/// table is what a debugger consults to walk a stack.
///|
pub(all) struct FunctionTable {
entries : Int32
first_rva : Int32
last_rva : Int32
} derive(@debug.Debug)
///|
/// Read the runtime-function table, if the image has one.
pub fn Pe::function_table(self : Pe) -> FunctionTable? raise PeError {
let directory = match self.directory(3) {
None => return None
Some(directory) => directory
}
if directory.virtual_address == 0 || directory.size == 0 {
return None
}
let entries = directory.size / 12
if entries == 0 {
return None
}
let reader = match self.reader_at_rva(directory.virtual_address) {
Some(reader) => reader
None =>
raise PeError::Malformed(
"exception directory RVA " +
hex(directory.virtual_address) +
" is not backed by file bytes",
0,
)
}
let mut first = 0
let mut last = 0
let mut i = 0
while i < entries {
let begin = reader.u32()
let end = reader.u32()
reader.skip(4)
if i == 0 {
first = begin
}
if end > last {
last = end
}
i = i + 1
}
Some({ entries, first_rva: first, last_rva: last, })
}