# This file is part of Mach-O Loader for CLE.
# Contributed December 2016 by Fraunhofer SIT (https://www.sit.fraunhofer.de/en/).
from typing import Optional
from cle.backends.region import Section
from .segment import MachOSegment
TYPE_MASK = 0x000000FF
ATTRIBUTES_MASK = 0xFFFFFF00
[docs]class MachOSection(Section):
"""
Mach-O Section, only defined within the context of a Mach-O Segment.
- offset is the offset into the file the region starts
- vaddr (or just addr) is the virtual address
- filesize (or just size) is the size of the region in the file
- memsize (or vsize) is the size of the region when loaded into memory
- segname is the corresponding segment's name without padding
- sectname is the section's name without padding
- align is the sections alignment as a power of 2
- reloff is the file offset to the section's relocation entries
- nreloc is the number of relocation entries for this section
- flags is a bit vector containing per-section flags
- r1 and r2 are values for the reserved1 and reserved2 fields respectively
"""
[docs] def __init__(
self,
offset,
vaddr,
size,
vsize,
segname,
sectname,
align,
reloff,
nreloc,
flags,
r1,
r2,
parent_segment: Optional[MachOSegment] = None,
):
super().__init__(sectname.decode(), offset, vaddr, size)
self.filesize = size
self.memsize = vsize
self.segname = segname.decode()
self.sectname = sectname.decode()
self.align = align
self.reloff = reloff
self.nreloc = nreloc
self.flags = flags
self.reserved1 = r1
self.reserved2 = r2
self.parent_segment = parent_segment
@property
def type(self):
return self.flags & TYPE_MASK
@property
def attributes(self):
return self.flags & ATTRIBUTES_MASK
@property
def is_readable(self):
"""
Always true, because sections should always be readable
:return:
"""
return True
@property
def is_writable(self):
"""
Returns the permission of the parent segment, because MachO sections simply inherit that
:return:
"""
return self.parent_segment.is_writable
@property
def is_executable(self):
"""
Returns the permission of the parent segment, because MachO sections simply inherit that
:return:
"""
return self.parent_segment.is_executable
@property
def only_contains_uninitialized_data(self):
"""
I actually don't know if this is true, but it seems like a saner assumption than true
:return:
"""
return False
def __repr__(self):
return "<Section: {} (part of Segment: {})| offset {:#x}, vaddr {:#x}, size {:#x}>".format(
self.sectname if self.sectname else "Unnamed", self.segname, self.offset, self.vaddr, self.memsize
)