///|
pub fn PEImage::tls(self : Self) -> TlsInfo? raise PeError {
let directory = match self.directory(9) {
Some(directory) if directory.virtual_address != 0UL && directory.size > 0 =>
directory
_ => return None
}
let offset = self.rva_to_offset(directory.virtual_address)
let minimum_size = if self.is_64_bit() { 40 } else { 24 }
ensure_range(self.data, offset, minimum_size)
let pointer_size = if self.is_64_bit() { 8 } else { 4 }
let raw_start = self.read_pointer(offset)
let raw_end = self.read_pointer(offset + pointer_size)
let index_address = self.read_pointer(offset + pointer_size * 2)
let callbacks_address = self.read_pointer(offset + pointer_size * 3)
let size_offset = offset + pointer_size * 4
let size_of_zero_fill = checked_int(
read_u32(self.data, size_offset),
size_offset,
"TLS zero-fill size",
)
let characteristics = checked_int(
read_u32(self.data, size_offset + 4),
size_offset + 4,
"TLS characteristics",
)
let callbacks = []
if callbacks_address != 0UL {
match self.va_to_rva(callbacks_address) {
Some(callback_rva) => {
let callback_offset = self.rva_to_offset(callback_rva)
let mut index = 0
while index < 128 {
let entry_offset = callback_offset + index * pointer_size
if entry_offset + pointer_size > self.data.length() {
break
}
let callback = self.read_pointer(entry_offset)
if callback == 0UL {
break
}
callbacks.push(callback)
index = index + 1
}
}
None => ()
}
}
Some({
raw_data_start: raw_start,
raw_data_end: raw_end,
index_address,
callbacks_address,
size_of_zero_fill,
characteristics,
callbacks,
})
}
///|
fn PEImage::read_pointer(self : Self, offset : Int32) -> UInt64 raise PeError {
if self.is_64_bit() {
read_u64(self.data, offset)
} else {
read_u32(self.data, offset)
}
}