forgot to commit image loader code
parent
1f03449694
commit
df9e610d14
@ -0,0 +1,104 @@
|
|||||||
|
"""
|
||||||
|
Laods a memory image with debug information into memory
|
||||||
|
"""
|
||||||
|
|
||||||
|
from ..MMU import MMU
|
||||||
|
from ..Config import RunConfig
|
||||||
|
from ..Executable import Executable, LoadedExecutable, LoadedMemorySection, LoadedInstruction, MemoryFlags
|
||||||
|
from .ElfLoader import ElfInstruction, ElfLoadedMemorySection, InstructionAccessFault, InstructionAddressMisalignedTrap
|
||||||
|
from ..decoder import decode
|
||||||
|
from ..IO.IOModule import IOModule
|
||||||
|
from .privmodes import PrivModes
|
||||||
|
from ..colors import FMT_ERROR, FMT_NONE
|
||||||
|
|
||||||
|
from functools import lru_cache
|
||||||
|
from typing import Dict, List, Tuple, Optional, TYPE_CHECKING
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from .PrivCPU import PrivCPU
|
||||||
|
|
||||||
|
|
||||||
|
class ContinuousMMU(MMU):
|
||||||
|
io: List[IOModule]
|
||||||
|
data: bytearray
|
||||||
|
io_start: int
|
||||||
|
debug_info: Dict[str, Dict[str, str]]
|
||||||
|
|
||||||
|
def __init__(self, data: bytes, debug_info: Dict, cpu, io_start: int = 0xFF0000):
|
||||||
|
super(ContinuousMMU, self).__init__(conf=RunConfig())
|
||||||
|
self.cpu: 'PrivCPU' = cpu
|
||||||
|
self.data = bytearray(data)
|
||||||
|
if len(data) < io_start:
|
||||||
|
self.data += bytearray(io_start - len(data))
|
||||||
|
self.debug_info = debug_info
|
||||||
|
self.io_start = io_start
|
||||||
|
self.io = list()
|
||||||
|
self.kernel_end = 0
|
||||||
|
for start, name in debug_info['sections'].items():
|
||||||
|
if name.startswith('programs'):
|
||||||
|
self.kernel_end = int(start)
|
||||||
|
break
|
||||||
|
|
||||||
|
@lru_cache(maxsize=2048)
|
||||||
|
def read_ins(self, addr: int) -> ElfInstruction:
|
||||||
|
if addr >= self.io_start:
|
||||||
|
raise InstructionAccessFault(addr)
|
||||||
|
if addr % 4 != 0:
|
||||||
|
raise InstructionAddressMisalignedTrap(addr)
|
||||||
|
|
||||||
|
return ElfInstruction(*decode(self.data[addr:addr + 4]))
|
||||||
|
|
||||||
|
def read(self, addr: int, size: int) -> bytearray:
|
||||||
|
if addr < 0x100:
|
||||||
|
pc = self.cpu.pc
|
||||||
|
text_sec = self.get_sec_containing(pc)
|
||||||
|
print(FMT_ERROR + "[MMU] possible null dereference (read {:x}) from (pc={:x},sec={},rel={:x})".format(
|
||||||
|
addr, pc, text_sec.owner + ':' + text_sec.name, pc - text_sec.base
|
||||||
|
) + FMT_NONE)
|
||||||
|
if addr >= self.io_start:
|
||||||
|
return self.io_at(addr).read(addr, size)
|
||||||
|
return self.data[addr: addr + size]
|
||||||
|
|
||||||
|
def write(self, addr: int, size: int, data):
|
||||||
|
if addr < 0x100:
|
||||||
|
pc = self.cpu.pc
|
||||||
|
text_sec = self.get_sec_containing(pc)
|
||||||
|
print(FMT_ERROR + "[MMU] possible null dereference (write {:x}) from (pc={:x},sec={},rel={:x})".format(
|
||||||
|
addr, pc, text_sec.owner + ':' + text_sec.name, pc - text_sec.base
|
||||||
|
) + FMT_NONE)
|
||||||
|
if addr < self.kernel_end:
|
||||||
|
if self.cpu.mode != PrivModes.MACHINE:
|
||||||
|
pc = self.cpu.pc
|
||||||
|
text_sec = self.get_sec_containing(pc)
|
||||||
|
print(FMT_ERROR + "[MMU] kernel access to {:x} from outside kernel mode! (pc={:x},sec={},rel={:x})".format(
|
||||||
|
addr, pc, text_sec.owner + ':' + text_sec.name, pc - text_sec.base
|
||||||
|
) + FMT_NONE)
|
||||||
|
|
||||||
|
if addr >= self.io_start:
|
||||||
|
return self.io_at(addr).write(addr, data, size)
|
||||||
|
self.data[addr:addr + size] = data[0:size]
|
||||||
|
|
||||||
|
def io_at(self, addr) -> IOModule:
|
||||||
|
for mod in self.io:
|
||||||
|
if mod.contains(addr):
|
||||||
|
return mod
|
||||||
|
raise InstructionAccessFault(addr)
|
||||||
|
|
||||||
|
def add_io(self, io: IOModule):
|
||||||
|
self.io.append(io)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "ImageMMU()"
|
||||||
|
|
||||||
|
@lru_cache(maxsize=32)
|
||||||
|
def get_sec_containing(self, addr: int) -> Optional[LoadedMemorySection]:
|
||||||
|
next_sec = len(self.data)
|
||||||
|
for sec_addr, name in sorted(self.debug_info['sections'].items(), key=lambda x: int(x[0]), reverse=True):
|
||||||
|
if addr >= int(sec_addr):
|
||||||
|
owner, name = name.split(':')
|
||||||
|
base = int(sec_addr)
|
||||||
|
size = next_sec - base
|
||||||
|
flags = MemoryFlags('.text' in name, '.text' in name)
|
||||||
|
return ElfLoadedMemorySection(name, base, size, self.data[base:next_sec], flags, owner)
|
||||||
|
else:
|
||||||
|
next_sec = int(sec_addr)
|
Loading…
Reference in New Issue