Skip to content

Commit b8d1b5e

Browse files
committed
Add stack alignment to CRT0 to ensure it in programs after kernel entry; improve debug output on stack traces
1 parent 09b030d commit b8d1b5e

File tree

3 files changed

+111
-36
lines changed

3 files changed

+111
-36
lines changed

kernel/src/kernel/system/interrupts/exceptions.cpp

Lines changed: 101 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2020

2121
#include "kernel/system/interrupts/exceptions.hpp"
22+
23+
#include <shared/utils/string.hpp>
24+
2225
#include "kernel/memory/memory.hpp"
2326
#include "kernel/memory/page_reference_tracker.hpp"
2427
#include "kernel/memory/paging.hpp"
@@ -28,9 +31,6 @@
2831
#include "kernel/tasking/tasking.hpp"
2932
#include "kernel/tasking/tasking_memory.hpp"
3033
#include "shared/logger/logger.hpp"
31-
#include "shared/panic.hpp"
32-
33-
#define DEBUG_PRINT_STACK_TRACE 1
3434

3535
/**
3636
* Names of the exceptions
@@ -99,6 +99,98 @@ bool exceptionsHandleDivideError(g_task* task)
9999
return true;
100100
}
101101

102+
g_elf_object* exceptionsFindResponsibleObject(g_task* task, g_address rip)
103+
{
104+
g_elf_object* object = nullptr;
105+
106+
auto iter = hashmapIteratorStart(task->process->object->loadedObjects);
107+
while(hashmapIteratorHasNext(&iter))
108+
{
109+
auto nextObject = hashmapIteratorNext(&iter)->value;
110+
if(rip >= nextObject->startAddress && rip < nextObject->endAddress)
111+
{
112+
object = nextObject;
113+
break;
114+
}
115+
}
116+
hashmapIteratorEnd(&iter);
117+
118+
return object;
119+
}
120+
121+
Elf64_Sym* exceptionsFindFunctionSymbol(g_elf_object* object, g_address rip)
122+
{
123+
if(object->root)
124+
{
125+
// TODO: Symbol lookup only works well for shared libs so far, for some reason
126+
return nullptr;
127+
}
128+
129+
Elf64_Sym* bestMatch = nullptr;
130+
g_address localRip = rip - object->baseAddress;
131+
132+
for(uint64_t symbolIndex = 0; symbolIndex < object->dynamicSymbolTableSize; symbolIndex++)
133+
{
134+
auto& symbol = object->dynamicSymbolTable[symbolIndex];
135+
136+
if(ELF64_ST_TYPE(symbol.st_info) == STT_FUNC)
137+
{
138+
if(localRip >= symbol.st_value &&
139+
localRip < symbol.st_value + symbol.st_size)
140+
{
141+
return &symbol;
142+
}
143+
144+
if(localRip >= symbol.st_value &&
145+
(!bestMatch || symbol.st_value > bestMatch->st_value))
146+
{
147+
bestMatch = &symbol;
148+
}
149+
}
150+
}
151+
152+
return bestMatch;
153+
}
154+
155+
void exceptionsPrintCallAtRip(g_task* task, g_address rip)
156+
{
157+
auto object = exceptionsFindResponsibleObject(task, rip);
158+
auto function = object ? exceptionsFindFunctionSymbol(object, rip) : nullptr;
159+
160+
if(object && function)
161+
{
162+
auto functionName = function->st_name ? &object->dynamicStringTable[function->st_name] : "?";
163+
logInfo("%# %h (%s <%s> %h)", rip, object->name, functionName, rip - object->baseAddress);
164+
}
165+
else if(object)
166+
{
167+
logInfo("%# %h (%s %h)", rip, object->name, rip - object->baseAddress);
168+
}
169+
else
170+
{
171+
logInfo("%# %h", rip);
172+
}
173+
}
174+
175+
void exceptionsPrintStackTrace(g_task* task, volatile g_processor_state* state)
176+
{
177+
logInfo("%# stack trace:");
178+
exceptionsPrintCallAtRip(task, state->rip);
179+
180+
auto rbp = reinterpret_cast<g_address*>(state->rbp);
181+
for(int frame = 0; frame < 25; ++frame)
182+
{
183+
g_address rip = rbp[1];
184+
if(rip < 0x1000)
185+
{
186+
break;
187+
}
188+
rbp = reinterpret_cast<g_address*>(rbp[0]);
189+
190+
exceptionsPrintCallAtRip(task, rip);
191+
}
192+
}
193+
102194
/**
103195
* Dumps the current CPU state to the log file
104196
*/
@@ -113,54 +205,28 @@ void exceptionsDumpState(g_task* task, volatile g_processor_state* state)
113205
// Page fault
114206
logInfo("%# accessed address: %h", exceptionsGetCR2());
115207
}
208+
logInfo("%# INTR: %h ERROR: %h", state->intr, state->error);
116209
logInfo("%# RIP: %h RFLAGS: %h", state->rip, state->rflags);
117-
logInfo("%# RAX: %h RBX: %h", state->rax, state->rbx);
118-
logInfo("%# RCX: %h RDX: %h", state->rcx, state->rdx);
119-
logInfo("%# RSP: %h RBP: %h", state->rsp, state->rbp);
120210
logInfo("%# CS: %h SS: %h", state->cs, state->ss);
121-
logInfo("%# INTR: %h ERROR: %h", state->intr, state->error);
211+
logInfo("%# RSP: %h RBP: %h", state->rbp, state->rbp);
212+
logInfo("%# RAX: %h RBX: %h %RCX: %h RDX: %h", state->rax, state->rbx, state->rcx, state->rdx);
122213
if(task)
123214
{
124215
logInfo("%# task stack: %h - %h", task->stack.start, task->stack.end);
125216
logInfo("%# intr stack: %h - %h", task->interruptStack.start, task->interruptStack.end);
126217

218+
logInfo("%# loaded objects:");
127219
auto iter = hashmapIteratorStart(task->process->object->loadedObjects);
128220
while(hashmapIteratorHasNext(&iter))
129221
{
130222
auto object = hashmapIteratorNext(&iter)->value;
131223

132-
logInfo("%# obj %x-%x: %s", object->startAddress, object->endAddress, object->name);
133-
134-
if(state->rip >= object->startAddress && state->rip < object->endAddress)
135-
{
136-
if(object == task->process->object)
137-
{
138-
logInfo("%# caused in executable object");
139-
}
140-
else
141-
{
142-
logInfo("%# caused in object '%s' at offset %x", object->name, state->rip - object->baseAddress);
143-
}
144-
break;
145-
}
224+
logInfo("%# %x-%x: %s", object->startAddress, object->endAddress, object->name);
146225
}
147226
hashmapIteratorEnd(&iter);
148227
}
149228

