Page 1 of 1
this gets overwritten
Posted: Wed Aug 14, 2013 6:27 pm
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 = .;
}
Re: this gets overwritten
Posted: Thu Aug 15, 2013 2:26 am
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.
Re: this gets overwritten
Posted: Thu Aug 15, 2013 3:32 am
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.
Re: this gets overwritten
Posted: Thu Aug 15, 2013 5:16 am
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?
Re: this gets overwritten
Posted: Thu Aug 15, 2013 4:03 pm
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
Re: this gets overwritten
Posted: Thu Aug 15, 2013 8:08 pm
by Shaun
you can try declare pageDirectory as a global or static variable.
if it does not work ,paste your class related codes, please.
Re: this gets overwritten
Posted: Fri Aug 16, 2013 4:30 am
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:
Re: this gets overwritten
Posted: Fri Aug 16, 2013 6:17 am
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();
};
Re: this gets overwritten
Posted: Fri Aug 16, 2013 10:23 am
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