I'm developing my 64 bits kernel in C++ and I'm trying to solve a bug that causes an Exception 14 (Page Fault) at address 0x0.
The exception raises when I call a virtual method on a local object. The very first thing the kernel does is instantiating the object, and the virtual call is the second.
What puzzles me most is that the error seems to dissapear if I comment a few lines of code after the bugous call, but reapears as soon as I uncomment them, I have verified that those lines don't get actually excecuted before the crash by printing a character to the first byte of video memory.
At first I thought that I was accidentally writing over the vtable, but the kernel crashes immediatly on the first call to a virtual method, before I even write on memory. Then I considered the possibility of having a missing section in my linker script, and verified that I have text, rodata, data and bss sections present. After that I considered that probably I'm missing a propper paging setup, or just writing outside the page setup, but the bootloader is already taking care of mapping a big chunk of memory before jumping into long mode.
Has anyone had a smiliar behaviour? I appreciate a lot your time and help.
This is my setup:
Language: C++
Bootloader: Pure64
Cross Compiler: gcc 4.8.2 x86-64
Linker script:
Code: Select all
OUTPUT_FORMAT("binary")
ENTRY(loader)
SECTIONS
{
.text 0x0000000000100000 :
{
*(.text)
}
rodata = .;
.rodata :
{
*(.rodata)
}
data = .;
.data :
{
*(.data)
}
bss = .;
.bss :
{
*(.bss)
}
endOfKernel = .;
}
Code: Select all
int main() {
(char*)(0xb8000)) = 'K';
WyrmLog log;
log.clear(); //Clear calls the function that causes the problem
(char*)(0xb8000)) = 'R'; //This never gets executed.
//If I comment the lines below, the error on the previos line stops happening
MemoryMap map(log, (void*)(getStackBase() + sizeof(uint64_t)));
PageAllocator pageAllocator(map.startAddress(), map.totalMemory(), log);
configurePageAllocator(map, pageAllocator);
void * mem = pageAllocator.alloc(1);
long long int test = 1;
RedBlackTreeNodeImpl<long long int> * node = new (mem) RedBlackTreeNodeImpl<long long int>(test);
...
}
//Log is the base class of WyrmLog
class Log {
public:
virtual Log& chr(int c) = 0;
...
}
Log& WyrmLog::clear() {
*((char*)(0xb8000)) = 'F';
for (int i = 0; i < Columns * Lines; i++) {
chr(' '); //This is the pure virtual method causing the problem
}
xPos = yPos = 0;
return *this;
}
Log& WyrmLog::chr(int c) {
*((char*)(0xb8000)) = '1'; //This never gets executed
...
return *this;
}
*EDIT* I corrected an allocation on the NULL address (it was not being executed anyway)