Problem with AMD64 ld with linker script

Peter Bindels dascandy@gmail.com
Thu Oct 5 17:00:00 GMT 2006


Hi list,

I'm developing a kernel for amd64 platforms. I'd prefer it to be in
ELF format with 4k-alignment between sections. Also, I have to specify
a load address and a link address for use in the output, as it's used
by my boot loader. The addresses are in the higher-half of the address
space, all code is compiled with -mcmodel=kernel with gcc 4.1.1. I'm
using binutils 2.17.

When I link the kernel without a linker script, the sections are
aligned according to their minimum alignment (which is 2^4 for most,
2^12 for bss since I had to put a page-aligned thing in it). I can't
specify the load and the virtual address however.

As soon as I use a linker script, the alignments for all sections
immediately jump to 2^20, with no possible way to get the alignment
down. As a result of that, the .text is at 0x100000, .data is at
0x200000 and .init (kernel-specific section) is at 0x300000. That
results in a binary over 3 megabytes in size, albeit very sparse,
where I wanted about a 64k binary.

I've tried a load of forms in the linker file that could have worked,
most did nothing, some of which enlarged it even more. I'm out of
options and I still can't figure out where the alignment is coming
from.

Here's my linker script, it's linking from a single object file.

--------- script-
UTPUT_FORMAT("elf64-x86-64")
ENTRY("_start")

PHDRS {
        header PT_PHDR FILEHDR PHDRS;
        init PT_LOAD AT(0x90000);
        text PT_LOAD AT(0x100000);
        data PT_LOAD AT(0x100000 + LENGTH(text));
}

SECTIONS {
  . = ALIGN(0x1000);
  .init 0xFFFFFFFFD0000000 : {
        KEEP(*(.init*))
        init_ctors_begin = .;
        KEEP(*(.ctors))
        init_ctors_end = .;
  } :init
  . = ALIGN(0x1000);
  .text 0xFFFFFFFFC0000000 : {
        KEEP (*(.text*))
        KEEP (*(.rodata))
  } :text
  . = ALIGN(0x1000);
  .data 0xFFFFFFFFC4000000 : {
        KEEP (*(.data))
        KEEP (*(COMMON))
        kernel_max_mem = .;
  } :data
  .bss (ADDR(.data) + SIZEOF(.data)) : {
        KEEP (*(.bss))
  } :data
        /DISCARD/ : {
                *(.eh_frame)
                *(.fini*)
                *(.dtors)
                *(.rel*)
        }
}
-------- end script

The phdrs statement is probably wrong on the data bit, but that
shouldn't make it 3mb.

Am I doing something very wrong, is this a bug or what is causing my inability?

Thanks in advance,
Peter Bindels



More information about the Binutils mailing list