LD does not output correct VMAs

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
HyperAssembler
Member
Member
Posts: 36
Joined: Thu Sep 04, 2014 5:24 pm
Location: !SIGSEGV

LD does not output correct VMAs

Post by HyperAssembler »

Hi,
I encountered this weird issue while trying to link object files.

LD seems to only put the very first segment into the correct VMA and everything else just goes wild.

OBJ files are compiled by gcc with mcmodel=kernel.

The VMA of the kernel is (0xFFFFFFFF8000000 or -2GB)
The PMA of the kernel is (0x4000000 or 64MB)

Here is my linker script:

Code: Select all

OUTPUT_FORMAT(elf64-x86-64)
ENTRY(HAL_ENTRY_PADDR)
OUTPUT_ARCH(i386:x86-64)

SECTIONS
{
  . = HAL_KERNEL_BASE_VADDR + 0x4000000;

  kernel_start = .;

  .multiboot_header ALIGN(0x1000) : AT(ADDR(.multiboot_header) - HAL_KERNEL_BASE_VADDR)
  {
    *(.multiboot_header)
  }

  .text ALIGN(0x1000) : AT(ADDR(.text) - HAL_KERNEL_BASE_VADDR)
  {
    *(.text)
  }

  .data ALIGN(0x1000) : AT(ADDR(.data) - HAL_KERNEL_BASE_VADDR)
  {
    *(.data)
    *(.rodata*)
  }

  .bss ALIGN(0x1000) : AT(ADDR(.bss) - HAL_KERNEL_BASE_VADDR)
  {
    *(.bss)
    *(COMMON)
  }

  kernel_end = .;
}
Here is the output of the readelf:

Code: Select all

Elf file type is EXEC (Executable file)
Entry point 0x80411000
There are 4 program headers, starting at offset 64

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  LOAD           0x0000000000200000 0xffffffff84000000 0x0000000004000000
                 0x0000000000000030 0x0000000000000030  R      200000
  LOAD           0x0000000000201000 0x0000000000401000 0x0000000080401000
                 0x0000000000012450 0x0000000000012450  R E    200000
  LOAD           0x0000000000214000 0x0000000000614000 0x0000000080614000
                 0x0000000000007022 0x0000000000014560  RW     200000
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RWE    10

 Section to Segment mapping:
  Segment Sections...
   00     .multiboot_header
   01     .text .rodata .eh_frame
   02     .data .bss
   03
As you can see the linker only put the first section which is the multiboot header has expected values: VMA at 0xffffffff84000000 and PMA at 0x4000000. All the other segments seem to have wild VMA and PMAs.

Not sure if I missed something small or I'm doing something fundamentally wrong.

Thanks!
User avatar
crunch
Member
Member
Posts: 81
Joined: Wed Aug 31, 2016 9:53 pm
Libera.chat IRC: crunch
Location: San Diego, CA

Re: LD does not output correct VMAs

Post by crunch »

When I ported everything to x86_64 the linker script was by far the most frustrating part.

Where are you defining HAL_KERNEL_BASE_VADDR ?

Here's my script, for reference:

Code: Select all

OUTPUT_FORMAT("elf64-x86-64")

KERNEL_VIRT   = 0xFFFF800000000000;
KERNEL_PHYS   = 0x100000;

ENTRY(main)
SECTIONS
{

    . = KERNEL_VIRT + KERNEL_PHYS;
    
    _kernel_start = .;
    .text ALIGN(0x1000) : AT(ADDR(.text) - KERNEL_VIRT)
    {
        *(.text)

    }

   .data ALIGN(0x1000) : AT(ADDR(.data) - KERNEL_VIRT)
   {
        *(.data)
        *(.rodata)
   }

   .bss ALIGN(0x1000): AT(ADDR(.bss) -  KERNEL_VIRT)
   {
       *(.bss)
        *(COMMON)
   }

   _kernel_end = .;


   /DISCARD/ :
   {
        *(.comment)
    }
}
HyperAssembler
Member
Member
Posts: 36
Joined: Thu Sep 04, 2014 5:24 pm
Location: !SIGSEGV

Re: LD does not output correct VMAs

Post by HyperAssembler »

Thanks for the reply!

It's inside my asm file:

Code: Select all

HAL_KERNEL_BASE_VADDR equ 0xFFFFFFFF80000000
global HAL_KERNEL_BASE_VADDR 

HAL_ENTRY_PADDR equ hal_entry_32 - HAL_KERNEL_BASE_VADDR
global HAL_ENTRY_PADDR
HyperAssembler
Member
Member
Posts: 36
Joined: Thu Sep 04, 2014 5:24 pm
Location: !SIGSEGV

Re: LD does not output correct VMAs

Post by HyperAssembler »

Update:
I objdumped the elf, the only symbols that start with 0xFFFFFFFF80000000 are

Code: Select all

ffffffff80000000 g       *ABS*  0000000000000000 HAL_KERNEL_BASE_VADDR
ffffffff84000000 g       .bss   0000000000000000 kernel_start
ffffffff84000030 g       .multiboot_header      0000000000000000 kernel_end
plus a bunch of multiboot header symbols.

it's interesting how kernel_start is in bss segment and kernel_end is inside multiboot_header segment.

IT seems like the ld completely ignored the stuff between ".multiboot_header" and "kernel_end"
HyperAssembler
Member
Member
Posts: 36
Joined: Thu Sep 04, 2014 5:24 pm
Location: !SIGSEGV

Re: LD does not output correct VMAs

Post by HyperAssembler »

Okay I solved this problem.
Obviously I somehow added -I option to the linker options and everything was freakin out.

I encountered another "-lgcc" not found issue but I managed to solve it by invoking gcc to link instead of ld.

Hopefully moving from bin to elf yields results that's worth the effort.
Post Reply