Is ELF64 in GRUB2 broken? [SOLVED]
Posted: Tue Sep 30, 2014 12:17 pm
I'm using GRUB 2.02 beta2.113, and once my kernel grows beyond a certain size (_loadEnd - _loadStart) > 64kb, things start going funny.
GRUB seems to be putting things in funny places.
Here's part of my kernel disassembled:
It's a higher half kernel, so that function should be loaded by GRUB at 10c2dc. Here's a memory dump of 10c2dc after GRUB loads the kernel:
The function was actually loaded at 10c2f4 - 24 bytes higher than where it should have been. This only occurs when (_loadEnd - _loadStart) > 64kb.
Here's my linker script:
And my multiboot header:
My whole .text section is being loaded 24 bytes above where it should be. Is this a bug in GRUB, or would something be purposely offsetting the load address?
GRUB seems to be putting things in funny places.
Here's part of my kernel disassembled:
Code: Select all
ffffffff8010c2dc <kmain>:
ffffffff8010c2dc: 55 push rbp
ffffffff8010c2dd: 48 89 e5 mov rbp, rsp
ffffffff8010c2e0: fa cli
ffffffff8010c2e1: f4 hlt
Code: Select all
000000000010c2dc: 0x40 0x60 0x48 0x8b 0x04 0xc5 0x00 0xf0
000000000010c2e4: 0x10 0x80 0x48 0x89 0xc7 0xe8 0x1b 0x04
000000000010c2ec: 0x00 0x00 0xfa 0xf4 0xeb 0xfd 0xc9 0xc3
000000000010c2f4: 0x55 0x48 0x89 0xe5 0xfa 0xf4 0x90 0x5d
Here's my linker script:
Code: Select all
ENTRY(EntryPoint)
VIRT_BASE = 0xFFFFFFFF80000000;
SECTIONS
{
. = 0x100000;
.boot :
{
*(.mbhdr)
_loadStart = .;
*(.boot)
. = ALIGN(4096);
Pml4 = .;
. += 0x1000;
Pdpt = .;
. += 0x1000;
Pd = .;
. += 0x1000;
. += 0x8000;
Stack = .;
}
. += VIRT_BASE;
.text ALIGN(0x1000) : AT(ADDR(.text) - VIRT_BASE)
{
*(.text)
*(.gnu.linkonce.t*)
}
.data ALIGN(0x1000) : AT(ADDR(.data) - VIRT_BASE)
{
*(.data)
*(.gnu.linkonce.d*)
}
.rodata ALIGN(0x1000) : AT(ADDR(.rodata) - VIRT_BASE)
{
*(.rodata*)
*(.gnu.linkonce.r*)
}
_loadEnd = . - VIRT_BASE;
.bss ALIGN(0x1000) : AT(ADDR(.bss) - VIRT_BASE)
{
*(COMMON)
*(.bss)
*(.gnu.linkonce.b*)
}
_bssEnd = . - VIRT_BASE;
/DISCARD/ :
{
*(.comment)
*(.eh_frame)
}
}
Code: Select all
MbHdr:
dd 0xE85250D6 ; magic
dd 0 ; architecture
dd HdrEnd - MbHdr ; length
dd -(0xE85250D6 + 0 + (HdrEnd - MbHdr)) ; checksum
; tags
; sections override
dw 2, 0 ; multiboot_header_tag_address
dd 24
dd MbHdr
dd _loadStart
dd _loadEnd
dd _bssEnd
; entry point override
dw 3, 0 ; multiboot_header_tag_entry_address
dd 12
dd EntryPoint
dd 0 ; align next tag to 8 byte boundry
; request some information from GRUB for the kernel
dw 1, 0 ; multiboot_header_tag_information_request
dd 12
dd 6 ; request multiboot_tag_type_mmap
dd 0 ; align next tag to 8 byte boundry
; end of tags
dw 0, 0 ; MULTIBOOT_TAG_TYPE_END
dd 8
; hdr end mark
HdrEnd: