implemented mmu.allocate_region and reworked how the stack works

float_support
Anton Lydike 4 years ago
parent bc8c061c6d
commit 242af5c7a3

@ -10,7 +10,7 @@ import sys
from typing import Tuple, List, Dict, Callable, Type from typing import Tuple, List, Dict, Callable, Type
from .Tokenizer import RiscVTokenizer from .Tokenizer import RiscVTokenizer
from .Executable import MemoryFlags
from .Syscall import SyscallInterface, get_syscall_symbols from .Syscall import SyscallInterface, get_syscall_symbols
from .Exceptions import RiscemuBaseException, LaunchDebuggerException from .Exceptions import RiscemuBaseException, LaunchDebuggerException
from .MMU import MMU from .MMU import MMU
@ -85,6 +85,12 @@ class CPU:
Run a loaded executable Run a loaded executable
""" """
self.pc = le.run_ptr self.pc = le.run_ptr
if self.conf.stack_size > 0:
stack = self.mmu.allocate_section("stack", self.conf.stack_size, MemoryFlags(False, False))
self.regs.set('sp', stack.base + stack.size)
print(FMT_CPU + '[CPU] Allocated {} bytes of stack'.format(stack.size) + FMT_NONE)
print(FMT_CPU + '[CPU] Started running from 0x{:08X} ({})'.format(le.run_ptr, le.name) + FMT_NONE) print(FMT_CPU + '[CPU] Started running from 0x{:08X} ({})'.format(le.run_ptr, le.name) + FMT_NONE)
self.__run() self.__run()

@ -10,7 +10,7 @@ from typing import Optional
@dataclass(frozen=True, init=True) @dataclass(frozen=True, init=True)
class RunConfig: class RunConfig:
preffered_stack_size: Optional[int] = None stack_size: int = 0 # 8 * 1024 * 1024 * 8 # for 8MB stack
include_scall_symbols: bool = True include_scall_symbols: bool = True
add_accept_imm: bool = False add_accept_imm: bool = False
# debugging # debugging

@ -90,12 +90,28 @@ class OutOfMemoryException(RiscemuBaseException):
self.action = action self.action = action
def message(self): def message(self):
return + FMT_MEM + '{}(Ran out of memory during {})'.format( return FMT_MEM + '{}(Ran out of memory during {})'.format(
self.__class__.__name__, self.__class__.__name__,
self.action self.action
) + FMT_NONE ) + FMT_NONE
class InvalidAllocationException(RiscemuBaseException):
def __init__(self, msg, name, size, flags):
self.msg = msg
self.name = name
self.size = size
self.flags = flags
def message(self):
return FMT_MEM + '{}[{}](name={}, size={}, flags={})'.format(
self.__class__.__name__,
self.msg,
self.name,
self.size,
self.flags
)
# CPU Exceptions # CPU Exceptions

@ -7,7 +7,7 @@ SPDX-License-Identifier: BSD-2-Clause
from .Config import RunConfig from .Config import RunConfig
from .Executable import Executable, LoadedExecutable, LoadedMemorySection, LoadedInstruction, MemoryFlags from .Executable import Executable, LoadedExecutable, LoadedMemorySection, LoadedInstruction, MemoryFlags
from .helpers import align_addr from .helpers import align_addr
from .Exceptions import OutOfMemoryException from .Exceptions import OutOfMemoryException, InvalidAllocationException
from .colors import * from .colors import *
from typing import Dict, List, Tuple, Optional from typing import Dict, List, Tuple, Optional
@ -22,6 +22,11 @@ class MMU:
The maximum size of the memory in bytes The maximum size of the memory in bytes
""" """
max_alloc_size = 8 * 1024 * 1024 * 64
"""
No single allocation can be bigger than 64 MB
"""
sections: List[LoadedMemorySection] sections: List[LoadedMemorySection]
""" """
A list of all loaded memory sections A list of all loaded memory sections
@ -84,6 +89,32 @@ class MMU:
return loaded_bin return loaded_bin
def allocate_section(self, name: str, req_size: int, flag: MemoryFlags):
"""
Used to allocate a memory region (data only). Use `load_bin` if you want to load a binary, this is used for
stack and maybe malloc in the future.
:param name: Name of the section to allocate
:param req_size: The requested size
:param flag: The flags protecting this memory section
:return: The LoadedMemorySection
"""
if flag.executable:
raise InvalidAllocationException('cannot allocate executable section', name, req_size, flag)
if req_size < 0:
raise InvalidAllocationException('Invalid size request', name, req_size, flag)
if req_size > self.max_alloc_size:
raise InvalidAllocationException('Cannot allocate more than {} bytes at a time'.format(self.max_alloc_size), name, req_size, flag)
base = align_addr(self.first_free_addr)
size = align_addr(req_size)
sec = LoadedMemorySection(name, base, size, bytearray(size), flag, "<runtime>")
self.sections.append(sec)
self.first_free_addr = base + size
return sec
def get_sec_containing(self, addr: int) -> Optional[LoadedMemorySection]: def get_sec_containing(self, addr: int) -> Optional[LoadedMemorySection]:
""" """
Returns the section that contains the address addr Returns the section that contains the address addr

@ -62,13 +62,13 @@ if __name__ == '__main__':
help="Instruction sets to load, available are: {}. All are enabled by default" help="Instruction sets to load, available are: {}. All are enabled by default"
.format(", ".join(all_ins_names)), keys={k: True for k in all_ins_names}, omit_empty=True) .format(", ".join(all_ins_names)), keys={k: True for k in all_ins_names}, omit_empty=True)
parser.add_argument('--default_stack_size', type=int, help='Default stack size of loaded programs', default=None, parser.add_argument('--stack_size', type=int, help='Stack size of loaded programs, defaults to 8MB', nargs='?')
metavar='default-stack-size', nargs='?')
args = parser.parse_args() args = parser.parse_args()
cfg = RunConfig( # create a RunConfig from the cli args
preffered_stack_size=args.default_stack_size, cfg_dict = dict(
stack_size=args.stack_size,
debug_instruction=not args.options['disable_debug'], debug_instruction=not args.options['disable_debug'],
include_scall_symbols=not args.options['no_syscall_symbols'], include_scall_symbols=not args.options['no_syscall_symbols'],
debug_on_exception=not args.options['fail_on_ex'], debug_on_exception=not args.options['fail_on_ex'],
@ -76,6 +76,11 @@ if __name__ == '__main__':
scall_fs=args.syscall_opts['fs_access'], scall_fs=args.syscall_opts['fs_access'],
scall_input=not args.syscall_opts['disable_input'] scall_input=not args.syscall_opts['disable_input']
) )
for k, v in dict(cfg_dict).items():
if v is None:
del cfg_dict[k]
cfg = RunConfig(**cfg_dict)
if not hasattr(args, 'ins'): if not hasattr(args, 'ins'):
setattr(args, 'ins', {k: True for k in all_ins_names}) setattr(args, 'ins', {k: True for k in all_ins_names})

Loading…
Cancel
Save