public IEnumerable <KeyValuePair <string, ulong> > GetSavedRegisters() { var layout = _Provider.GetThreadLayout(_Evaluator); var sp = _Evaluator.EvaluateIntegralExpression(GetFieldExpression("sp")) ?? 0; var lr = _Evaluator.EvaluateIntegralExpression(GetFieldExpression("stack_frame")) ?? 0; if (sp == 0 || lr == 0) { return(new KeyValuePair <string, ulong> [0]); } StackLayoutBuilder builder = new StackLayoutBuilder(); builder.AddRegisters("r", 4, 11); if ((lr & 0x10) == 0) { builder.AddRegisters("s", 16, 31); } builder.AddRegisters("r", 0, 3); builder.AddRegisters("r12", "lr", "pc"); builder.Skip(4); return(builder.FetchValues(sp, _Evaluator)); }
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()); }
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)); }
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); } }
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()); }
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) { //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 int?GetActiveVirtualThreadId(IGlobalExpressionEvaluator evaluator) { ulong?id = evaluator.EvaluateIntegralExpression("_kernel.current"); return((int?)id); }
ulong GetSavedRegister(int slotNumber) { return(_Evaluator.EvaluateIntegralExpression( string.Format("((void **)0x{0:x})[{1}]", _SavedSP, slotNumber)).Value); }
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")); }
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()); }