///|
pub fn PEImage::exports(self : Self) -> Array[ExportSymbol] raise PeError {
let directory = match self.directory(0) {
Some(directory) if directory.virtual_address != 0UL && directory.size > 0 =>
directory
_ => return []
}
let offset = self.rva_to_offset(directory.virtual_address)
ensure_range(self.data, offset, 40)
let name_rva = read_u32(self.data, offset + 12)
let ordinal_base = read_u32(self.data, offset + 16)
let number_of_functions = read_u32(self.data, offset + 20)
let number_of_names = read_u32(self.data, offset + 24)
let functions_rva = read_u32(self.data, offset + 28)
let names_rva = read_u32(self.data, offset + 32)
let ordinals_rva = read_u32(self.data, offset + 36)
if name_rva == 0UL || number_of_names == 0UL || number_of_functions == 0UL {
return []
}
let name_limit = if number_of_names < 8192UL {
number_of_names.to_int()
} else {
8192
}
let function_limit = if number_of_functions < 65536UL {
number_of_functions.to_int()
} else {
65536
}
let names_offset = self.rva_to_offset(names_rva)
let ordinals_offset = self.rva_to_offset(ordinals_rva)
let functions_offset = self.rva_to_offset(functions_rva)
ensure_range(self.data, names_offset, name_limit * 4)
ensure_range(self.data, ordinals_offset, name_limit * 2)
ensure_range(self.data, functions_offset, function_limit * 4)
let exports = []
for index in 0..= function_limit {
continue
}
let function_rva = read_u32(self.data, functions_offset + ordinal_index * 4)
if function_rva == 0UL {
continue
}
let symbol_name = self.read_c_string(symbol_name_rva, 4096)
let forwarder = if function_rva >= directory.virtual_address &&
function_rva < directory.virtual_address + directory.size.to_uint64() {
Some(self.read_c_string(function_rva, 4096))
} else {
None
}
exports.push({
name: symbol_name,
ordinal: ordinal_base.to_int() + ordinal_index,
rva: function_rva,
forwarder,
})
}
exports
}