Page 1 of 1
Not enough room for program headers (allocated 2, need 4)???
Posted: Sun Jul 29, 2007 5:36 pm
by hanumant
I cant make anything out of this ?? my linker script is giving me a lot of grief. I am using cygwin with gcc cross compiler
OUTPUT_FORMAT("elf32-i386")
ENTRY(start)
SECTIONS
{
. = 0x100000;
.setup :
{
*(.setup)
}
. += 0xC0000000;
.text : AT(ADDR(.text) - 0xC0000000)
{
*(.text)
*(.rodata)
}
.data ALIGN (4096) : AT(ADDR(.data) - 0xC0000000)
{
*(.data)
}
.bss ALIGN (4096) : AT(ADDR(.bss) - 0xC0000000)
{
_sbss = .;
*(COMMON)
*(.bss)
_ebss = .;
}
}
I need help!!!!!!!
error/usr/cross/bin/i586-elf-ld: kernel: Not enough room for program headers (allocated 2, need 4)
/usr/cross/bin/i586-elf-ld: final link failed: Bad value
Posted: Mon Jul 30, 2007 2:08 am
by JamesM
Are you making a higher-half kernel? Does it link when you take out all the 0xC0000000 crap? I.e. is it that that's the problem?
JamesM
Posted: Mon Jul 30, 2007 2:24 am
by AJ
I'm guessing your setup section at 0x100000 sets up paging and then jumps to the rest of the kernel at 0xC0000000.
I'm just wondering whether your linker is trying to fill the values between 0x100000 and 0xC0000000 with padding. If that's the case, it's trying to create a (nearly) 3GB file.
I find the easiest way to do this is to load a second-stage loader via GRUB (kernel=mysecondstageloader.sys), and load the
actual kernel as a module (module=mykernel.sys). Your second stage loader can then be purely linked at 0x100000 and the kernel at 0xC0000000. The second stage loader enables paging then relocates the kernel and jumps to it.
Of course, there are other ways (and it may be that your linker way can work - I just don't like it
). One of these involves doing funny things with the GDT - I think that's covered in the wiki. I just like the second-stage loader way because it means that I can do some other setup things too before launching the kernel in a friendlier environment.
Sorry I didn't directly answer the linker problem - I'm no expert with ld!
HTH,
Adam
Posted: Mon Jul 30, 2007 12:30 pm
by jnc100
AJ wrote:I'm just wondering whether your linker is trying to fill the values between 0x100000 and 0xC0000000 with padding
It really shouldn't if its producing elf output...
@hanumantt: google shows this is quite a common problem, but not mentioned explicitly with osdev. In an ELF file you have section headers and program (segment) headers. The program headers have to exist in a section of the output file, just like everything else. The problem you are getting is that ld makes a one-pass attempt to work out the number of program headers needed, then generates a section large enough to hold them. Sometimes it manages to get it wrong though.
One possible reason I saw mentioned is that you might not be including all your input sections into the output, although personally I can't see why this should make a difference. Maybe you could try adding something like *(.rdata) to .text. In addition, if you're using c++ you should include your global constructors and destructors.
Another possible solution I came across is to define the program headers manually, with a PHDRS region before the SECTIONS in the linker script. Program headers are really useful in loading a program into a system, so ordinarily you have to get them right. I wonder, though, whether grub relies on the section headers instead when loading a kernel (as it provides you with a _section_ header array rather than a program header one in the multiboot struct). In that case, you might not need any program headers and I wonder whether just putting PHDRS { } into your linker script near the top would solve your problem. Of course, this is all just speculation as I've never had this problem using an i586-elf-ld binutils with a linker script that defines more sections than just .text, .data and .bss. Admittedly I'm not doing a higher half kernel, though.
Regards,
John.