6

I have a linker script for a kernel with two absolute symbols: _kernel_start and _kernel_end. However, I get a linker relocation error for only _kernel_end:

In function `kernel::mem::mm::setup_memorymap':
/home/virtlink/kernel/src/mem/mm.rs:25:(.text._ZN3mem2mm15setup_memorymap):
  relocation truncated to fit: R_X86_64_PC32 against symbol `_kernel_end'
  defined in *ABS* section in ./kernel.bin

There have been many questions here on SO about this error, but I found none that solves my particular problem.

Apparently, this:

_kernel_start = .;

...is treated as 32-bit, whereas this:

. += KERNEL_BASE;
_kernel_end = . - KERNEL_BASE;

...is treated as 64-bit. If I move the _kernel_end symbol above the . += KERNEL_BASE line like this:

_kernel_end = .;
. += KERNEL_BASE;

...then it works again. But I want _kernel_end at the end of my linker script.

The linker script puts the boot code at the start of memory, and the rest of the code in the higher-half of the 64-bit virtual memory space. It looks like this:

OUTPUT_FORMAT(elf64-x86-64)

KERNEL_BASE = 0xFFFFFFFF80000000;

SECTIONS
{
    /* Boot code at 1 MiB */
    . = 1M;
    _kernel_start = .;
    .boot :
    {
        KEEP( *(.multiboot) )
        *(.boot)
        *(.bootdata)
    }

    /* Kernel code at high virtual address. */
    . += KERNEL_BASE;
    .text ALIGN(4K) : AT(ADDR(.text) - KERNEL_BASE)
    {
        *(.text)
        *(.gnu.linkonce.t*)
    }
    .data ALIGN(4K) : AT(ADDR(.data) - KERNEL_BASE)
    {
        *(.data)
        *(.gnu.linkonce.d*)
    }
    .rodata ALIGN(4K) : AT(ADDR(.rodata) - KERNEL_BASE)
    {
        *(.rodata)
        *(.gnu.linkonce.r*)
    }
    .bss ALIGN(4K) : AT(ADDR(.bss) - KERNEL_BASE)
    {
        *(COMMON)
        *(.bss)
        *(.bss.*)
        *(.gnu.linkonce.b*)
    }
    _kernel_end = . - KERNEL_BASE;

    /DISCARD/ :
    {
        *(.comment)
        *(.eh_frame)
    }
}

The kernel is really small, so _kernel_start = 0x00100000 and _kernel_end = 0x00142000. It shouldn't give me relocation errors.

How can I rewrite the linker script such that _kernel_end give me no more relocation errors? I don't want to use mcmodel=large just for this one symbol.


Here's the code in which I'm using the symbols. It's Rust.

fn get_kernel_location() -> (*const u8, *const u8) {
    extern {
        static _kernel_start: u8;
        static _kernel_end: u8;
    }

    let kernel_start: *const u8 = &_kernel_start;
    let kernel_end: *const u8 = &_kernel_end;

    println!("{:p}", kernel_start);
    println!("{:p}", kernel_end);

    (kernel_start, kernel_end)
}

Here are the entries in the relocation table of the Rust compiled object file:

  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000000012  058800000009 R_X86_64_GOTPCREL 0000000000000000 _kernel_end - 4
000000000019  058900000009 R_X86_64_GOTPCREL 0000000000000000 _kernel_start - 4
Daniel A.A. Pelsmaeker
  • 47,471
  • 20
  • 111
  • 157
  • I think you need to show the code corresponding to the problematic relocation, in mm.rs:25. It sounds like you need something like mcmodel=kernel in gcc. – Jonathon Reinhart Apr 08 '15 at 10:17
  • Just noticed that you want to avoid that option. – Jonathon Reinhart Apr 08 '15 at 10:19
  • Why do you subtract the `KERNEL_BASE` when placing the `_kernel_end`? The linker adds up the addresses and you made it start the calculation at `KERNEL_BASE`, so `_kernel_end` should be enough – maxdev Jun 23 '15 at 11:12
  • @maxdev The kernel is loaded into physical memory at the 1 MiB mark, and I want `_kernel_end` to be the end of the kernel in physical memory (i.e. 1 MiB + kernel size). Since I added `KERNEL_BASE` to the current address, I have to subtract it again to get the end of the physical kernel. – Daniel A.A. Pelsmaeker Jun 23 '15 at 11:14
  • Ah, I see what you're trying to do. This approach is quite hacky and I'd suggest you to write an additional loader binary that is linked to lower memory, sets up paging and then directly loads the binary to higher memory (its not much effort). (Only an opinion) – maxdev Jun 23 '15 at 11:17
  • What are the exact compilation commands and your distro? Related: http://stackoverflow.com/questions/9827157/what-does-keep-mean-in-a-linker-script – Ciro Santilli OurBigBook.com Oct 06 '15 at 21:47

0 Answers0