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 System.Collections.Generic; 8 using System.Globalization; 9 using System.Text; 10 using Antmicro.Renode.Exceptions; 11 12 namespace Antmicro.Renode.Utilities.GDB 13 { 14 // Based on the extended "thread-id" syntax information from https://sourceware.org/gdb/current/onlinedocs/gdb.html/Packets.html 15 // Shouldn't be used for "those packets and replies explicitly documented to include a process ID, rather than a thread-id". 16 public struct PacketThreadId 17 { 18 /// <param name="gdbArgument">It must be a full argument, i.e., including <c>"p"</c> if it was present.</param> PacketThreadIdAntmicro.Renode.Utilities.GDB.PacketThreadId19 public PacketThreadId(string gdbArgument) 20 { 21 var ids = gdbArgument.TrimStart('p').Split('.'); 22 23 if(ids.Length == 1 && TryParseId(ids[0], out var id)) 24 { 25 if(gdbArgument.StartsWith('p')) 26 { 27 ProcessId = id; 28 ThreadId = All; 29 } 30 else 31 { 32 ProcessId = null; 33 ThreadId = id; 34 } 35 } 36 else if(ids.Length == 2 && gdbArgument.StartsWith('p') 37 && TryParseId(ids[0], out var id1) && id1 != All && TryParseId(ids[1], out var id2)) 38 { 39 ProcessId = id1; 40 ThreadId = id2; 41 } 42 else 43 { 44 throw new RecoverableException($"Invalid GDB packet's thread-id argument: {gdbArgument}"); 45 } 46 } 47 ToStringAntmicro.Renode.Utilities.GDB.PacketThreadId48 public override string ToString() 49 { 50 return string.Empty 51 .AppendIf(ProcessId.HasValue, $"process-id: {IdToString(ProcessId.Value)}, ") 52 .Append($"thread-id: {IdToString(ThreadId)}").ToString(); 53 } 54 55 public int? ProcessId; 56 public int ThreadId; 57 58 // All and Any can be passed as a part of a valid argument. 59 public const int All = -1; 60 public const int Any = 0; 61 IdToStringAntmicro.Renode.Utilities.GDB.PacketThreadId62 private static string IdToString(int id) 63 { 64 switch(id) 65 { 66 case All: 67 return "all"; 68 case Any: 69 return "any"; 70 default: 71 return id.ToString(); 72 } 73 } 74 TryParseIdAntmicro.Renode.Utilities.GDB.PacketThreadId75 private static bool TryParseId(string s, out int result) 76 { 77 if(s == "-1") 78 { 79 result = -1; 80 return true; 81 } 82 else 83 { 84 // No need to ensure it isn't lower than -1 because negative values aren't allowed with HexNumber. 85 return int.TryParse(s, NumberStyles.HexNumber, NumberFormatInfo.InvariantInfo, out result); 86 } 87 } 88 } 89 } 90 91