Page 1 of 1

Grub: error loading a kernel when compiled with -g

Posted: Wed Apr 11, 2007 1:44 pm
by BluReaver
Hi

I'm using Bochs-2.3 compiled with the --enable-gdb-stub option under mandriva 10.2 linux, with gcc 3.4.3 and nasm 0.98.39.

Basically, I'm trying to debug a simple kernel to find where a fault is triggered, using gdb remotely.

My kernel (a mixture of C and ASM) is loaded by Grub, and this works fine normally. However, if I compile with the -g option in gcc (I believe this to be the correct switch to compile with debugging information, please tell me if I'm wrong), grub complains that the kernel does not fit in memory.

I find this strange as the kernel is only ~20kb, and the emulated memory size is 128mb.

I am aware that it sometimes reports this message even if the error is something else, but what other scenarios cause this error?

I tried using 'strip -d kernel.bin -o kernel.debug', but this does not affect the size of the kernel.bin binary (or the error message for that matter). I'm unfamiliar with this tool though, so I am possibly doing something stupid.

My kernel format is elf32-i386, and it is loaded at 0x00100000.

Hope I've provided enough information. Do you need to see my makefile/link script?
Even suggestions/guesses/hunches are welcome :)

Thanks

Posted: Wed Apr 11, 2007 2:19 pm
by BluReaver
There is something strange going on...

As I explained, when I compile my code normally, it all works fine. However, now I've also discovered that if I comment a few lines out, I get the dreaded "Error 28: Selected item cannot fit into memory" again. Why should that be?

Code: Select all

void main()

{

	InitVideo();

	SetupGDT();

	SetupIDT();

	InstallISRs();

	//__asm__ __volatile__ ("sti");

	

	//ClearScreen(0x1E);

	//PrintString("Hello world");

}
With those lines uncommented, it loads fine, but when they are commented, grub complains that it does not fit in memory! It is so bizarre!

Thanks again :)

Re: Grub: error loading a kernel when compiled with -g

Posted: Wed Apr 11, 2007 3:02 pm
by mystran
BluReaver wrote:grub complains that the kernel does not fit in memory.
Ten times out of nine, that happens because some section in the binary is marked for loading and has it's physical address set to some non-sensical value. Typical examples of this happening are stuff like trying to link kernel at 3GB and forgetting to tell the linker what it's not really where the binary will be loaded. :)

Now, "objdump -h <binary>" will show the relevant headers. You get output something like this:

Code: Select all


kernel:     file format elf32-i386

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         00009eb2  00100000  00100000  00001000  2**5
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .data         00001710  00109ec0  00109ec0  0000aec0  2**5
                  CONTENTS, ALLOC, LOAD, DATA
  2 .bss          0001c818  00110000  00110000  0000d000  2**15
                  ALLOC
  3 .note.GNU-stack 00000000  00000000  00000000  0000d000  2**0
                  CONTENTS, READONLY
  4 .comment      000005d8  00000000  00000000  0000d000  2**0
                  CONTENTS, READONLY

From the above we can see that in my kernel there's .text and .data which are to be loaded, and .bss which is just zeroed. The rest are irrelevant..

There are various other flags to objdump get various other kinds of header information (-p gives program header if you've got an ELF kernel)...

Most likely you'll find some section which is supposed to be loaded at some crazy address. Mostly likely it's either a problem with your linker script, or the parameters you give to your linker..

Posted: Wed Apr 11, 2007 3:04 pm
by mystran
If you give your linker script, your Makefile (or at least linker command line) and the output of objdump with either -h or -p (or both) for the failing kernel (say, one with debugging symbols), it'll be easier to figure out what exactly could be the problem.

Posted: Thu Apr 12, 2007 5:13 am
by BluReaver
Thanks very much for you response :)

This is the output from objdump:

Code: Select all

[root@neptune OS2]# objdump -h ./disk/boot/kernel.bin

./disk/boot/kernel.bin:     file format elf32-i386

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         00001000  00100000  00100000  00001000  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .data         00001000  00101000  00101000  00002000  2**5
                  CONTENTS, ALLOC, LOAD, DATA
  2 .bss          00002844  00102000  00102000  00003000  2**5
                  ALLOC
  3 .note.GNU-stack 00000000  00000000  00000000  00003000  2**0
                  CONTENTS, READONLY
  4 .comment      000000c8  00000000  00000000  00003000  2**0
                  CONTENTS, READONLY
  5 .rodata       00000279  000000c8  000000c8  000000c8  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA

[root@neptune OS2]# objdump -p ./disk/boot/kernel.bin

./disk/boot/kernel.bin:     file format elf32-i386

Program Header:
    LOAD off    0x00000000 vaddr 0x00000000 paddr 0x00000000 align 2**12
         filesz 0x00000341 memsz 0x00000341 flags r--
    LOAD off    0x00001000 vaddr 0x00100000 paddr 0x00100000 align 2**12
         filesz 0x00001000 memsz 0x00001000 flags r-x
    LOAD off    0x00002000 vaddr 0x00101000 paddr 0x00101000 align 2**12
         filesz 0x00001000 memsz 0x00003844 flags rw-
   STACK off    0x00000000 vaddr 0x00000000 paddr 0x00000000 align 2**2
         filesz 0x00000000 memsz 0x00000000 flags rwx
My linker script is fairly simple and was just copied out a tutorial (ashamedly) :oops:

Code: Select all

OUTPUT_FORMAT("elf32-i386")
ENTRY(start)
phys = 0x00100000;
SECTIONS
{
  .text phys : AT(phys) {
    code = .;
    *(.text)
    . = ALIGN(4096);
  }

  .data : AT(phys + (data - code))
  {
    data = .;
    *(.data)
    . = ALIGN(4096);
  }

  .bss : AT(phys + (bss - code))
  {
    bss = .;
    *(.bss)
    . = ALIGN(4096);
  }
  end = .;
}
And my makefile

Code: Select all

kernel.bin: makefile kernel_asm.o kernel.o screen.o pm.o isr_asm.o isr.o
	ld -T link.ld -o ./disk/boot/kernel.bin kernel_asm.o kernel.o screen.o pm.o isr_asm.o isr.o
	sync

kernel_asm.o: kernel.asm
	nasm -f aout -o kernel_asm.o kernel.asm

kernel.o: kernel.c
	gcc -Wall -g -fstrength-reduce -fomit-frame-pointer -finline-functions -nostdinc -fno-builtin -I./include -c -o kernel.o kernel.c

...similar lines for the rest of the objects have been omitted...
./disk is where i mounted the disk image, and sync is there because it doesn't seem to take effect immediately without it.

Thanks again :)

Posted: Thu Apr 12, 2007 7:24 am
by frank
try adding rodata to your linker script

Code: Select all

.text phys : AT(phys) {
    code = .;
    *(.text)
    *(.rodata)
    . = ALIGN(4096);
  } 

Posted: Thu Apr 12, 2007 3:31 pm
by BluReaver
Thankyou very much Frank, that has fixed the problem :)