From 3828186c56ffba1af5e8aab95712757c431f359b Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 14 Dec 2022 14:21:48 +0200 Subject: [PATCH] RIP history implementation for broken stacks --- Core/Crash/Screens/StackFrame.cpp | 34 +++++++++++++++++++++++++++---- Tasking/Task.cpp | 17 ++++++++++++++++ include/task.hpp | 3 +++ 3 files changed, 50 insertions(+), 4 deletions(-) diff --git a/Core/Crash/Screens/StackFrame.cpp b/Core/Crash/Screens/StackFrame.cpp index 3698183..661269b 100644 --- a/Core/Crash/Screens/StackFrame.cpp +++ b/Core/Crash/Screens/StackFrame.cpp @@ -27,11 +27,9 @@ namespace CrashHandler EHPrint("\n\eFAFAFATracing 40 process frames..."); SymbolResolver::Symbols *sh = data.Process->ELFSymbolTable; if (!sh) - { EHPrint("\n\eFF0000< No symbol table available. >\n"); - return; - } - TraceFrames(data.Frame, 40, sh, false); + else + TraceFrames(data.Frame, 40, sh, false); } EHPrint("\n\eFAFAFATracing interrupt frames..."); for (uint64_t i = 0; i < 8; i++) @@ -53,5 +51,33 @@ namespace CrashHandler EHPrint("\eFF4CA9Outside Kernel"); } } + if (data.Process && data.Thread) + { + EHPrint("\n\n\eFAFAFATracing thread RIP history..."); + SymbolResolver::Symbols *sh = data.Process->ELFSymbolTable; + if (!sh) + EHPrint("\n\eFF0000< No symbol table available. >\n"); + else + { + int SameItr = 0; + uint64_t LastRIP = 0; + for (int i = 0; i < 128; i++) + { + if (data.Thread->RIPHistory[i] == 0) + break; + if (data.Thread->RIPHistory[i] == LastRIP) + { + SameItr++; + if (SameItr > 3) + continue; + } + else + SameItr = 0; + LastRIP = data.Thread->RIPHistory[i]; + EHPrint("\n\e2565CC%p\e7925CC-\e25CCC9%s", data.Thread->RIPHistory[i], sh->GetSymbolFromAddress((uint64_t)data.Thread->RIPHistory[i])); + } + EHPrint("\n\e7925CCNote: \e2565CCSame RIPs are not shown more than 3 times.\n"); + } + } } } diff --git a/Tasking/Task.cpp b/Tasking/Task.cpp index 94b9735..05abb26 100644 --- a/Tasking/Task.cpp +++ b/Tasking/Task.cpp @@ -489,6 +489,23 @@ namespace Tasking CurrentCPU->CurrentThread->Status = TaskStatus::Running; *Frame = CurrentCPU->CurrentThread->Registers; + + // FIXME: Untested + for (int i = 0; i < 128; i++) + { + if (CurrentCPU->CurrentThread->RIPHistory[i] == 0) + { + CurrentCPU->CurrentThread->RIPHistory[i] = Frame->rip; + break; + } + + if (i == 127) + { + for (int j = 0; j < 127; j++) + CurrentCPU->CurrentThread->RIPHistory[j] = CurrentCPU->CurrentThread->RIPHistory[j + 1]; + CurrentCPU->CurrentThread->RIPHistory[127] = Frame->rip; + } + } GlobalDescriptorTable::SetKernelStack((void *)((uint64_t)CurrentCPU->CurrentThread->Stack->GetStackTop())); CPU::x64::writecr3({.raw = (uint64_t)CurrentCPU->CurrentProcess->PageTable}); // Not sure if this is needed, but it's better to be safe than sorry. diff --git a/include/task.hpp b/include/task.hpp index cad66c2..cdd565f 100644 --- a/include/task.hpp +++ b/include/task.hpp @@ -94,8 +94,11 @@ namespace Tasking #if defined(__amd64__) CPU::x64::TrapFrame Registers; uint64_t GSBase, FSBase; + uint64_t RIPHistory[128]; #elif defined(__i386__) uint32_t Registers; // TODO + uint64_t GSBase, FSBase; + uint32_t EIPHistory[128]; #elif defined(__aarch64__) uint64_t Registers; // TODO #endif