1 // 2 // Copyright (c) 2010-2024 Antmicro 3 // 4 // This file is licensed under the MIT License. 5 // Full license text is available in 'licenses/MIT.txt'. 6 // 7 using Antmicro.Renode.Core; 8 using Antmicro.Renode.UserInterface; 9 using ELFSharp.ELF; 10 using System.Text; 11 using System.Linq; 12 using System.Collections.Generic; 13 14 namespace Antmicro.Renode.Utilities.GDB.Commands 15 { 16 internal class MonitorCommand : Command 17 { MonitorCommand(CommandsManager m)18 public MonitorCommand(CommandsManager m) : base(m) 19 { 20 openOcdOverlay = new OpenOcdOverlay(m); 21 } 22 23 [Execute("qRcmd,")] Run([Argument(Encoding = ArgumentAttribute.ArgumentEncoding.HexString)]string arg)24 public IEnumerable<PacketData> Run([Argument(Encoding = ArgumentAttribute.ArgumentEncoding.HexString)]string arg) 25 { 26 if(!openOcdOverlay.TryProcess(arg, out var result, out var ok)) 27 { 28 var monitor = ObjectCreator.Instance.GetSurrogate<Monitor>(); 29 var eater = new CommandInteractionEater(); 30 monitor.Parse(arg, eater); 31 result = eater.HasError 32 ? eater.GetError() 33 : eater.GetContents(); 34 } 35 36 var consoleOutput = string.IsNullOrEmpty(result) ? null : string.Join(string.Empty, Encoding.UTF8.GetBytes(result).Select(x => x.ToString("X2")).Prepend("O")); 37 var resultReply = ok ? PacketData.Success : PacketData.ErrorReply(); 38 if(consoleOutput != null) 39 { 40 return new [] { new PacketData(consoleOutput), resultReply }; 41 } 42 return new [] { resultReply }; 43 } 44 45 private readonly OpenOcdOverlay openOcdOverlay; 46 47 private class OpenOcdOverlay 48 { OpenOcdOverlay(CommandsManager manager)49 public OpenOcdOverlay(CommandsManager manager) 50 { 51 this.manager = manager; 52 } 53 54 /// <param name="output">The output generated by the command, if successful; otherwise null.</param> 55 /// <param name="ok">Whether the command completed successfully.</param> 56 /// <returns>true if the command exists; otherwise false.</returns> TryProcess(string input, out string output, out bool ok)57 public bool TryProcess(string input, out string output, out bool ok) 58 { 59 output = null; 60 ok = true; 61 62 var argv = input.Split(new [] { ' ' }); 63 switch(argv.FirstOrDefault()) 64 { 65 case "reset": 66 if(argv.ElementAtOrDefault(1) != "init") 67 { 68 ok = false; 69 return true; 70 } 71 manager.Machine.Pause(); 72 manager.Machine.Reset(); 73 break; 74 case "halt": 75 manager.Machine.Pause(); 76 break; 77 case "reg": 78 var inputBuilder = new StringBuilder("=====\n"); 79 foreach(var i in manager.Cpu.GetRegisters().Where(x => x.IsGeneral).Select(x => x.Index)) 80 { 81 inputBuilder.AppendFormat("({0}) r{0} (/32): 0x", i); 82 var value = manager.Cpu.GetRegister(i); 83 // We always use big-endian GetBytes because we want 0x12345678 to become [0x12, 0x34, 0x56, 0x78] 84 // GetBytes also returns an array of the right length and appropriately padded with zeros. 85 foreach(var b in value.GetBytes(Endianess.BigEndian)) 86 { 87 inputBuilder.AppendFormat("{0:x2}", b); 88 } 89 inputBuilder.Append("\n"); 90 } 91 output = inputBuilder.ToString(); 92 break; 93 default: 94 return false; 95 } 96 return true; 97 } 98 99 private readonly CommandsManager manager; 100 } 101 } 102 } 103 104