GRUB Fails when loading Kernel >32k

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
thegamefreak0134
Posts: 14
Joined: Thu Jan 08, 2009 1:54 am

GRUB Fails when loading Kernel >32k

Post by thegamefreak0134 »

Hi guys, really pulling my hair out over this one. I've basically started out with a tutorial and worked up from there, and the interaction between elf files, the linker script, and GRUB, appears to have bitten be in the rear somewhere.

I've been looking at the output of the memory map spat out by the linker (when using the -Map [filename] flag) and it seems that when there are any symbols that get defined past the 32k mark, GRUB refuses to load the kernel, stating that it's an "Invalid or unsupported executable format". I've literally linked this to my code size-- the program compiles and runs until I add enough lines of code (any code whatsoever) that would make the total size greater than 32k in the memory map. Specifically (since I'm starting my first section at the 1MB mark) it fails when ebss comes out to greater than...

Hmm. After checking that again, it seems it's failing when it gets close to 32k, not right at it.

This is *really* bizzare. I'm going to spit out any files I think might be relevant here, tell me if something jumps out at you that I've done wrong. Note: my loader uses hand-converted FASM code from example NASM code, there's a potential that something went screwey in there, but it's very simplistic.

Linker Script:

Code: Select all

ENTRY (loader)

SECTIONS{
    . = 0x00100000;

    .text :{
        *(.text)
    }

    .rodata ALIGN (0x1000) : {
        *(.rodata)
    }

    .data ALIGN (0x1000) : {
        *(.data)
    }

    .bss : {
        sbss = .;
        *(COMMON)
        *(.bss)
        ebss = .;
    }
}

Linker Map Output (fail run):

Code: Select all

Allocating common symbols
Common symbol       size              file

gp                  0x6               build/core.o
idtp                0x6               build/idt.o
gdt                 0x18              build/core.o
conPos              0x4               build/consoleio.o
idt                 0x800             build/idt.o

Memory Configuration

Name             Origin             Length             Attributes
*default*        0x0000000000000000 0xffffffffffffffff

Linker script and memory map

                0x0000000000100000                . = 0x100000

.text           0x0000000000100000     0x1020
 *(.text)
 .text          0x0000000000100000      0x2be build/consoleio.o
                0x0000000000100000                strlen
                0x0000000000100025                setColor
                0x0000000000100032                write
                0x000000000010006b                writec
                0x000000000010014a                scrollScreen
                0x000000000010020e                clearScreen
                0x0000000000100256                writenum
 *fill*         0x00000000001002be        0x2 00
 .text          0x00000000001002c0      0x1f2 build/core.o
                0x00000000001002c0                kmain
 *fill*         0x00000000001004b2        0x2 00
 .text          0x00000000001004b4      0x4de build/exception-interrupts.o
                0x00000000001004b4                isrs_install
                0x000000000010095c                fault_handler
 *fill*         0x0000000000100992        0x2 00
 .text          0x0000000000100994      0x133 build/gdt.o
                0x0000000000100994                gdt_set_gate
                0x0000000000100a23                gdt_install
 *fill*         0x0000000000100ac7        0x1 00
 .text          0x0000000000100ac8      0x3b2 build/hardware-interrupts.o
                0x0000000000100ac8                irq_install_handler
                0x0000000000100ada                irq_uninstall_handler
                0x0000000000100aed                irq_remap
                0x0000000000100bbd                irq_install
                0x0000000000100e1b                irq_handler
 *fill*         0x0000000000100e7a        0x2 00
 .text          0x0000000000100e7c       0xa9 build/idt.o
                0x0000000000100e7c                idt_set_gate
                0x0000000000100ee3                idt_install
 *fill*         0x0000000000100f25        0x3 00
 .text          0x0000000000100f28       0xdc build/system.o
                0x0000000000100f28                memcpy
                0x0000000000100f5d                memset
                0x0000000000100f92                memsetw
                0x0000000000100fc9                inportb
                0x0000000000100fe6                outportb
 .text          0x0000000000101004       0x1c build/loader.o
                0x0000000000101010                loader

.iplt           0x0000000000101020        0x0
 .iplt          0x0000000000000000        0x0 build/consoleio.o

.rodata         0x0000000000102000      0x458
 *(.rodata)
 .rodata        0x0000000000102000      0x241 build/core.o
 *fill*         0x0000000000102241        0x3 00
 .rodata        0x0000000000102244      0x214 build/exception-interrupts.o

.rel.dyn        0x0000000000102458        0x0
 .rel.iplt      0x0000000000000000        0x0 build/consoleio.o
 .rel.text      0x0000000000000000        0x0 build/consoleio.o
 .rel.flat      0x0000000000000000        0x0 build/consoleio.o

.data           0x0000000000103000       0xa0
 *(.data)
 .data          0x0000000000103000        0x4 build/consoleio.o
                0x0000000000103000                consoleColor
 .data          0x0000000000103004        0x0 build/core.o
 *fill*         0x0000000000103004       0x1c 00
 .data          0x0000000000103020       0x80 build/exception-interrupts.o
                0x0000000000103020                exception_messages
 .data          0x00000000001030a0        0x0 build/gdt.o
 .data          0x00000000001030a0        0x0 build/hardware-interrupts.o
 .data          0x00000000001030a0        0x0 build/idt.o
 .data          0x00000000001030a0        0x0 build/system.o

.igot.plt       0x00000000001030a0        0x0
 .igot.plt      0x0000000000000000        0x0 build/consoleio.o

.flat           0x00000000001030a0      0x1e8
 .flat          0x00000000001030a0       0x25 build/gdt-install.o
                0x00000000001030a0                setGdt
                0x00000000001030bd                idt_load
 *fill*         0x00000000001030c5        0x3 00
 .flat          0x00000000001030c8       0x99 build/irq.o
                0x00000000001030c8                irq0
                0x00000000001030cf                irq1
                0x00000000001030d6                irq2
                0x00000000001030dd                irq3
                0x00000000001030e4                irq4
                0x00000000001030eb                irq5
                0x00000000001030f2                irq6
                0x00000000001030f9                irq7
                0x0000000000103100                irq8
                0x0000000000103107                irq9
                0x000000000010310e                irq10
                0x0000000000103115                irq11
                0x000000000010311c                irq12
                0x0000000000103123                irq13
                0x000000000010312a                irq14
                0x0000000000103131                irq15
 *fill*         0x0000000000103161        0x3 00
 .flat          0x0000000000103164      0x124 build/isr.o
                0x0000000000103164                isr0
                0x000000000010316e                isr1
                0x0000000000103178                isr2
                0x0000000000103182                isr3
                0x000000000010318c                isr4
                0x0000000000103196                isr5
                0x00000000001031a0                isr6
                0x00000000001031aa                isr7
                0x00000000001031b4                isr8
                0x00000000001031bc                isr9
                0x00000000001031c6                isr10
                0x00000000001031ce                isr11
                0x00000000001031d6                isr12
                0x00000000001031de                isr13
                0x00000000001031e3                isr14
                0x00000000001031e8                isr15
                0x00000000001031ef                isr16
                0x00000000001031f6                isr17
                0x00000000001031fd                isr18
                0x0000000000103204                isr19
                0x000000000010320b                isr20
                0x0000000000103212                isr21
                0x0000000000103219                isr22
                0x0000000000103220                isr23
                0x0000000000103227                isr24
                0x000000000010322e                isr25
                0x0000000000103235                isr26
                0x000000000010323c                isr27
                0x0000000000103243                isr28
                0x000000000010324a                isr29
                0x0000000000103251                isr30
                0x0000000000103258                isr31

.bss            0x00000000001032a0     0x48a0
                0x00000000001032a0                sbss = .
 *(COMMON)
 COMMON         0x00000000001032a0        0x4 build/consoleio.o
                0x00000000001032a0                conPos
 COMMON         0x00000000001032a4       0x1e build/core.o
                0x00000000001032a4                gp
                0x00000000001032aa                gdt
 *fill*         0x00000000001032c2       0x1e 00
 COMMON         0x00000000001032e0      0x820 build/idt.o
                0x00000000001032e0                idtp
                0x0000000000103300                idt
 *(.bss)
 .bss           0x0000000000103b00        0x0 build/consoleio.o
 .bss           0x0000000000103b00        0x0 build/core.o
 .bss           0x0000000000103b00        0x0 build/exception-interrupts.o
 .bss           0x0000000000103b00        0x0 build/gdt.o
 .bss           0x0000000000103b00       0x40 build/hardware-interrupts.o
                0x0000000000103b00                irq_routines
 .bss           0x0000000000103b40        0x0 build/idt.o
 .bss           0x0000000000103b40        0x0 build/system.o
 .bss           0x0000000000103b40     0x4000 build/loader.o
                0x0000000000107b40                ebss = .
LOAD build/consoleio.o
LOAD build/core.o
LOAD build/exception-interrupts.o
LOAD build/gdt.o
LOAD build/hardware-interrupts.o
LOAD build/idt.o
LOAD build/system.o
LOAD build/gdt-install.o
LOAD build/irq.o
LOAD build/isr.o
LOAD build/loader.o
OUTPUT(cd/kernel.elf elf32-i386)