150-
#if DEBUG_PRINT_STACK_TRACE
151-
g_address* rbp = reinterpret_cast<g_address*>(state->rbp);
152-
logInfo("%# stack trace:");
153-
for(int frame = 0; frame < 8; ++frame)
154-
{
155-
g_address rip = rbp[1];
156-
if(rip < 0x1000)
157-
{
158-
break;
159-
}
160-
rbp = reinterpret_cast<g_address*>(rbp[0]);
161-
logInfo("%# %h", rip);
162-
}
163-
#endif
229+
exceptionsPrintStackTrace(task, state);
164230
}
165231

166232
bool exceptionsHandlePageFault(g_task* task, volatile g_processor_state* state)

kernel/src/kernel/system/interrupts/interrupts.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ extern "C" volatile g_processor_state* _interruptHandler(volatile g_processor_st
107107
panic("%! attempted to switch to null task (%x) or state (%x)", "system", newTask, newTask->state);
108108
if(newTask != task)
109109
taskingRestoreState(newTask);
110+
110111
return newTask->state;
111112
}
112113

libc/crt/x86_64/crt0.S

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,15 @@
2727

2828
# The <_start> function is where the kernel starts the execution.
2929
_start:
30-
call __g_main
30+
mov %rsp, %rax
31+
and $0xf, %rax
32+
jz _skipAlignment
33+
34+
sub %rax, %rsp
35+
add $16, %rsp
36+
37+
_skipAlignment:
38+
call __g_main
3139

3240
# Endless loop, for the case that bad things happen
3341
wait:

0 commit comments

Comments
 (0)