public IEnumerable <KeyValuePair <string, ulong> > FetchValues(ulong sp, IGlobalExpressionEvaluator evaluator) { var bytes = evaluator.ReadMemoryBlock($"0x{sp:x8}", _Position) ?? new byte[0]; List <KeyValuePair <string, ulong> > result = new List <KeyValuePair <string, ulong> >(); foreach (var rec in _AllRegisters) { if (rec.EndOffset > bytes.Length) { continue; //Unavailable } switch (rec.Size) { case 4: result.Add(new KeyValuePair <string, ulong>(rec.Name, BitConverter.ToUInt32(bytes, rec.Offset))); break; case 8: result.Add(new KeyValuePair <string, ulong>(rec.Name, BitConverter.ToUInt64(bytes, rec.Offset))); break; } } result.Add(new KeyValuePair <string, ulong>("sp", sp + (ulong)_Position)); return(result); }
CPUTypes?GetCPUType(IGlobalExpressionEvaluator e) { // Reads CPUID register in SCB ulong CPUID = (ulong)e.EvaluateIntegralExpression("*((int*)0xE000ED00)") & 0x0000FFF0; // Bits 15:4 are: // 0xC20 if Cortex-M0 // 0xC23 if Cortex-M3 // 0xC24 if Cortex-M4 if (CPUID == 0x0000C200) { return(CPUTypes.CPU_ARM_CORTEX_M0); } else if (CPUID == 0x0000C230) { return(CPUTypes.CPU_ARM_CORTEX_M3); } else if (CPUID == 0x0000C240) { return(CPUTypes.CPU_ARM_CORTEX_M4); } else { return(CPUTypes.CPU_UNIDENTIFIED); } }
private KnownStackLayout GetThreadLayout(IGlobalExpressionEvaluator evaluator) { if (!_StackLayout.HasValue) { var insns = evaluator.DisassembleMemory("SVC_ContextSave", 10) ?? new SimpleInstruction[0]; bool hasFP = false; //This is a basic check to distinguish between known stack layouts. It is not trying to actually reconstruct the stack layout by analyzing the disassembly. foreach (var insn in insns) { if (insn.Text?.ToLower()?.Contains("vstmdbeq") == true) { hasFP = true; break; } if (insn.Text?.ToLower()?.StartsWith("bl") == true) { break; } } _StackLayout = hasFP ? KnownStackLayout.IntegralWithOptionalFP : KnownStackLayout.IntegralOnly; } return(_StackLayout.Value); }
LayoutCache BuildLayoutCache(IGlobalExpressionEvaluator evaluator, string structName, IEnumerable <string> fieldDescriptors) { int minOffset = int.MaxValue, maxOffset = int.MinValue; List <KeyValuePair <string, int> > offsets = new List <KeyValuePair <string, int> >(); foreach (var field in fieldDescriptors) { int idx = field.IndexOf('='); if (idx == -1) { continue; } ulong?rawOffset = evaluator.EvaluateIntegralExpression($"&(({structName} *)0)->{field.Substring(0, idx).Trim()}"); if (rawOffset.HasValue) { int offset = (int)rawOffset.Value; minOffset = Math.Min(minOffset, offset); maxOffset = Math.Max(maxOffset, offset); offsets.Add(new KeyValuePair <string, int>(field.Substring(idx + 1).Trim(), offset)); } } if (offsets.Count == 0) { return(null); } return(new LayoutCache(minOffset, maxOffset, offsets)); }
public ZephyrThread(ZephyrThreadProvider provider, ulong threadObjectAddress, IGlobalExpressionEvaluator evaluator, bool isCurrentlyExecuting = false) { IsCurrentlyExecuting = isCurrentlyExecuting; _Provider = provider; _ThreadObjectAddress = threadObjectAddress; _Evaluator = evaluator; UniqueID = (int)threadObjectAddress; var name = evaluator.EvaluateStringExpression($"(char *)&(((struct k_thread *)0x{threadObjectAddress:x8})->name)"); if (!string.IsNullOrEmpty(name)) { Name = name; } else { var sym = evaluator.TryGetMeaningulSymbolName(threadObjectAddress); if (sym.Symbol != null && sym.Offset == 0) { Name = sym.Symbol; } else { Name = $"0x{threadObjectAddress:x8}"; } } }
public IVirtualThread[] GetVirtualThreads( IGlobalExpressionEvaluator e) { // Get the total number of tasks running int taskCount = (int)e.EvaluateIntegralExpression("uxCurrentNumberOfTasks"); // Get the number of different priorities (i.e. configMAX_PRIORITIES) -- // there is a ready task list for each possible priority int priorityCount = (int)e.EvaluateIntegralExpression("sizeof(pxReadyTasksLists)/sizeof(pxReadyTasksLists[0])"); List <IVirtualThread> threads = new List <IVirtualThread>(); // Get a pointer to the current TCB -- it's used to compare to the TCB of // each list found below, and a match means it's the currently running task UInt64?pxCurrentTCB = e.EvaluateIntegralExpression("pxCurrentTCB"); int currentTask = 0; // If the CPU type hasn't been found yet, do it -- it's necessary to find // out the stack layout later on if (!CPUType.HasValue) { CPUType = GetCPUType(e); } // Find tasks in ready lists -- one for each possible priority in FreeRTOS for (int i = 0; i < priorityCount; i++) { // Add all tasks found in this list threads.AddRange(GetThreadsFromList(e, "pxReadyTasksLists[" + i + "]", pxCurrentTCB, ref currentTask)); // If all tasks are accounted for, return early so as not to waste time // querying for extra tasks if (currentTask == taskCount) { return(threads.ToArray()); } } // Find tasks in delayed task lists for (int i = 1; i <= 2; i++) { // Add all tasks found in this list threads.AddRange(GetThreadsFromList(e, "xDelayedTaskList" + i, pxCurrentTCB, ref currentTask)); // If all tasks are accounted for, return early so as not to waste time // querying for extra tasks if (currentTask == taskCount) { return(threads.ToArray()); } } // Find tasks in suspended task list threads.AddRange(GetThreadsFromList(e, "xSuspendedTaskList", pxCurrentTCB, ref currentTask)); return(threads.ToArray()); }
public VirtualThread(CPUTypes?CPUType, string name, UInt64 savedSP, int index, bool isRunning, IGlobalExpressionEvaluator evaluator) { _CPUType = CPUType; _SavedSP = savedSP; _Name = name; _Index = index; _IsRunning = isRunning; _Evaluator = evaluator; }
public VirtualThread(StackLayout stackLayout, string name, UInt64 savedSP, int id, bool isRunning, IGlobalExpressionEvaluator evaluator) { _StackLayout = stackLayout; _SavedSP = savedSP; _Name = name; _UniqueID = id; _IsRunning = isRunning; _Evaluator = evaluator; }
public RTXThread(RTXThreadProvider provider, ulong threadObjectAddress, IGlobalExpressionEvaluator evaluator, bool isCurrentlyExecuting = false) { IsCurrentlyExecuting = isCurrentlyExecuting; _Provider = provider; _ThreadObjectAddress = threadObjectAddress; _Evaluator = evaluator; UniqueID = (int)threadObjectAddress; //RTX threads don't have meaningful sequential IDs Name = evaluator.EvaluateStringExpression(GetFieldExpression("name")) ?? "(unnamed)"; }
void ReportThreadList(List <IVirtualThread> result, IGlobalExpressionEvaluator expressionEvaluator, string expression, HashSet <ulong> reportedIDs) { for (ulong?addr = expressionEvaluator.EvaluateIntegralExpression(expression); addr.HasValue && addr != 0; addr = expressionEvaluator.EvaluateIntegralExpression($"(({ThreadTypeName} *)0x{addr.Value:x8})->thread_next")) { if (reportedIDs.Contains(addr.Value)) { continue; } reportedIDs.Add(addr.Value); result.Add(new RTXThread(this, addr.Value, expressionEvaluator)); } }
List <IVirtualThread> GetThreadsFromList(IGlobalExpressionEvaluator e, string listName, UInt64?pxCurrentTCB, ref int currentThread) { List <IVirtualThread> threads = new List <IVirtualThread>(); // Find how many tasks are there in this list int?threadsInListCount = (int?)e.EvaluateIntegralExpression(listName + ".uxNumberOfItems"); // If none, abort early; also, it's possible that a given list doesn't exist -- // for instance if INCLUDE_vTaskSuspend is 0 if (!threadsInListCount.HasValue || threadsInListCount == 0) { return(threads); } // Get the first list item in that list, and the corresponding task control block UInt64 currentListItem = (UInt64)e.EvaluateIntegralExpression(listName + ".xListEnd.pxNext"); UInt64 currentTCB = (UInt64)e.EvaluateIntegralExpression(string.Format("((ListItem_t*)0x{0:x})->pvOwner", currentListItem)); for (int j = 0; j < threadsInListCount.Value; j++) { // Get stack pointer UInt64 savedSP = (UInt64)e.EvaluateIntegralExpression(string.Format("((TCB_t*)0x{0:x})->pxTopOfStack", currentTCB)); // Get task name string name = e.EvaluateRawExpression(string.Format("((TCB_t*)0x{0:x})->pcTaskName", currentTCB)); // Trim null characters (\000) and quotes from the name Regex rgx = new Regex("\\\"(.*)\\\"(.*)"); name = name.Replace("\\000", ""); name = rgx.Replace(name, "$1"); // Add this thread to the list threads.Add(new VirtualThread(CPUType, // CPU type name, // task name savedSP, // stack pointer currentThread++, // index pxCurrentTCB == currentTCB, // is currently running? (yes if equality holds) e)); // evaluator // Iterate to next list item and TCB currentListItem = (UInt64)e.EvaluateIntegralExpression(string.Format("((ListItem_t*)0x{0:x})->pxNext", currentListItem)); currentTCB = (UInt64)e.EvaluateIntegralExpression(string.Format("((ListItem_t*)0x{0:x})->pvOwner", currentListItem)); } return(threads); }
public IVirtualThread[] GetVirtualThreads(IGlobalExpressionEvaluator expressionEvaluator) { _CalleeSavedLayout ??= BuildLayoutCache(expressionEvaluator, "struct k_thread", new[] { "callee_saved.psp=sp" }.Concat(Enumerable.Range(1, 8).Select(i => $"callee_saved.v{i}=r{i + 3}"))); _ESFLayout ??= BuildLayoutCache(expressionEvaluator, "struct __esf", new[] { "basic.ip=ip", "basic.lr=lr", "basic.pc=pc" }.Concat(Enumerable.Range(1, 4).Select(i => $"basic.a{i}=r{i - 1}"))); _ESFSize = expressionEvaluator.EvaluateIntegralExpression("sizeof(struct __esf)") ?? 0; List <IVirtualThread> result = new List <IVirtualThread>(); var pCurrentThread = expressionEvaluator.EvaluateIntegralExpression("_kernel.current"); if (!pCurrentThread.HasValue || pCurrentThread == 0) { return(new IVirtualThread[0]); } HashSet <ulong> reportedIDs = new HashSet <ulong>(); var allThreads = expressionEvaluator.EvaluateIntegralExpression("_kernel.threads"); if (allThreads.HasValue && allThreads.Value != 0) { for (ulong?pThread = allThreads; (pThread ?? 0) != 0; pThread = expressionEvaluator.EvaluateIntegralExpression($"((struct k_thread *)0x{pThread.Value:x8})->next_thread")) { if (reportedIDs.Contains(pThread.Value)) { break; //Avoid infinite loops } reportedIDs.Add(pThread.Value); result.Add(new ZephyrThread(this, pThread.Value, expressionEvaluator, pThread.Value == pCurrentThread.Value)); } } if (!reportedIDs.Contains(pCurrentThread.Value)) { result.Insert(0, new ZephyrThread(this, pCurrentThread.Value, expressionEvaluator, true)); } return(result.ToArray()); }
public IEnumerable <KeyValuePair <string, ulong> > Load(IGlobalExpressionEvaluator evaluator, ulong address) { int blockSize = _MaxOffset - _MinOffset + WordSize; var data = evaluator.ReadMemoryBlock($"0x{address + (uint)_MinOffset:x8}", blockSize); List <KeyValuePair <string, ulong> > result = new List <KeyValuePair <string, ulong> >(); foreach (var kv in _Offsets) { int offset = kv.Value - _MinOffset; if (data != null && data.Length >= (offset + WordSize)) { result.Add(new KeyValuePair <string, ulong>(kv.Key, BitConverter.ToUInt32(data, offset))); } else { //We could not fetch the data block, or it was incomplete } } return(result); }
public IVirtualThread[] GetVirtualThreads(IGlobalExpressionEvaluator expressionEvaluator) { //Based on the logic from svcRtxThreadEnumerate() List <IVirtualThread> result = new List <IVirtualThread>(); var thr = expressionEvaluator.EvaluateIntegralExpression("osRtxInfo.thread.run.curr"); if (!thr.HasValue || thr == 0) { return(new IVirtualThread[0]); } HashSet <ulong> reportedIDs = new HashSet <ulong> { thr.Value }; result.Add(new RTXThread(this, thr.Value, expressionEvaluator, true)); ReportThreadList(result, expressionEvaluator, "osRtxInfo.thread.ready.thread_list", reportedIDs); ReportThreadList(result, expressionEvaluator, "osRtxInfo.thread.delay_list", reportedIDs); ReportThreadList(result, expressionEvaluator, "osRtxInfo.thread.wait_list", reportedIDs); return(result.ToArray()); }
public IVirtualThread[] GetVirtualThreads( IGlobalExpressionEvaluator e) { // Get the total number of tasks running int taskCount = (int)e.EvaluateIntegralExpression("uxCurrentNumberOfTasks"); // Get the number of different priorities (i.e. configMAX_PRIORITIES) -- // there is a ready task list for each possible priority int priorityCount = (int)e.EvaluateIntegralExpression("sizeof(pxReadyTasksLists)/sizeof(pxReadyTasksLists[0])"); List <IVirtualThread> threads = new List <IVirtualThread>(); // Get a pointer to the current TCB -- it's used to compare to the TCB of // each list found below, and a match means it's the currently running task UInt64?pxCurrentTCB = e.EvaluateIntegralExpression("pxCurrentTCB"); int currentTask = 0; // If the CPU type hasn't been found yet, do it -- it's necessary to find // out the stack layout later on if (!_StackLayout.HasValue) { int disassemblyLines = e.GDBSession.ExecuteCommand("disassemble PendSV_Handler").AdditionalOutput?.Count(s => rgDisassemblyLine.IsMatch(s)) ?? 0; if (disassemblyLines == 0) { disassemblyLines = e.GDBSession.ExecuteCommand("disassemble xPortPendSVHandler").AdditionalOutput?.Count(s => rgDisassemblyLine.IsMatch(s)) ?? 0; } if (disassemblyLines >= 21 && disassemblyLines <= 22) { _StackLayout = StackLayout.WithoutFPU; } else if (disassemblyLines >= 30 && disassemblyLines <= 33) { _StackLayout = StackLayout.WithOptionalFPU; } else if (e.EvaluateIntegralExpression("sizeof(void *)") == 8) { _StackLayout = StackLayout.CortexA53; } else { var cpu = GetCPUType(e); _StackLayout = (cpu == CPUTypes.CPU_ARM_CORTEX_M4) ? StackLayout.WithOptionalFPU : StackLayout.WithoutFPU; } } // Find tasks in ready lists -- one for each possible priority in FreeRTOS for (int i = 0; i < priorityCount; i++) { // Add all tasks found in this list threads.AddRange(GetThreadsFromList(e, "pxReadyTasksLists[" + i + "]", pxCurrentTCB, ref currentTask)); // If all tasks are accounted for, return early so as not to waste time // querying for extra tasks if (currentTask == taskCount) { return(threads.ToArray()); } } // Find tasks in delayed task lists for (int i = 1; i <= 2; i++) { // Add all tasks found in this list threads.AddRange(GetThreadsFromList(e, "xDelayedTaskList" + i, pxCurrentTCB, ref currentTask)); // If all tasks are accounted for, return early so as not to waste time // querying for extra tasks if (currentTask == taskCount) { return(threads.ToArray()); } } // Find tasks in suspended task list threads.AddRange(GetThreadsFromList(e, "xSuspendedTaskList", pxCurrentTCB, ref currentTask)); return(threads.ToArray()); }
public int?GetActiveVirtualThreadId(IGlobalExpressionEvaluator evaluator) { ulong?id = evaluator.EvaluateIntegralExpression("_kernel.current"); return((int?)id); }
public int?GetActiveVirtualThreadId(IGlobalExpressionEvaluator evaluator) { ulong?id = evaluator.EvaluateIntegralExpression("osRtxInfo.thread.run.curr"); return((int?)id); }
public int?GetActiveVirtualThreadId(IGlobalExpressionEvaluator evaluator) { return((int?)evaluator.EvaluateIntegralExpression("pxCurrentTCB->uxTCBNumber")); }