Page 1 of 3

Any C crashes kernel

Posted: Sat May 05, 2007 1:54 pm
by thewonderidiot
I'm very new to OS development. I've written a simple bootloader that does everything to get into protected mode (enable a20, set up gdt, etc.)(I haven't set up an IDT yet, though). I can get it to load and use the kernel entry point (which I can do whatever with), but including any C code at all kills it. Even just having something like

Code: Select all

void main() {}
crashes the kernel immediately. The last few lines in the bochs output before crash are:

Code: Select all

00000320000e[CLVGA] character height = 1, skipping text update
00000400000e[CLVGA] character height = 1, skipping text update
00000480000i[XGUI ] charmap update. Font Height is 16
00024645358i[CPU  ] BxError: instruction with opcode=0xff
00024645358i[CPU  ] mod was c0, nnn was 7, rm was 7
00024645358i[CPU  ] WARNING: Encountered an unknown instruction (signalling illegal instruction)
00024645358e[CPU  ] interrupt(): gate descriptor is not valid sys seg
00024645358e[CPU  ] interrupt(): gate descriptor is not valid sys seg
00024645358i[CPU  ] protected mode
00024645358i[CPU  ] CS.d_b = 32 bit
00024645358i[CPU  ] SS.d_b = 32 bit
00024645358i[CPU  ] | EAX=00000017  EBX=00000010  ECX=00000003  EDX=00000000
00024645358i[CPU  ] | ESP=0009cff8  EBP=00000000  ESI=0000a3b0  EDI=0000ffde
00024645358i[CPU  ] | IOPL=0 id vip vif ac vm RF nt of df if tf sf ZF af PF cf
00024645358i[CPU  ] | SEG selector     base    limit G D
00024645358i[CPU  ] | SEG sltr(index|ti|rpl)     base    limit G D
00024645358i[CPU  ] |  CS:0008( 0001| 0|  0) 00000000 000fffff 1 1
00024645358i[CPU  ] |  DS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00024645358i[CPU  ] |  SS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00024645358i[CPU  ] |  ES:ffff( 0000| 0|  0) 000ffff0 0000ffff 0 0
00024645358i[CPU  ] |  FS:0000( 0000| 0|  0) 00000000 0000ffff 0 0
00024645358i[CPU  ] |  GS:0000( 0000| 0|  0) 00000000 0000ffff 0 0
00024645358i[CPU  ] | EIP=02000001 (02000001)
00024645358i[CPU  ] | CR0=0x00000011 CR1=0 CR2=0x00000000
00024645358i[CPU  ] | CR3=0x00000000 CR4=0x00000000
00024645358i[CPU  ] >> (invalid)  : FFFF
00024645358e[CPU  ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
00024645358i[SYS  ] bx_pc_system_c::Reset(SOFTWARE) called
Any ideas on what might be going wrong? I can post code/system stats if necessary.

Posted: Sat May 05, 2007 3:25 pm
by frank
For some reason your code is jumping to code at 0x2000001. Can we see your linker script and the code that calls main?

Posted: Sat May 05, 2007 3:31 pm
by Shecks
If you are jumping to main() from assembler the implicit return at the end of main will just pop what ever is on the stack as the return address.

try

Code: Select all

void main ()
{
    while(1); 
}
If you are calling main from assembler make sure that you are blocking after the call for when main returns (your kernel main() normally shouldn't return anyway)

Hope that helps,

Shecks

Posted: Sat May 05, 2007 10:20 pm
by thewonderidiot
The main() definitely isn't returning. Putting an infinite loop at the end didn't do anything. Here's the linker script:

Code: Select all

OUTPUT_FORMAT("binary")
ENTRY(start)
phys = 0x00100000;
SECTIONS
{
	.text phys : {
		*(.text)
	}
	.data : {
		*(.data)
	}
	.bss : {
		*(.bss)
	}
}
and here's the code that calls main():

Code: Select all

[BITS	32]
global start
start:
	extern	main
	call	main
	cli
	hlt
I guess this error message may also be of interest:

Code: Select all

ld: warning: i386 architecture of input file `start.o' is incompatible with i386:x86-64 output
I'm guessing the linker's the source of the problem here....

EDIT: The linker's almost definitely to blame. My start.asm file crashes when there's any C file linked to it, but runs perfectly fine if unlinked. No references between the programs are made at all.

Posted: Sun May 06, 2007 12:19 am
by Solar
One, you are doing a call without having a stack set up.

Two, I have a suspicion that your toolchain is screwed up, as you seem to mix x86 and x86_64 somehow.

Posted: Sun May 06, 2007 12:40 am
by earlz
Are you sure it links properly?
since start.asm should be linked first(assuming your using binary) you can have something at the first of your asm file like "db "I'm start.asm"

and then look in your hex editor to see if it is the first part of the file..

Posted: Sun May 06, 2007 7:27 am
by thewonderidiot
hckr83 wrote:Are you sure it links properly?
since start.asm should be linked first(assuming your using binary) you can have something at the first of your asm file like "db "I'm start.asm"

and then look in your hex editor to see if it is the first part of the file..
You're right. For whatever reason, the string shows up at the very end of the file.

To Solar: I do have a stack set up in the bootloader. Just in case, I tried setting it up again in start.asm, but it didn't do anything.

Posted: Sun May 06, 2007 7:45 am
by t0xic
[BITS 32]
[global start]
[extern _main]

start:
call _main
cli
hlt


Try what I've put in red... maybe it will work?

Posted: Sun May 06, 2007 7:51 am
by thewonderidiot
No, undefined reference to _main. GCC doesn't put underscores before function names, right? And the square brackets around "global start" didn't affect anything.

Posted: Sun May 06, 2007 8:07 am
by frank
Are you trying to create an X86-64 binary? Can we see your makefile or the command lines you use to build the kernel?

Posted: Sun May 06, 2007 8:12 am
by thewonderidiot

Code: Select all

gcc -c kernel.c -o kernel.o
nasm -f aout start.asm -o start.o
ld -T link.ld -o kernel.bin start.o kernel.o   
That's what I use to build the kernel. For now, I just want my kernel to be x86. Building everything on my x86 laptop eliminated the warning but not the problem.

Posted: Sun May 06, 2007 12:02 pm
by thewonderidiot

Code: Select all

gdt:
gdt_null:
        dd      0
        dd      0
gdt_cs:
        dw      0xffff
        dw      0
        db      0
        db      0x9a
        db      0xcf
        db      0
gdt_ds:
        dw      0xffff
        dw      0
        db      0
        db      0x92
        db      0xcf
        db      0
gdte:
descriptor:
        dw      gdte-gdt-1
        dd      gdt
There's the GDT, and here's the code that calls start:

Code: Select all

        mov     esp,0x9d000
skrnl:
        jmp     0x8:0x100000
        cli
        hlt

Posted: Sun May 06, 2007 12:06 pm
by neon
Try compiling like this:

Code: Select all

gcc -ffreestanding -nostdlib -nostartfiles -fno-builtin -c -o kernel.o kernel.c
This will insure GCC does not include std library files.

Posted: Sun May 06, 2007 12:08 pm
by frank
Well I am almost out of ideas, but I have one left could you add

Code: Select all

-Map kernel.map
to the line with ld in it and post the contents of kernel.map

Posted: Sun May 06, 2007 12:10 pm
by Candy
thewonderidiot wrote:

Code: Select all

gcc -c kernel.c -o kernel.o
nasm -f aout start.asm -o start.o
ld -T link.ld -o kernel.bin start.o kernel.o   
That's what I use to build the kernel. For now, I just want my kernel to be x86. Building everything on my x86 laptop eliminated the warning but not the problem.
You're using your system compiler. Do you happen to have a 64-bit system setup?

If so, try our cross-compiler setup logic we have here to avoid loads of bogus "errors" that only occur because of setups that weren't meant to do OS dev. For an example, see the _main suggestion above. Cygwin GCC does prepend them by default, crosscompilers really should not (it was for compatibility with a language over 30 years ago).