sim:config: use upstream sel4 extensions Change-Id: I31ef32a5c7687a35d1f479975c8be7e6fdec5a30
diff --git a/gdbscript.py b/gdbscript.py deleted file mode 100755 index b4ed8ac..0000000 --- a/gdbscript.py +++ /dev/null
@@ -1,303 +0,0 @@ -#!/usr/bin/env python - -import os -import os.path -from glob import glob - - -def source(callable): - """Convenience decorator for sourcing gdb commands""" - callable() - return callable - - -@source -class seL4(gdb.Command): - """Utility functions for debugging seL4 applications""" - def __init__(self): - super(self.__class__, self).__init__('sel4', gdb.COMMAND_USER, prefix=True) - - -@source -class seL4BreakpointsEnabled(gdb.Command): - """Enable or disable breakpoints (disabled by default)""" - - def __init__(self): - super(self.__class__, self).__init__('sel4 breakpoints-enabled', gdb.COMMAND_STATUS) - - def complete(self, text, words): - return [c for c in ['True', 'False'] if c.startswith(text)] - - def invoke(self, arg, from_tty): - if arg: - breakpoints_enabled(arg) - else: - print(breakpoints_enabled()) - - -@source -class seL4Threads(gdb.Command): - """Lists all seL4 threads""" - - def __init__(self): - super(self.__class__, self).__init__('sel4 threads', gdb.COMMAND_STATUS) - - def invoke(self, arg, from_tty): - print('\n'.join(get_threads())) - - -@source -class seL4Thread(gdb.Command): - """Returns current seL4 thread""" - - def __init__(self): - super(self.__class__, self).__init__('sel4 thread', gdb.COMMAND_STATUS) - - def invoke(self, arg, from_tty): - print(get_current_thread()) - -@source -class seL4WaitForThread(gdb.Command): - """Waits for given thread to be avaiable""" - - def __init__(self): - super(self.__class__, self).__init__('sel4 wait-for-thread', gdb.COMMAND_BREAKPOINTS) - - def complete(self, text, word): - return list(thread for thread in get_threads() if thread.startswith(text)) - - def invoke(self, arg, from_tty): - gdb.execute('mon seL4 WaitForThread "{}"'.format(arg)) - gdb.execute('continue') - - -@source -class seL4SwitchSymbols(gdb.Command): - """Forcibly switches symbols to ones of the given component - - sel4 switch-symbols [component] - - Forcibly sets symbol-file to file corresponding to given component. - If no comonent name is given or thread is "default" then default - binary is loaded instead.""" - - def __init__(self): - super(self.__class__, self).__init__('sel4 switch-symbols', gdb.COMMAND_FILES) - - def complete(self, text, word): - global BINARIES - - components = list(BINARIES.keys()) - components.append('default') - return list(component for component in components if component.startswith(text)) - - def invoke(self, arg, from_tty): - if not arg or arg == 'default': - switch_symbols(verbose=True) - else: - switch_symbols(arg, fallback=False, verbose=True) - - -@source -class seL4Break(gdb.Command): - """Creates breakpoint - - sel4 break thread [address] - - Creates breakpoint in <thread> on optional <address> - If no address is given, the breakpoint will be set on - first address after context-switch""" - - def __init__(self): - super(self.__class__, self).__init__('sel4 break', gdb.COMMAND_BREAKPOINTS) - - def complete(self, text, word): - words = text.split(' ') - if not text or len(words) <= 1: - return list(thread for thread in get_threads() if thread.startswith(word)) - elif len(words) == 2: - return gdb.COMPLETE_SYMBOL - else: - return gdb.COMPLETE_NONE - - def invoke(self, arg, from_tty): - args = arg.split(' ') - - if len(args) < 1 or not args[0]: - raise gdb.GdbError("sel4 break: thread argument is required") - - thread = args[0] if len(args) >= 1 else None - symbol_name = args[1] if len(args) >= 2 else None - - if symbol_name: - symbol, _ = gdb.lookup_symbol(symbol_name) - address = int(symbol.value().address) - gdb.execute('mon seL4 SetBreakpoint "{}" {}'.format(thread, hex(address))) - else: - gdb.execute('mon seL4 SetBreakpoint "{}"'.format(thread)) - - -@source -class seL4Delete(gdb.Command): - """Removes breakpoint - - sel4 delete thread [address] - - Removes given breakpoint. If no address is given, the context-switch - breakpoint is removed""" - - def __init__(self): - super(self.__class__, self).__init__('sel4 delete', gdb.COMMAND_BREAKPOINTS) - - def complete(self, text, word): - words = text.split(' ') - if not text or len(words) <= 1: - return list(thread for thread in get_threads() if thread.startswith(word)) - elif len(words) == 2: - breakpoints = get_breakpoints(words[0]) - lines = breakpoints.split('\n')[3:][:-1] - completions = [] - for line in lines: - values = line.split('|') - thread = values[1].strip() - - if words[0] not in thread: - continue - - if 'null' in values[2]: - continue - - address = values[2].strip(); - if address.startswith(word): - completions.append(address) - return completions - else: - return gdb.COMPLETE_NONE - - def invoke(self, arg, from_tty): - args = arg.split(' ') - - if len(args) < 1 or not args[0]: - raise gdb.GdbError("sel4 delete: thread argument is required") - - thread = args[0] if len(args) >= 1 else None - address = args[1] if len(args) >= 2 else None - - if address: - gdb.execute('mon seL4 RemoveBreakpoint "{}" {}'.format(thread, address)) - else: - gdb.execute('mon seL4 RemoveBreakpoint "{}"'.format(thread)) - - -@source -class seL4DeleteAll(gdb.Command): - """Removes all breakpoints assigned to thread - - sel4 delete-all thread""" - - def __init__(self): - super(self.__class__, self).__init__('sel4 delete-all', gdb.COMMAND_BREAKPOINTS) - - def complete(self, text, word): - return list(thread for thread in get_threads() if thread.startswith(text)) - - def invoke(self, arg, from_tty): - gdb.execute('mon seL4 RemoveBreakpoint "{}" 0x0 True'.format(arg)) - - -@source -class seL4ListBreakpoints(gdb.Command): - """Lists all breakpoints - - sel4 list-breakpoints [thread] - """ - - def __init__(self): - super(self.__class__, self).__init__('sel4 list-breakpoints', gdb.COMMAND_BREAKPOINTS) - - def complete(self, text, word): - return list(thread for thread in get_threads() if thread.startswith(text)) - - def invoke(self, arg, from_tty): - print(get_breakpoints()) - - -@source -class seL4Ready(gdb.Command): - """Returns ready state of seL4 extensions""" - - def __init__(self): - super(self.__class__, self).__init__('sel4 ready', gdb.COMMAND_STATUS) - - def invoke(self, arg, from_tty): - gdb.execute('mon seL4 Ready') - - -@source -def find_binaries(): - global BINARIES, DEFAULT_BINARY - BINARIES = {} - - out = os.environ['OUT'] - kata_path = os.path.join(out, 'kata', 'riscv32-unknown-elf', 'debug') - DEFAULT_BINARY = os.path.join(kata_path, 'kernel', 'kernel.elf') - - images_path = os.path.join(kata_path, '*.instance.bin') - for image_path in glob(images_path): - image_name = os.path.basename(image_path).split('.instance.bin')[0] - BINARIES[image_name] = image_path - - BINARIES['rootserver'] = os.path.join(kata_path, 'capdl-loader') - - -def get_breakpoints(thread=None): - if not thread: - breakpoints = gdb.execute('mon seL4 GetBreakpoints', to_string=True).strip() - else: - breakpoints = gdb.execute('mon seL4 GetBreakpoints \"{}\"'.format(thread), to_string=True).strip() - return breakpoints - - -def get_current_thread(): - return gdb.execute('mon seL4 CurrentThread', to_string=True).strip() - - -def get_threads(): - threads = ', '.join(gdb.execute('mon seL4 Threads', to_string=True).strip().split('\n')[1:-1]) - return [thread.strip() for thread in threads.split(',') if thread.strip()] - - -def breakpoints_enabled(value=None): - if value: - gdb.execute('mon seL4 BreakpointsEnabled {}'.format(value)) - else: - return gdb.execute('mon seL4 BreakpointsEnabled', to_string=True).strip() - - -def switch_symbols(thread=None, fallback=True, verbose=False): - global BINARIES, DEFAULT_BINARY - - if thread is None: - gdb.execute('symbol-file {}'.format(DEFAULT_BINARY), from_tty=verbose) - return - - image_name = next((key for key in BINARIES.keys() if key in thread), None) - if image_name is not None: - image_path = BINARIES[image_name] - elif image_name is None and fallback: - image_path = DEFAULT_BINARY - else: - raise gdb.GdbError("no symbol-file found for thread/component {}".format(thread)) - - gdb.execute('symbol-file {}'.format(image_path), from_tty=verbose) - - -def stop_handler(event): - if not isinstance(event, gdb.StopEvent): - return - - thread = get_current_thread() - switch_symbols(thread) - - -gdb.events.stop.connect(stop_handler)
diff --git a/shodan.resc b/shodan.resc index 9be4dcb..e0f09c9 100644 --- a/shodan.resc +++ b/shodan.resc
@@ -12,7 +12,7 @@ include @sim/config/shodan_infrastructure/SmcRiscV32.cs include @sim/config/shodan_infrastructure/OpenTitan2_UART.cs include @sim/config/shodan_infrastructure/Mailbox.cs -include @sim/config/shodan_infrastructure/seL4Extensions.cs +include @sim/renode/tools/sel4_extensions/seL4Extensions.cs machine LoadPlatformDescription @sim/config/platforms/shodan.repl
diff --git a/shodan_infrastructure/seL4Extensions.cs b/shodan_infrastructure/seL4Extensions.cs deleted file mode 100644 index b4b09c9..0000000 --- a/shodan_infrastructure/seL4Extensions.cs +++ /dev/null
@@ -1,278 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Antmicro.Renode.Core; -using Antmicro.Renode.Logging; -using Antmicro.Renode.Peripherals.CPU; -using Antmicro.Renode.Peripherals.Bus; -using Antmicro.Renode.Utilities; - -namespace Antmicro.Renode.Debug -{ - public static class seL4Extensions - { - public static void CreateseL4(this RiscV32 @this) - { - EmulationManager.Instance.CurrentEmulation.ExternalsManager.AddExternal(new seL4(@this), "seL4"); - } - } - - public class seL4 : IExternal - { - public seL4(RiscV32 cpu) - { - this.cpu = cpu; - this.mapping = new Dictionary<ulong, string>(); - this.breakpoints = new Dictionary<string, SortedSet<ulong?>>(); - - var handleUnknownSyscallAddress = bus.GetSymbolAddress("handleUnknownSyscall"); - this.cpu.AddHook(handleUnknownSyscallAddress, HandleUnknownSyscall); - var idleThreadAddresss = bus.GetSymbolAddress("idle_thread"); - this.cpu.AddHook(idleThreadAddresss, Finalize); - } - - public string CurrentThread() - { - var tcb = bus.ReadDoubleWord(this.ksCurThreadPhysAddress, context: cpu); - if(!mapping.ContainsKey(tcb)) - { - return "default"; - } - return mapping[tcb]; - } - - public void WaitForThread(string threadName) - { - pendingThreadName = threadName; - } - - public void SetBreakpoint(string threadName, ulong? address = null) - { - var realThreadName = mapping.Values.Where(thread => thread.Contains(threadName)).FirstOrDefault(); - if(String.IsNullOrEmpty(realThreadName)) - { - this.Log(LogLevel.Warning, "No thread with name '{0}' found.", threadName); - return; - } - - if(!breakpoints.ContainsKey(realThreadName)) - { - breakpoints.Add(realThreadName, new SortedSet<ulong?>()); - } - - if(!breakpoints[realThreadName].Add(address)) - { - this.Log(LogLevel.Warning, "This breakpoint already exists."); - } - } - - public void RemoveBreakpoint(string threadName, ulong? address = null, bool removeAll = false) - { - var realThreadName = mapping.Values.Where(thread => thread.Contains(threadName)).FirstOrDefault(); - if(String.IsNullOrEmpty(realThreadName)) - { - this.Log(LogLevel.Warning, "No thread with name '{0}' found.", threadName); - return; - } - - if(!breakpoints.ContainsKey(realThreadName)) - { - return; - } - - if(removeAll) - { - foreach(var addr in breakpoints[realThreadName]) - { - if(addr != null) - { - cpu.RemoveHook(addr.Value, HandleBreakpoint); - } - } - - breakpoints.Remove(realThreadName); - } - else - { - if(breakpoints[realThreadName].Remove(address) && address != null) - { - cpu.RemoveHook(address.Value, HandleBreakpoint); - } - } - } - - public string[,] GetBreakpoints(string threadName = null) - { - var entries = breakpoints.SelectMany(t => t.Value, (thread, address) => new { Thread = thread.Key, Address = address }); - if(threadName != null) - { - entries = entries.Where(x => x.Thread.Contains(threadName)); - } - var table = new Table().AddRow("Thread", "Address"); - table.AddRows(entries, x => x.Thread, x => x.Address == null ? "null" : "0x{0:X}".FormatWith(x.Address)); - return table.ToArray(); - } - - private void HandleUnknownSyscall(ICpuSupportingGdb _cpu, ulong address) - { - if(cpu.A[0] != DebugThreadNameSyscall) - { - return; - } - - cpu.RemoveHook(address, HandleUnknownSyscall); - - var ksCurThreadAddress = bus.GetSymbolAddress("ksCurThread"); - var lookupIPCBufferAddress = bus.GetSymbolAddress("lookupIPCBuffer"); - var lookupCapAndSlotAddress = bus.GetSymbolAddress("lookupCapAndSlot"); - - ksCurThreadPhysAddress = cpu.TranslateAddress(ksCurThreadAddress, MpuAccess.Read); - cpu.AddHook(lookupCapAndSlotAddress, HandleLookupCapAndSlotAddress); - cpu.AddHook(lookupIPCBufferAddress, HandleLookupIPCBuffer); - } - - private void Finalize(ICpuSupportingGdb _cpu, ulong address) - { - cpu.RemoveHook(address, Finalize); - Ready = true; - this.Log(LogLevel.Info, "Initialization complete."); - } - - private void ksCurThreadChanged(ICpuSupportingGdb _cpu, ulong address) - { - foreach(var addr in breakpoints.Values.SelectMany(v => v).Where(v => v != null)) - { - cpu.RemoveHook(addr.Value, HandleBreakpoint); - } - - var thread = CurrentThread(); - if(!breakpoints.ContainsKey(thread)) - { - return; - } - - var tcb = cpu.TranslateAddress((ulong)bus.ReadDoubleWord(this.ksCurThreadPhysAddress, context: cpu) + 0x88, MpuAccess.Read); - var pc = bus.ReadDoubleWord(tcb, context: cpu); - cpu.AddHook(pc, HandleThreadSwitch); - } - - private void HandleThreadSwitch(ICpuSupportingGdb _cpu, ulong address) - { - cpu.RemoveHook(address, HandleThreadSwitch); - - var thread = CurrentThread(); - foreach(var addr in breakpoints[thread]) - { - if(addr == null) - { - continue; - } - - cpu.AddHook(addr.Value, HandleBreakpoint); - } - - if(breakpoints[thread].Contains(null)) - { - cpu.Pause(); - cpu.EnterSingleStepModeSafely(new HaltArguments(HaltReason.Breakpoint, cpu.Id, address, BreakpointType.MemoryBreakpoint), true); - } - } - - private void HandleBreakpoint(ICpuSupportingGdb _cpu, ulong address) - { - cpu.Pause(); - cpu.EnterSingleStepModeSafely(new HaltArguments(HaltReason.Breakpoint, cpu.Id, address, BreakpointType.MemoryBreakpoint), true); - } - - private void HandleLookupCapAndSlotAddress(ICpuSupportingGdb _cpu, ulong address) - { - cpu.RemoveHook(address, HandleLookupCapAndSlotAddress); - cpu.AddHook(cpu.RA, HandlePostLookupCapAndSlotAddress); - } - - private void HandlePostLookupCapAndSlotAddress(ICpuSupportingGdb _cpu, ulong address) - { - var luRet = cpu.A[0]; - var paddr = cpu.TranslateAddress(luRet + 0x4UL, MpuAccess.Read); - var underlying = bus.ReadDoubleWord(paddr, context: cpu); - currentTCB = underlying & 0xffffff00; - } - - - private void HandleLookupIPCBuffer(ICpuSupportingGdb _cpu, ulong address) - { - cpu.RemoveHook(address, HandleLookupIPCBuffer); - cpu.AddHook(cpu.RA, HandlePostLookupIPCBuffer); - } - - private void HandlePostLookupIPCBuffer(ICpuSupportingGdb _cpu, ulong address) - { - var paddr = cpu.TranslateAddress(cpu.A[0] + 0x4UL, MpuAccess.Read); - // NOTE(mwitkowski): 100 bytes is arbitrary - var bytes = bus.ReadBytes(paddr, 100, context: cpu) - .TakeWhile(b => b != 0) - .ToArray(); - var threadName = System.Text.Encoding.ASCII.GetString(bytes); - - if(!mapping.ContainsKey(currentTCB)) - { - mapping.Add(currentTCB, threadName); - } - else if(threadName.Contains("_control")) - { - mapping[currentTCB] = threadName; - } - - if(pendingThreadName != null && threadName.Contains(pendingThreadName)) - { - pendingThreadName = null; - cpu.Pause(); - cpu.EnterSingleStepModeSafely(new HaltArguments(HaltReason.Breakpoint, cpu.Id, address, BreakpointType.MemoryBreakpoint), true); - } - } - - public bool BreakpointsEnabled - { - get - { - return breakpointsEnabled; - } - set - { - if(breakpointsEnabled == value) - { - return; - } - - breakpointsEnabled = value; - var address = bus.GetSymbolAddress("restore_user_context"); - if(value) - { - cpu.AddHook(address, ksCurThreadChanged); - } - else - { - cpu.RemoveHook(address, ksCurThreadChanged); - } - } - } - - public string[] Threads => mapping.Values.ToArray(); - - public bool Ready { get; private set; } - - private const uint DebugThreadNameSyscall = 0xffffffef; - - private readonly Dictionary<string, SortedSet<ulong?>> breakpoints; - private readonly Dictionary<ulong, string> mapping; - private readonly RiscV32 cpu; - private SystemBus bus => cpu.Bus; - - private bool breakpointsEnabled; - private ulong ksCurThreadPhysAddress; - private string pendingThreadName; - private ulong currentTCB; - } -} -