.comment        0x0000000000000000       0x23
 .comment       0x0000000000000000       0x23 build/consoleio.o
                                         0x24 (size before relaxing)
 .comment       0x0000000000000000       0x24 build/core.o
 .comment       0x0000000000000000       0x24 build/exception-interrupts.o
 .comment       0x0000000000000000       0x24 build/gdt.o
 .comment       0x0000000000000000       0x24 build/hardware-interrupts.o
 .comment       0x0000000000000000       0x24 build/idt.o
 .comment       0x0000000000000000       0x24 build/system.o

.note.GNU-stack
                0x0000000000000000        0x0
 .note.GNU-stack
                0x0000000000000000        0x0 build/consoleio.o
 .note.GNU-stack
                0x0000000000000000        0x0 build/core.o
 .note.GNU-stack
                0x0000000000000000        0x0 build/exception-interrupts.o
 .note.GNU-stack
                0x0000000000000000        0x0 build/gdt.o
 .note.GNU-stack
                0x0000000000000000        0x0 build/hardware-interrupts.o
 .note.GNU-stack
                0x0000000000000000        0x0 build/idt.o
 .note.GNU-stack
                0x0000000000000000        0x0 build/system.o
loader.asm

Code: Select all

FORMAT ELF

public loader
extrn kmain

section '.text'
align 4
MultiBootHeader:
   dd 0x1BADB002,0x00000003,0xE4524FFB

STACKSIZE equ 0x4000

loader:
   mov esp, stack_loc+STACKSIZE          ; set up the stack
   push eax                           ; pass Multiboot magic number
   push ebx                           ; pass Multiboot info structure
 
   call  kmain                       ; call kernel proper
 
   cli
hang:
   hlt                                ; halt machine should kernel return
   jmp   hang

section '.bss' 
;align 32
stack_loc:
   rb STACKSIZE

Makefile

Code: Select all

#Generate the objects list. Essentially, every .c and .asm file needs a 
#corresponding .o file to be linked in. Pretty simple, even though it 
#looks like creepy voodoo code.
#
#Note: This does *not* use quotes, so don't come in here and try to 
#space it out to make it all pretty. Learned that the hard way I did...
OBJS := $(patsubst source/%.c,build/%.o,$(wildcard source/*.c)) \
		$(patsubst assembly/%.asm,build/%.o,$(wildcard assembly/*.asm))

vpath %.c   source
vpath %.h   include
vpath %.asm assembly

.PHONY : all

all: core.iso

core.iso : cd/kernel.elf
	mkisofs -R -quiet -b grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -boot-info-table -o core.iso cd
	@echo ISO Created. Build seems to be completely successful. Hooray!

cd/kernel.elf : $(OBJS)
	ld -T linker.ld -melf_i386 -Map map.txt -o cd/kernel.elf $^
	
build/%.o : %.asm
	./fasm $< $@

build/%.o : %.c
	gcc -o $@ -c $< -Wall -Wextra -fno-builtin -nostdlib -nostartfiles -nodefaultlibs -m32 -Iinclude
	
.PHONY : clean
	
clean:
	-rm -f build/*.o
	-rm -f core.iso
	-rm -f cd/kernel.elf
	
Many thanks if you can see the issue, and holler if you need to see another file. This has basically halted my development and I really have no clue how to fix it without writing a custom bootloader, which I'm really trying to avoid at the moment. (I'll do it eventually, but baby steps, you know?)

-Nicholas
js
Member
Member
Posts: 38
Joined: Thu Feb 26, 2009 1:45 am

Re: GRUB Fails when loading Kernel >32k

Post by js »

In your loader asm file, you need to put the multiboot header in a separate section (not .text, but .multiboot or any unused name), and in your linker script you need to insert that section as early as possible (just before .text in your case).

Plus I personnaly recommend using . = 0x00100080; because as the linker tries to align everything big enough on a 4K boundary, with . = 0x00100000; you'll have a 0x80-bytes elf header, zero padding up to 4K and then your kernel. the zero padding is a stupid waste of space, so if you mis-align your kernel by 0x80 bytes on purpose, there's some space for the elf header just before your kernel, thus you avoid the padding. But this is just personnal taste.
thegamefreak0134
Posts: 14
Joined: Thu Jan 08, 2009 1:54 am

Re: GRUB Fails when loading Kernel >32k

Post by thegamefreak0134 »

Holy crap, that worked like a charm. ^_^

So let me see if I get this straight: too much code was causing the multiboot header to end up lying outside of the range that GRUB was searching for it? That's good to know. Thank you! I want to send you cookies now.
Post Reply