I'm just trying to code a startup environment for some 64 bit code, because I want to play with the virtualization extensions.
Unfortunately the linker always blows up my kernel with zeros.
The boostrapping code (from 32 bit to 64 bit) should be located at 1MB. This code sets up 4MB identity mapped memory starting at 0x0 and jumps to the 64 bit C-code. At least this is what it is supposed to do
I tried elf64-x86-64 and elf64-little as a target binary in the linker script. Both results are the same.
GCC is the newest 4.4.2, Binutils: newest 2.20.
If I look at the produced ELF File with a Hex-Editor, I can see the ELF header and then a padding until 0x100000.
Why does the linker do this? It's not necessary.
If I modify the linker script so that the location is 0xC000000, the file is not 3GB big. It's just 2MB.
readelf says this:
Code: Select all
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .bootstrap PROGBITS 0000000000100000 00100000
000000000000008a 0000000000000000 AX 0 0 16
[ 2] .rela.bootstrap RELA 0000000000000000 001030a8
0000000000000000 0000000000000018 26 1 8
[ 3] .text PROGBITS 000000000010008c 0010008c
0000000000000f74 0000000000000000 AX 0 0 4
[ 4] .eh_frame PROGBITS 0000000000101000 00101000
0000000000000040 0000000000000000 A 0 0 8
[ 5] .rela.eh_frame RELA 0000000000000000 001030a8
0000000000000000 0000000000000018 26 4 8
[ 6] .data PROGBITS 0000000000101040 00101040
0000000000000fc0 0000000000000000 WA 0 0 4
[ 7] .rela.data RELA 0000000000000000 001030a8
0000000000000000 0000000000000018 26 6 8
[ 8] .bss NOBITS 0000000000102000 00102000
0000000000004000 0000000000000000 WA 0 0 4
[ 9] .stab PROGBITS 0000000000000000 00102000
0000000000000198 0000000000000014 11 0 4
[10] .rel.stab REL 0000000000000000 001030a8
0000000000000000 0000000000000010 26 9 8
[11] .stabstr STRTAB 0000000000000000 00102198
000000000000000d 0000000000000000 0 0 4
[12] .debug_abbrev PROGBITS 0000000000000000 001021a5
0000000000000036 0000000000000000 0 0 1
[13] .debug_info PROGBITS 0000000000000000 001021db
0000000000000056 0000000000000000 0 0 1
[14] .rela.debug_info RELA 0000000000000000 001030a8
0000000000000000 0000000000000018 26 13 8
[15] .debug_line PROGBITS 0000000000000000 00102231
000000000000003d 0000000000000000 0 0 1
[16] .rela.debug_line RELA 0000000000000000 001030a8
0000000000000000 0000000000000018 26 15 8
[17] .debug_frame PROGBITS 0000000000000000 00102270
0000000000000040 0000000000000000 0 0 8
[18] .rela.debug_frame RELA 0000000000000000 001030a8
0000000000000000 0000000000000018 26 17 8
[19] .debug_loc PROGBITS 0000000000000000 001022b0
000000000000004c 0000000000000000 0 0 1
[20] .debug_pubnames PROGBITS 0000000000000000 001022fc
000000000000001b 0000000000000000 0 0 1
[21] .rela.debug_pubna RELA 0000000000000000 001030a8
0000000000000000 0000000000000018 26 20 8
[22] .debug_aranges PROGBITS 0000000000000000 00102317
0000000000000030 0000000000000000 0 0 1
[23] .rela.debug_arang RELA 0000000000000000 001030a8
0000000000000000 0000000000000018 26 22 8
[24] .debug_str PROGBITS 0000000000000000 00102347
0000000000000042 0000000000000001 MS 0 0 1
[25] .shstrtab STRTAB 0000000000000000 00102389
00000000000000e4 0000000000000000 0 0 1
[26] .symtab SYMTAB 0000000000000000 00102b70
0000000000000450 0000000000000018 27 38 8
[27] .strtab STRTAB 0000000000000000 00102fc0
00000000000000e5 0000000000000000 0 0 1
Does anybody have a clue why this is done? Any help would be great.
Thanks and merry christmas
Some code:
start.S
Code: Select all
PAGE_SIZE equ 0x1000
STACK_SIZE equ 16*1024
PML2 equ 0x1000
PML3 equ PML2+PAGE_SIZE
PML4 equ PML3+PAGE_SIZE
;---------------------------------------------------------------------------------------------
MODULEALIGN equ 1<<0
MEMINFO equ 1<<1
FLAGS equ MODULEALIGN | MEMINFO
MAGIC equ 0x1BADB002
CHECKSUM equ -(MAGIC + FLAGS)
[extern main]
[global bootstrap]
;---------------------------------------------------------------------------------------------
section .text
[BITS 32]
align 4
MultiBootHeader:
dd MAGIC
dd FLAGS
dd CHECKSUM
bootstrap:
cli
; clear 3 pages of pagetables
mov edi, PML2
xor eax, eax
mov ecx, 3*4096/4
rep stosd
; set up pagetables
mov dword [PML2], 0x87 ; single 4 MB id mapping PML2
mov dword [PML3], PML2 | 7 ; single entry at PML3
mov dword [PML4], PML3 | 7 ; single entry at PML4
; load the GDT
lgdt [gdt_desc]
; set PSE, PAE
mov eax, 0x30
mov cr4, eax
; long mode
mov ecx, 0xc0000080
rdmsr
or eax, 0x100
wrmsr
; enable pagetables
mov eax, PML4
mov cr3, eax
; turn on long mode and paging
mov eax, 0x80010001
mov cr0, eax
jmp SEL_CS:code64
[BITS 64]
code64:
mov ax, SEL_DS
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
mov esp, bootStack
call main
inf:
jmp inf
;---------------------------------------------------------------------------------------------
section .data
gdt_desc:
dw GDT_LEN-1
dd gdt
align 8
gdt db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ; 0x00 dummy
gdt_cs db 0xff, 0xff, 0x00, 0x00, 0x00, 0x9b, 0xaf, 0x00 ; 0x08 code64
gdt_ds db 0xff, 0xff, 0x00, 0x00, 0x00, 0x93, 0xaf, 0x00 ; 0x18 data64
GDT_LEN equ $ - gdt
SEL_CS equ gdt_cs - gdt
SEL_DS equ gdt_ds - gdt
;---------------------------------------------------------------------------------------------
section .bss
align 32
global bootStack
bootStack:
resb STACK_SIZE
Code: Select all
int main(void);
int main()
{
for(;;);
return 0;
}
Code: Select all
OUTPUT_FORMAT(elf64-x86-64)
ENTRY (bootstrap)
SECTIONS{
. = 0x100000;
.bootstrap :
{
obj/start.o (.text)
}
. += 0x0;
.text : AT(ADDR(.text) - 0x0)
{
_code = .;
*(.text)
*(.rodata)
. = ALIGN(4096);
}
.data : AT(ADDR(.data) - 0x0)
{
_data = .;
*(.data)
. = ALIGN(4096);
}
.ehframe : AT(ADDR(.ehframe) - 0x0)
{
_ehframe = .;
*(.ehframe)
. = ALIGN(4096);
}
.bss : AT(ADDR(.data) - 0x0)
{
_bss = .;
*(.bss)
. = ALIGN(4096);
}
_end = .;
/DISCARD/ :
{
*(.comment)
}
}
Just saw that the PML2 constant was set to 0x1000.
I was pretty sure that this didn't this behaviour since it is not a symbol, but I changed it anyway. As expected, the output remains the same