this gets overwritten

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
Agares
Posts: 18
Joined: Sat Aug 25, 2012 4:19 pm

this gets overwritten

Post by Agares »

Hi!
In my kernel(x86, 32bit) I have some casual code to fill an array with 0's:

Code: Select all

	for (u32 i = 0; i < 1024; i++) {
		pageDirectory[i] = 0;
	}
This is what "pageDirectory" is(this code is in constructor, u32 is typdefed to unsigned int, pageDirectory is declared as private member: u32 *pageDirectory):

Code: Select all

pageDirectory = (u32 *)((((u32)&kernel_end) & 0xfffff000) + 0x1000) ;
kernel_end is declared as extern "C" u32 kernel_end and defined in my linker script(look below). My problem is, that right after the aforementioned loop, this is set to a strange value(at least that's what gdb[connected to qemu 1.4.0] says): 0x7f9dc00.
I am sure that pageDirectory is greater than &kernel_end(I've printed it to the screen, and printing'em out in gdb confirms that). What the hell am I doing wrong?
I compile the code with clang: clang -g -c -m32 -ffreestanding -fno-builtin -nostdlib -nostdinc -nostdinc++ -std=c++11 -fno-rtti paging.cpp -o paging.cpp.o
And link it with ld(from binutils compiled by myself): ~/opt/cross/bin/i586-elf-ld -L ~/opt/cross/lib/gcc/i586-elf/4.8.1/ -lgcc -T link.ld -o agos paging.cpp.o (and some more *.o files here of course)
this is my linker script:

Code: Select all

ENTRY(_start)

SECTIONS
{
	. = 1M;
	kernel_start = .;
	
	.text : ALIGN(4K) {
		*(.multiboot)
		*(.text)
	}

	.rodata : ALIGN(4K) {
		*(.rodata)
	}
	
	.data : ALIGN(4K) {
		*(.data)
	}

	.bss : ALIGN(4K) {
		*(COMMON)
		*(.bss)
		*(.bootstrapStack)
	}

	kernel_end = .;
}
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: this gets overwritten

Post by Combuster »

The appropriate type for kernel_end would technically be void because it doesn't actually store anything, it only exists to take it's reference - the language won't like it, so you'd at least declare it as something that's going to cause the least amount of errors, like declaring it as const uint8_t.

Another interesting consequence of this is that the value of &kernel_end should end up being hardcoded into the binary because that address is a constant. The compiler knows it and inserts symbol references, and then the linker fills it in for you - so if it actually changes you're doing something else wrong, like maybe actually writing to the variable instead or doing something significantly more scary.



Also, there's a minor bug in your aligning code that makes it sometimes skip unnecessary memory.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
Shaun
Member
Member
Posts: 43
Joined: Mon Sep 17, 2012 3:14 am
Contact:

Re: this gets overwritten

Post by Shaun »

is pageDirectory a class private variable? Is it global or static?

if pageDirectory is class private variable, and the class is built in runtime, and then you should know where the problem is.
Agares
Posts: 18
Joined: Sat Aug 25, 2012 4:19 pm

Re: this gets overwritten

Post by Agares »

I've changed type to u8, but it dint't change anything. The address ISN'T changing on runtime. And pageDirectory is a private variable, but it's only a pointer, so what's the difference?
Agares
Posts: 18
Joined: Sat Aug 25, 2012 4:19 pm

Re: this gets overwritten

Post by Agares »

I've checked esp after that loop and it's much less than pageDirectory address. Seriously, I don't have any more ideas. What am I missing? :C
User avatar
Shaun
Member
Member
Posts: 43
Joined: Mon Sep 17, 2012 3:14 am
Contact:

Re: this gets overwritten

Post by Shaun »

you can try declare pageDirectory as a global or static variable.

if it does not work ,paste your class related codes, please.
Kevin
Member
Member
Posts: 1071
Joined: Sun Feb 01, 2009 6:11 am
Location: Germany
Contact:

Re: this gets overwritten

Post by Kevin »

Combuster wrote:The appropriate type for kernel_end would technically be void because it doesn't actually store anything, it only exists to take it's reference - the language won't like it, so you'd at least declare it as something that's going to cause the least amount of errors, like declaring it as const uint8_t.
This is perfectly valid C and what I usually use:

Code: Select all

extern const void kernel_end;
Developer of tyndur - community OS of Lowlevel (German)
Agares
Posts: 18
Joined: Sat Aug 25, 2012 4:19 pm

Re: this gets overwritten

Post by Agares »

I declared pageDirectory as global and changed kernel_end type to void. Unfortunately, it didn't change anything.
Here is my class declaration(loop is in initializeDirectory, called from install):

Code: Select all

			
			class PagingInstaller {
			public:
				static const int pageSize = 0x1000;
				static const int addressMask = 0xFFFFF000;
				
				void install(Log *log, int availableMemory);
				
				void mapPage(u32 physicalAddress, u32 logicalAddress);
				void mapBlock(u32 physicalAddress, u32 logicalAddress, u32 size);
				void reloadTable();
			private:
				Log *log;
				u32 pagesToMap;
				
				void initializeDirectory();
				void mapMemory();
				void updateDirectory();
				void loadDirectory();
				void enablePaging();
			};
Agares
Posts: 18
Joined: Sat Aug 25, 2012 4:19 pm

Re: this gets overwritten

Post by Agares »

I've checked and even moving those loops to kernel_main messes up local variables. I really have no idea what is the reason. My GDT appears to be ok:

Code: Select all

Global Descriptor Table (base=0x0000000000117344, limit=24):
GDT[0x00]=??? descriptor hi=0x00000000, lo=0x00000000
GDT[0x01]=Code segment, base=0x00000000, limit=0xffffffff, Execute/Read, Non-Conforming, Accessed, 32-bit
GDT[0x02]=Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
Edit:
I also tested and it appears that reordering declarations of variables(or removing some) helps. It seems to be a stack overflow, but I am quite sure that my stack is okay, this is my entry file(nasm -felf -ostart.asm.o start.asm, i tried changing from times 4096 db 0 to times 5*1024*1024 db 0, but it didn't help):

Code: Select all

MBALIGN 	equ 1<<0
MEMINFO 	equ 1<<1
FLAGS		equ MBALIGN | MEMINFO
MAGIC		equ 0x1BADB002
CHECKSUM	equ -(MAGIC+FLAGS)

section .multiboot
align 4
	dd MAGIC
	dd FLAGS
	dd CHECKSUM

section .bootstrapStack
align 4

global stackBottom
global stackTop

stackBottom:
	times 4096 db 0
stackTop:

section .text
global _start
_start:
	mov esp, stackTop

	push ebx
	push eax
	
	extern kernel_main
	call kernel_main

	cli
hang:
	hlt
	jmp hang
Post Reply