OSDev.org
https://forum.osdev.org/

[SOLVED] 64-bit Higher Half relocation issues
https://forum.osdev.org/viewtopic.php?f=1&t=32475
Page 1 of 1

Author:  isaacwoods [ Sun Oct 08, 2017 3:09 pm ]
Post subject:  [SOLVED] 64-bit Higher Half relocation issues

Hi, I'm trying to get a 64-bit higher half kernel working, which has been somewhat challenging. I opted to go with a 32-bit bootstrap placed in the physical address space, in which I set up identity mapping and enter Long Mode, then set up real higher-half page tables and then jump into the higher-half. The relevant part of the bootstrap code is:
Code:
extern Entry64
InLongMode:
  ; Reload every data segment with 0 (Long-mode doesn't use segmentation)
  mov ax, 0
  mov ss, ax
  mov ds, ax
  mov es, ax
  mov fs, ax
  mov gs, ax

  ; This sets up the higher half page tables
  call MapHigherHalf

  ; Correct the address of the Multiboot structure
  add rdi, 0xffffff0000000000

  lea rax, [Entry64]
  jmp rax


Entry64 is defined in another file (linked into the virtual address space with a base of 0xffffff0000100000):
Code:
bits 64
section .text
global Entry64
Entry64:
  ; Print OKAY
  mov rax, 0x2f592f412f4b2f4f
  mov qword [0xb8000], rax  ; TODO: use proper virtual address (this would only work because the identity mapping is still also in place)
  hlt


This is all linked into one executable (with the bootstrap at 0x100000 and the rest of the kernel at 0xffffff0000100000) with:
Code:
KERNEL_LMA = 0x100000;
KERNEL_VMA = 0xffffff0000100000;

SECTIONS
{
  /*
   * First, we physically-map a bootstrap section that will load the 64-bit code. This is required
   * because we haven't enabled paging yet, and so code that uses virtual addresses won't work.
   */
  . = KERNEL_LMA;

  .bootstrap.text :
  {
    KEEP(*(.multiboot))
    *bootstrap.o (.text .text.*)
    . = ALIGN(4K);
  }

  .bootstrap.bss :
  {
    *bootstrap.o (.bss)
    . = ALIGN(4K);
  }

  .bootstrap.rodata :
  {
    *bootstrap.o (.rodata .rodata.*)
    . = ALIGN(4K);
  }

  /*
   * Then, we place everything else at proper virtual addresses
   */
  . = KERNEL_VMA;

  .rodata : AT(ADDR(.rodata) - KERNEL_VMA)
  {
    *(EXCLUDE_FILE(bootstrap.o) .rodata .rodata.*)
    . = ALIGN(4K);
  }
  ...


However, it seems to emit the incorrect relocation to load the address of Entry64 (I don't understand why this doesn't output a R86_64_64 type relocation):
Code:
relocation truncated to fit: R_X86_64_32S against symbol `Entry64' defined in .text section in /home/isaac/Documents/RustOS/build/x86_64/entry64.o


There also seem to be problems with Entry64:
Code:
entry64.s:11:(.stab+0x14): relocation truncated to fit: R_X86_64_32 against `.text'
entry64.s:11:(.stab+0x20): relocation truncated to fit: R_X86_64_32 against `.text'
entry64.s:12:(.stab+0x2c): relocation truncated to fit: R_X86_64_32 against `.text'
entry64.s:12:(.stab+0x38): relocation truncated to fit: R_X86_64_32 against `.text'


What's causing these issues, and is this even a sensible approach to 64-bit higher half? I came across this thread and tried to find the NASM version of movabs without success, but I think it should've just loaded the 64-bit addresses correctly? Thank you in advance, and sorry if I've cluttered the post with too much code etc.

Author:  Korona [ Sun Oct 08, 2017 3:41 pm ]
Post subject:  Re: 64-bit Higher Half relocation issues

Code:
entry64.s:11:(.stab+0x14): relocation truncated to fit: R_X86_64_32 against `.text'

means that the linker cannot satisfy a relocation that has an offset larger than 4 GiB.

In 64-bit code things like loads from memory and jumps/calls are still limited to 4 GiB. As the address space is much larger, instead of 32-bit absolute offsets RIP-relative offsets are used. If you want absolute 64-bit addressing, you need to load the address into a register first (using movabs).

The offending code is
Code:
lea rax, [Entry64]

Use
Code:
movabs rax, Entry64

instead. (I'm not sure if your assembler uses the mov mnenomic for the movabs instruction but considering that your code does assemble with 64-bit mov instructions, I guess it does.)

Author:  isaacwoods [ Sun Oct 08, 2017 4:05 pm ]
Post subject:  Re: 64-bit Higher Half relocation issues

Okay, so NASM doesn't provide movabs, but I've replaced the
Code:
lea rax, [Entry64]

with:
Code:
mov rax, qword Entry64

which seems to disassemble to (obviously it won't be clear whether this actually does the relocation correctly until the link succeeds):
Code:
48 b8 00 00 00 00 00 00 00 00 movabs rax, 0x0


However, I still have problems. This hasn't got rid of the relocation problems in Entry64, nor has it produced correct code for this (with or without the 'qword'):
Code:
add rdi, qword 0xffffff0000000000

turns into:
Code:
48 83 c7 00       add rdi, 0x0

The 0x48 prefix leads me to think its worked out it needs to produce 64-bit code, but then it only emits a 1-byte immediate!

Author:  Korona [ Sun Oct 08, 2017 4:46 pm ]
Post subject:  Re: 64-bit Higher Half relocation issues

There is no "add r/m64, imm64". movabs is the only instruction that takes a 64-bit immediate value. So load the value into a register first and then add it.

Author:  Octocontrabass [ Sun Oct 08, 2017 6:39 pm ]
Post subject:  Re: 64-bit Higher Half relocation issues

BaconWraith wrote:
What's causing these issues, and is this even a sensible approach to 64-bit higher half?

Most instructions can only use 32-bit immediates and offsets, even though you're in 64-bit mode. The only instruction that can use a 64-bit immediate or offset is MOV. (AT&T syntax calls this "movabs".)

Most developers choose a kernel base address around -2GB (0xFFFFFFFF80000000) so kernel symbols can use R_X86_64_32S relocations. This choice also gives the most freedom to user-mode software, since the lowest 2GB of address space may use both R_X86_64_32 and R_X86_64_32S relocations.

BaconWraith wrote:
I came across this thread and tried to find the NASM version of movabs without success, but I think it should've just loaded the 64-bit addresses correctly?

The NASM equivalent of movabs looks like this:
Code:
mov <r64>, qword <symbol>
mov al/ax/eax/rax, [qword <symbol>]
mov [qword <symbol>], al/ax/eax/rax

Author:  isaacwoods [ Tue Oct 10, 2017 11:41 am ]
Post subject:  Re: 64-bit Higher Half relocation issues

Thank you both for your replies! I've read up a little on that and probably should've known that I needed to use mov to load 64-bit immediates :oops: . I've moved the kernel base to 0xffffffff80000000, but this doesn't get rid of the .stab relocation truncations. Looking into it, .stab seems to be a obsolete debug symbol format, so I tried making NASM use DWARF with -Fdwarf and this seems to fix the relocation issues with that. Of course, it still doesn't work, but I'll try to figure out that on my own! Thank you very much again for your help and advice, and sorry for it being such a simple set of fixes

Page 1 of 1 All times are UTC - 6 hours
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/