/* This file is part of Fennix Kernel. Fennix Kernel is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fennix Kernel is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Fennix Kernel. If not, see . */ #include "../crashhandler.hpp" #include "chfcts.hpp" #include #include #include #include #include #if defined(a64) #include "../../Architecture/amd64/cpu/gdt.hpp" #elif defined(a32) #elif defined(aa64) #endif #include "../../kernel.h" namespace CrashHandler { struct StackFrame { struct StackFrame *rbp; uintptr_t rip; }; SafeFunction void TraceFrames(CRData data, int Count, SymbolResolver::Symbols *SymHandle, bool Kernel) { if (!Memory::Virtual().Check(data.Frame)) { EHPrint("Invalid frame pointer: %p\n", data.Frame); return; } if (!Memory::Virtual().Check(SymHandle)) { EHPrint("Invalid symbol handle: %p\n", SymHandle); return; } bool TriedRetryBP = false; struct StackFrame *frames = nullptr; RetryBP: #if defined(a64) if (TriedRetryBP == false) frames = (struct StackFrame *)data.Frame->rbp; #elif defined(a32) if (TriedRetryBP == false) frames = (struct StackFrame *)data.Frame->ebp; #elif defined(aa64) #endif if (!Memory::Virtual().Check((void *)frames)) { if (TriedRetryBP == false) { frames = (struct StackFrame *)Memory::Virtual(data.Process->PageTable).GetPhysical((void *)frames); TriedRetryBP = true; goto RetryBP; } #if defined(a64) EHPrint("Invalid rbp pointer: %p\n", data.Frame->rbp); #elif defined(a32) EHPrint("Invalid ebp pointer: %p\n", data.Frame->ebp); #elif defined(aa64) #endif return; } debug("\nStack tracing... %p %d %p %d", data.Frame, Count, frames, Kernel); EHPrint("\e7981FC\nStack Trace:\n"); if (!frames || !frames->rip || !frames->rbp) { #if defined(a64) EHPrint("\e2565CC%p", (void *)data.Frame->rip); #elif defined(a32) EHPrint("\e2565CC%p", (void *)data.Frame->eip); #elif defined(aa64) #endif EHPrint("\e7925CC-"); #if defined(a64) EHPrint("\eAA25CC%s", SymHandle->GetSymbolFromAddress(data.Frame->rip)); #elif defined(a32) EHPrint("\eAA25CC%s", SymHandle->GetSymbolFromAddress(data.Frame->eip)); #elif defined(aa64) #endif EHPrint("\e7981FC <- Exception"); EHPrint("\eFF0000\n< No stack trace available. >\n"); } else { #if defined(a64) EHPrint("\e2565CC%p", (void *)data.Frame->rip); EHPrint("\e7925CC-"); if ((data.Frame->rip >= 0xFFFFFFFF80000000 && data.Frame->rip <= (uintptr_t)&_kernel_end) || !Kernel) EHPrint("\eAA25CC%s", SymHandle->GetSymbolFromAddress(data.Frame->rip)); else EHPrint("Outside Kernel"); #elif defined(a32) EHPrint("\e2565CC%p", (void *)data.Frame->eip); EHPrint("\e7925CC-"); if ((data.Frame->eip >= 0xC0000000 && data.Frame->eip <= (uintptr_t)&_kernel_end) || !Kernel) EHPrint("\eAA25CC%s", SymHandle->GetSymbolFromAddress(data.Frame->eip)); else EHPrint("Outside Kernel"); #elif defined(aa64) #endif EHPrint("\e7981FC <- Exception"); for (int frame = 0; frame < Count; ++frame) { if (!frames->rip) break; EHPrint("\n\e2565CC%p", (void *)frames->rip); EHPrint("\e7925CC-"); #if defined(a64) if ((frames->rip >= 0xFFFFFFFF80000000 && frames->rip <= (uintptr_t)&_kernel_end) || !Kernel) #elif defined(a32) if ((frames->rip >= 0xC0000000 && frames->rip <= (uintptr_t)&_kernel_end) || !Kernel) #elif defined(aa64) if ((frames->rip >= 0xFFFFFFFF80000000 && frames->rip <= (uintptr_t)&_kernel_end) || !Kernel) #endif EHPrint("\e25CCC9%s", SymHandle->GetSymbolFromAddress(frames->rip)); else EHPrint("\eFF4CA9Outside Kernel"); if (!Memory::Virtual().Check(frames->rbp)) return; frames = frames->rbp; } } EHPrint("\n"); } }