Page 1 of 1

Going Paranoid

Posted: Sun May 24, 2009 8:48 am
by Creature
After countless hours of long work, I've finally managed to get a stable heap and everything seems to work fine. Seemed is the better word. I'm encountering very strange situations. For example: I create a vector (using a custom version) of a custom structure (lets name it 'foo'), everything works fine. I used my vector class countless times before, it worked fine, all tests succeed, no errors, etc... Then suddenly, I add this call:

Code: Select all

Vector<char> v;
somewhere and BOOM, everything crashes. I traced the bug to magically occur inside the paging code where paging is enabled with the first paging directory created. The weird thing is, the vector call is placed AFTER the paging initialization code and the vector code is never reached. Yet, if I remove the call, it works fine again. What makes it even more strange is that if I place the same code-line I placed above in another function, it suddenly works fine and nothing crashes!

At first I thought it was the heap again, but that's probably impossible since the heap isn't used, the crash occurs before anything ever gets to the heap or the vector class. So I'm thinking it's the linker script, but it's worked fine with me for a long time. Have any of you encountered something similar before? I really don't know what's going on or have any idea on how to fix this. I'm also using C++ for my kernel but have (I think) sufficient support for it (using information from on the wiki).

Could it be the linker in any way?

Code: Select all

ENTRY(BootEntry)
OUTPUT(../bin/Dynamix.bin)
OUTPUT_FORMAT("elf32-i386")

SECTIONS
{
	.text 0x100000 :
	{
		LdCode = .;
		*(.text)
		. = ALIGN(4096);
	}

	.data :
	{
		/* Constructor and destructor variables. */		
		LdConstrStart = .;
		*(.ctor*)
		LdConstrEnd = .;
		
		LdDestrStart = .;
		*(.dtor*)
		LdDestrEnd = .;
	
		LdData = .;
		*(.data)
		*(.rodata)
		. = ALIGN(4096);
	}

	.bss :
	{
		LdBss = .;
		*(.bss)
		*(.sbss)
		. = ALIGN(4096);
	}
	
	LdEnd = .;
}

INPUT
(	
	Boot.obj
	CPUID.obj
	Process.obj
	Interrupts.obj

	Compiler.o
	clib.o
	
	CPU.o
	Kernel.o
	Interrupts.o
	Keyboard.o
	IO.o
	
	Paging.o
	Heap.o
	Multitasking.o
	
	Main.o
)
EDIT: While doing more experiments with placing the code somewhere else, Bochs gave me an error similar to 'Bochs vetoed redirect' and 'getHostMem violation' once.

Thanks in advance.
Creature

Re: Going Paranoid

Posted: Sun May 24, 2009 8:56 am
by ru2aqare
I once encountered something similar when debugging my (still half-complete) ATA driver. The code would work, but when adding a simple printf("debug data: %p", some_pointer) call, it would crash. Changing it back to a simple printf("debug") statement, the code would work again. The crash eip got me nowhere, it crashed in code that was tested a hundred times before. Eventually I traced it back to a variable that was read, but the initializer statement had been commented out...

Also, in your case, it might be that the size of the .text section is larger than 4M, and your paging setup code is not prepared for it.

I don't know if that helps in your case.

Re: Going Paranoid

Posted: Sun May 24, 2009 10:35 am
by Firestryke31
I want to say it's a "not everything is loaded properly" thing. I think that about 90% of your code is properly mapped in, but when you try to run the 1% that's not, it fails. That would explain the fact that moving the statement around seems to fix the problem, since you're probably moving it somewhere where it is mapped in.

When I say mapped in, I mean either loaded from disk or having the pages set up, since both cause the same problem (no code where there should be code) but I would guess it's a paging set up problem.

Re: Going Paranoid

Posted: Sun May 24, 2009 12:50 pm
by Creature
Well I did drastically modify the old code I used from JamesM's tutorials because for some reason everything seemed to be looping itself. So I decided to create all the pages in the page-directory up front so they wouldn't need to be created later. I did it this way:

Code: Select all

/* Allocate 1024 page-tables for the page directory (do this now so the addresses can be identity mapped and frozen). */
	size_t PhysAddr;
	size_t i;

	for(i = 0; i < 1024; )
	{
		KernelDir->PageTables[i] = reinterpret_cast<PageTable *>(AllocAlignGetPhys(sizeof(PageTable), &PhysAddr));
		KernelDir->TablesPhys[i++] = PhysAddr | 0x7; /* The physical address with the 'Present', 'Read-Write' and 'UserMode' set. */
	}
Which worked better than JamesM's version for me (which crashed as soon as my heap wanted to expand). Is there anything wrong with it?

Re: Going Paranoid

Posted: Sun May 24, 2009 6:30 pm
by pcmattman
How big is your stack? And are you absolutely certain that the address space that the kernel uses at runtime is under 4 MB in size?

Re: Going Paranoid

Posted: Mon May 25, 2009 8:16 am
by Creature
My stack is 8 kB (8192 bytes). Everything seems fine and I checked things a few times over (comparing with some documentation on the wiki and JamesM's tuts). If you want to take a look at the entire source code, it's in my SVN repository.

Paging.cpp
Paging.h

Of which Paging.cpp contains the code that I displayed in my previous post. It's pretty strange that this problem appears now while it's worked fine earlier.