mirror of
https://github.com/qilingframework/qiling.git
synced 2026-10-12 02:21:40 +00:00
Change is_mapped semantics
This commit is contained in:
@@ -4,7 +4,7 @@ from abc import abstractmethod
|
||||
from qiling import Qiling
|
||||
from qiling.arch.x86 import QlArchIntel
|
||||
from qiling.arch.x86_const import *
|
||||
from qiling.exception import QlGDTError
|
||||
from qiling.exception import QlGDTError, QlMemoryMappedError
|
||||
from qiling.os.memory import QlMemoryManager
|
||||
|
||||
class GDTArray:
|
||||
@@ -50,8 +50,10 @@ class GDTManager:
|
||||
def __init__(self, ql: Qiling, base = QL_X86_GDT_ADDR, limit = QL_X86_GDT_LIMIT, num_entries = 16):
|
||||
ql.log.debug(f'Mapping GDT at {base:#x} with limit {limit:#x}')
|
||||
|
||||
if not ql.mem.is_mapped(base, limit):
|
||||
ql.mem.map(base, limit, info="[GDT]")
|
||||
if not ql.mem.is_available(base, limit):
|
||||
raise QlMemoryMappedError('cannot map GDT, memory location is taken')
|
||||
|
||||
ql.mem.map(base, limit, info="[GDT]")
|
||||
|
||||
# setup GDT by writing to GDTR
|
||||
ql.arch.regs.write(UC_X86_REG_GDTR, (0, base, limit, 0x0))
|
||||
|
||||
@@ -368,7 +368,7 @@ class QlLoaderELF(QlLoader):
|
||||
_vsyscall_addr = int(self.profile.get('vsyscall_address'), 0)
|
||||
_vsyscall_size = int(self.profile.get('vsyscall_size'), 0)
|
||||
|
||||
if not self.ql.mem.is_mapped(_vsyscall_addr, _vsyscall_size):
|
||||
if self.ql.mem.is_available(_vsyscall_addr, _vsyscall_size):
|
||||
# initialize with int3 instructions then insert syscall entry
|
||||
# each syscall should be 1KiB away
|
||||
self.ql.mem.map(_vsyscall_addr, _vsyscall_size, info="[vsyscall]")
|
||||
|
||||
+36
-6
@@ -280,7 +280,7 @@ class QlMemoryManager:
|
||||
self.ql.log.debug(f'restoring memory range: {lbound:#08x} {ubound:#08x} {label}')
|
||||
|
||||
size = ubound - lbound
|
||||
if not self.is_mapped(lbound, size):
|
||||
if self.is_available(lbound, size):
|
||||
self.ql.log.debug(f'mapping {lbound:#08x} {ubound:#08x}, mapsize = {size:#x}')
|
||||
self.map(lbound, size, perms, label)
|
||||
|
||||
@@ -420,9 +420,34 @@ class QlMemoryManager:
|
||||
for begin, end, _ in self.ql.uc.mem_regions():
|
||||
self.unmap(begin, end - begin + 1)
|
||||
|
||||
def __mapped_regions(self) -> Iterator[Tuple[int, int]]:
|
||||
"""Iterate through all mapped memory regions, consolidating adjacent regions
|
||||
together to a continuous one. Protection bits and labels are ignored.
|
||||
"""
|
||||
|
||||
if not self.map_info:
|
||||
return
|
||||
|
||||
iter_memmap = iter(self.map_info)
|
||||
|
||||
p_lbound, p_ubound, _, _, _ = next(iter_memmap)
|
||||
|
||||
# map_info is assumed to contain non-overlapping regions sorted by lbound
|
||||
for lbound, ubound, _, _, _ in iter_memmap:
|
||||
if lbound == p_ubound:
|
||||
p_ubound = ubound
|
||||
else:
|
||||
yield (p_lbound, p_ubound)
|
||||
|
||||
p_lbound = lbound
|
||||
p_ubound = ubound
|
||||
|
||||
yield (p_lbound, p_ubound)
|
||||
|
||||
|
||||
def is_available(self, addr: int, size: int) -> bool:
|
||||
"""Query whether the memory range starting at `addr` and is of length of `size` bytes
|
||||
can be allocated.
|
||||
is available for allocation.
|
||||
|
||||
Returns: True if it can be allocated, False otherwise
|
||||
"""
|
||||
@@ -433,16 +458,21 @@ class QlMemoryManager:
|
||||
end = addr + size
|
||||
|
||||
# make sure neither begin nor end are enclosed within a mapped range, or entirely enclosing one
|
||||
return not any((lbound <= begin < ubound) or (lbound < end <= ubound) or (begin <= lbound < ubound <= end) for lbound, ubound, _, _, _ in self.map_info)
|
||||
return not any((lbound <= begin < ubound) or (lbound < end <= ubound) or (begin <= lbound < ubound <= end) for lbound, ubound in self.__mapped_regions())
|
||||
|
||||
def is_mapped(self, addr: int, size: int) -> bool:
|
||||
"""Query whether the memory range starting at `addr` and is of length of `size` bytes
|
||||
is mapped, either partially or entirely.
|
||||
is fully mapped.
|
||||
|
||||
Returns: True if any part of the specified memory range is taken, False otherwise
|
||||
Returns: True if the specified memory range is taken fully, False otherwise
|
||||
"""
|
||||
|
||||
return not self.is_available(addr, size)
|
||||
assert size > 0, 'expected a positive size value'
|
||||
|
||||
begin = addr
|
||||
end = addr + size
|
||||
|
||||
return any((lbound <= begin < end <= ubound) for lbound, ubound in self.__mapped_regions())
|
||||
|
||||
def find_free_space(self, size: int, minaddr: int = None, maxaddr: int = None, align: int = None) -> int:
|
||||
"""Locate an unallocated memory that is large enough to contain a range in size of
|
||||
|
||||
@@ -13,7 +13,7 @@ from qiling.arch.x86_const import GS_SEGMENT_ADDR, GS_SEGMENT_SIZE, FS_SEGMENT_A
|
||||
from qiling.arch.x86_utils import GDTManager, SegmentManager86, SegmentManager64
|
||||
from qiling.cc import intel
|
||||
from qiling.const import QL_ARCH, QL_OS, QL_INTERCEPT
|
||||
from qiling.exception import QlErrorSyscallError, QlErrorSyscallNotFound
|
||||
from qiling.exception import QlErrorSyscallError, QlErrorSyscallNotFound, QlMemoryMappedError
|
||||
from qiling.os.fcall import QlFunctionCall
|
||||
from qiling.os.memory import QlMemoryHeap
|
||||
from qiling.os.os import QlOs
|
||||
@@ -116,11 +116,15 @@ class QlOsWindows(QlOs):
|
||||
segm.setup_fs(FS_SEGMENT_ADDR, FS_SEGMENT_SIZE)
|
||||
segm.setup_gs(GS_SEGMENT_ADDR, GS_SEGMENT_SIZE)
|
||||
|
||||
if not self.ql.mem.is_mapped(FS_SEGMENT_ADDR, FS_SEGMENT_SIZE):
|
||||
self.ql.mem.map(FS_SEGMENT_ADDR, FS_SEGMENT_SIZE, info='[FS]')
|
||||
if not self.ql.mem.is_available(FS_SEGMENT_ADDR, FS_SEGMENT_SIZE):
|
||||
raise QlMemoryMappedError('cannot map FS segment, memory location is taken')
|
||||
|
||||
if not self.ql.mem.is_mapped(GS_SEGMENT_ADDR, GS_SEGMENT_SIZE):
|
||||
self.ql.mem.map(GS_SEGMENT_ADDR, GS_SEGMENT_SIZE, info='[GS]')
|
||||
self.ql.mem.map(FS_SEGMENT_ADDR, FS_SEGMENT_SIZE, info='[FS]')
|
||||
|
||||
if not self.ql.mem.is_available(GS_SEGMENT_ADDR, GS_SEGMENT_SIZE):
|
||||
raise QlMemoryMappedError('cannot map GS segment, memory location is taken')
|
||||
|
||||
self.ql.mem.map(GS_SEGMENT_ADDR, GS_SEGMENT_SIZE, info='[GS]')
|
||||
|
||||
|
||||
def __setup_components(self):
|
||||
|
||||
Reference in New Issue
Block a user