Page 1 of 1

Kernel not loaded when a function is included

Posted: Sun Apr 03, 2011 1:42 pm
by Yargh
Currently I am working on writing a function for my kernel to scroll the screen when the cursor position is off the screen. To do this, however, I had to account for the X/Y alignment and X/Y size of the screen. The code I am using:

Code: Select all

void textScreen::scroll(){
	u8int colorAttrib = (colorBG << 4) | (colorFG & 0x0F); // FG color + BG color attribute

	u32int endPos; // Position it ends up at after clearing the other lines
	for(u32int i = 0; i < (xSize * (ySize-1))*2; i++){ // *2 for color attribute
		// Shift everything up a row, accounting for the x align, x size, y align, and y size.
		bufferAddr[i+xAlign+(xAlign*yAlign)] = bufferAddr[i+xSize+xAlign+(xAlign*yAlign)];
		endPos = i;
	}
	for(u32int i = endPos; i < xSize; i++){
		// Clear the last line
		bufferAddr[i+xAlign+(xAlign*yAlign)] = 0x20; // Space
		i++;
		bufferAddr[i+xAlign+(xAlign*yAlign)] = colorAttrib; // Color
	}

	csrX = xAlign;
	csrY = (yAlign + ySize) - 1;
}
I wrote out the calculations on paper and they seem to be correct. The problem, however, is that when I don't have this function commented out, even if I don't call it anywhere in the code, the kernel compiles fine but GRUB won't successfully load it (it freezes at the GRUB screen after I type "boot"). When I do have the function commented, it gets loaded fine and the kernel actually loads. I loaded the kernel in rebochs, and the disassembly showed that it made its way somewhere to an infinite loop, however the only infinite loops I have actually put in the code are after it displays something, which it doesn't.

One more odd thing is that when I include the function, even never calling it anywhere, it adds 4kb to the size of the kernel. Considering that it isn't even that large of a function, I don't see why this is happening. Any help would be appreciated.

Re: Kernel not loaded when a function is included

Posted: Sun Apr 03, 2011 3:23 pm
by Combuster
So you have the location of the infinite loop from the debugger, and you have objdump. Use them both together and you'll know what infinite loop you have reached.

Since you get an extra page of data in your final binary, it appears you are adding new sections. Which section is it and where is it in your linker script?

Re: Kernel not loaded when a function is included

Posted: Sun Apr 03, 2011 5:07 pm
by Yargh
It does not appear that any extra sections are getting added into my kernel binary... Objdump -x only shows .text, .rodata, and .bss. Linker script:

Code: Select all

ENTRY(kernelEntry) /* In boot.asm */

SECTIONS {
	. = 0x100000;

	/* Text Section */
	.text ALIGN(4096) : {
        code = .;
		*(.text*)
		*(.gnu.linkonce.t*)
	}

	/* Read-only data */
	.rodata ALIGN(4096) : {
		ctorStart = .; /* Start of constructors */
		*(.ctor*)
		ctorEnd = .; /* End of constructors */

		dtorStart = .; /* Start of destructors */
		*(.dtor*)
		dtorEnd = .; /* End of destructors */

		*(.rodata*)
		*(.gnu.linkonce.r*)
	}

	/* Data section */
	.data ALIGN(4096) : {
		*(.data*)
		*(.gnu.linkonce.d*)
	}

	/* BSS section */
	.bss ALIGN(4096) : {
        bss = .;
		*(.COMMON*)
		*(.bss*)
		*(.gnu.linkonce.b*)
	}

	end = .;

	/* Discarded sections */
	/DISCARD/ : {
		*(.comment)
		*(.eh_frame) /* No run-time c++ exceptions */
	}
}
Also, rebochs says the infinite loop is at 0x00007c54, which is as far as I can tell in the area where the GRUB stage1 is loaded (0x7c00 + some), and is way before the address (0x00100000) where the kernel is loaded. By the way, this IS grub 0.96 that I am using if i remember correctly, so maybe if someone had the stage1+stage2 for 0.98 that might fix it.

Re: Kernel not loaded when a function is included

Posted: Mon Apr 04, 2011 2:45 am
by Combuster
So we went from "code does not appear to be executed" to "wrong code is executed". Have you tried setting a breakpoint at your multiboot entry to see if it gets there? If so, step through it until you find out where it is going awry.
If your kernel isn't entered at the right place, you'll have to manually analyse your multiboot header in a hex editor to see where stuff goes.

Re: Kernel not loaded when a function is included

Posted: Mon Apr 04, 2011 7:49 pm
by Yargh
From what I can see (using the bochs debugger), it jumps to an invalid opcode somewhere, and triplefaults. The multiboot header, according to IDA Pro Free, is correct, with code/mboot header at 0x100000, bss at 0x103000, the flags being 011b, it ending at 0x11268E, and the entry at the address of the kernelEntry function. What is strange is that the header checksum is not 0, but then wouldn't GRUB error and not triplefault?

During debugging, I single-stepped through what GRUB was doing until around where it did a "mov eax, 0x2badb002", and then soon after that it triplefaulted, but before it hit the kernel entry, as the first instruction after the kernel entrypoint is a "xchg bx, bx" which would have trapped the debugger. This leads me to believe that because it was so close, it was jumping to the wrong address instead of the kernel entry (in addition to the fact that it triplefaulted on an invalid opcode error).

Re: Kernel not loaded when a function is included

Posted: Tue Apr 05, 2011 5:38 pm
by Yargh
I've found the problem (which in fact was in my kernel, facepalm): In my kernel when it's calling all the constructors, for some reason it sets eax to 0 and calls it, which results in it jumping to an area where it tries to, unsuccessfully, do a "lock push eax". Thanks for the help.

The entire problem was fixed with this:
if(*ctor != 0){
...
}
EDIT: (Reply to berkus) My implementation (aka the wiki's implementation) of calling constructors is having 2 variables defined by the linker, ctorStart and ctorEnd, and going through and calling the constructors from ctorStart until it reaches ctorEnd.