///|
/// One entry of the section table.
///
/// `virtual_size` is how much memory the section occupies; `raw_size` is how
/// many bytes are actually stored in the file. The two differ for the `.bss`
/// tail of a section, where the loader zero-fills the remainder. Code that maps
/// an RVA to a file offset must use the larger of the two for the span and reject
/// offsets inside the zero-filled tail.
///|
pub(all) struct Section {
name : String
virtual_size : Int32
virtual_address : Int32
raw_size : Int32
raw_pointer : Int32
characteristics : Int32
} derive(@debug.Debug)
///|
/// `IMAGE_SCN_MEM_EXECUTE`.
pub fn Section::is_executable(self : Section) -> Bool {
has_flag(self.characteristics, 0x20000000)
}
///|
/// `IMAGE_SCN_MEM_READ`.
pub fn Section::is_readable(self : Section) -> Bool {
has_flag(self.characteristics, 0x40000000)
}
///|
/// `IMAGE_SCN_MEM_WRITE`.
pub fn Section::is_writable(self : Section) -> Bool {
(self.characteristics.to_int64() & 0x80000000) != 0
}
///|
/// A short `rwx` rendering of the section permissions, the way `objdump`
/// prints them. A section that is both writable and executable deserves a
/// second look, which is why `w` and `x` are shown together rather than
/// collapsed into a single "flags" number.
pub fn Section::permissions(self : Section) -> String {
let sb = StringBuilder()
if self.is_readable() {
sb.write_char('r')
} else {
sb.write_char('-')
}
if self.is_writable() {
sb.write_char('w')
} else {
sb.write_char('-')
}
if self.is_executable() {
sb.write_char('x')
} else {
sb.write_char('-')
}
sb.to_string()
}