Why ALIGN affects section's file offset?
Posted: Wed Jun 29, 2011 3:10 am
When I am testing my code, I found a strange relevance between "align" and "file offset": the offset of first section in ELF is related to the biggest alignment used in asm.
My understand is "align" will only fill the gap by "nop" or "resb 1" to reach the correct VMA; but how "align 4096" in .data section affects the file offset of .loaderheader section?
My code basically enters long mode and hang. The code is not robust. Just used to generate ELF.
Note the "align 4096" in loader.s. If we change it to "align 8192", the final binary will be "loaderheader.offset=8192". What's the content before .loaderheader?
Did I miss something?
loader.s:
linker.ld
linker.ld:
When "align 4096":
objdump -h kernel64.bin:
Sections:
Idx Name Size VMA LMA File off Algn
0 .loaderheader 0000000c 0000000000100000 0000000000100000 00001000 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .text 000000f6 0000000000101000 0000000000101000 00002000 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
...
When "align 8192":
objdump -h kernel64.bin:
Sections:
Idx Name Size VMA LMA File off Algn
0 .loaderheader 0000000c 0000000000100000 0000000000100000 00002000 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .text 000000f6 0000000000101000 0000000000101000 00003000 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
One related thread in forum is http://forum.osdev.org/viewtopic.php?f=1&t=19128 but I cannot solve the problem by adding "-n".
My understand is "align" will only fill the gap by "nop" or "resb 1" to reach the correct VMA; but how "align 4096" in .data section affects the file offset of .loaderheader section?
My code basically enters long mode and hang. The code is not robust. Just used to generate ELF.
Note the "align 4096" in loader.s. If we change it to "align 8192", the final binary will be "loaderheader.offset=8192". What's the content before .loaderheader?
Did I miss something?
loader.s:
Code: Select all
global loader ; making entry point visible to linker
; setting up the Multiboot header - see GRUB docs for details
MODULEALIGN equ 1<<0 ; align loaded modules on page boundaries
MEMINFO equ 1<<1 ; provide memory map
FLAGS equ MODULEALIGN | MEMINFO ; this is the Multiboot 'flag' field
MAGIC equ 0x1BADB002 ; 'magic number' lets bootloader find the header
CHECKSUM equ -(MAGIC + FLAGS) ; checksum required
[BITS 32]
section .loaderheader
MultiBootHeader:
dd MAGIC
dd FLAGS
dd CHECKSUM
; reserve initial kernel stack space
STACKSIZE equ 0x4000 ; that's 16k.
CR0_PG equ 0x80000000
CR4_PAE equ 0x20
MSR_EFER equ 0xc0000080
MSR_EFER_LME equ 0x100
COM1_PORT equ 0x3F8
section .text
align 4
loader:
mov esp, stack+STACKSIZE ; set up the stack
;reload 32bit GDTR
lgdt [entry_gdtr32]
jmp 0x08:gdtreload32
gdtreload32:
;initialize page table
mov eax, (0<<21)+0x83
mov edi, entry_pde
mov ecx, 512*8
xor edx, edx
.oneentry:
mov [edi], eax
mov [edi+4], edx
add edi, 8
add eax, 1<<21
adc edx, 0
loop .oneentry
;enter long mode
mov eax, cr4
or eax, CR4_PAE
mov cr4, eax
mov eax, entry_pml4
mov cr3, eax
mov ecx, MSR_EFER
rdmsr
or eax, MSR_EFER_LME
wrmsr
mov eax, cr0
or eax, CR0_PG
mov cr0, eax
;xchg bx, bx ;bochs magic break
jmp 0x18:entry64
[BITS 64]
%macro outb 2 ;ruin dx, al
mov dx, %1
mov al, %2
out dx, al
%endmacro
entry64:
mov eax, 0x20
mov ds, eax
mov ss, eax
mov es, eax
;initialize TSS base address
mov rax, entry_gdt+0x28
mov rcx, tss_64
mov word[rax+2], cx
shr rcx, 16
mov byte[rax+4], cl
shr rcx, 8
mov byte[rax+7], cl
shr rcx, 8
mov [rax+8], ecx
;xchg bx, bx ;bochs magic break
lgdt [entry_gdtr64]
ltr [tss_selector] ;load tss
xor rdi,rdi
mov edi, ebx
xchg bx, bx ;bochs magic break
cli
hang:
hlt ; halt machine should kernel return
jmp hang
section .data
;tss
align 4
global tss_64
tss_64:
dd 0 ;reserved
dq 0 ;rsp0
dq 0 ;rsp1
dq 0 ;rsp2
dq 0 ;reserved
dq 0 ;ist1
dq 0 ;ist2
dq 0 ;ist3
dq 0 ;ist4
dq 0 ;ist5
dq 0 ;ist6
dq 0 ;ist7
dq 0 ;reserved
dw 0 ;reserved
dw io_bitmap-tss_64 ;i/o map base address
;i/o permission bitmap
io_bitmap:
times 65536/8 db 0
db 0xf
;tss selector
tss_selector:
dw 0x28
;gdt
align 4
entry_gdtr32:
dw 0x28-1
dd entry_gdt
entry_gdtr64:
dw 0x38-1
dq entry_gdt
global entry_gdt
entry_gdt:
dq 0
dq 0x00CF9B000000FFFF ;0x08 CODE32, DPL=0
dq 0x00CF93000000FFFF ;0x10 DATA32, DPL=0
dq 0x00AF9B000000FFFF ;0x18 CODE64, DPL=0
dq 0x00AF93000000FFFF ;0x20 DATA64, DPL=0
dq 0x009F89000000FFFF ;0x28 64-bit TSS lower half
dq 0x0000000000000000 ;0x30 64-bit TSS higher half
;page table (2MB pages)
[color=#FF0000]align 4096[/color]
entry_pml4:
dq entry_pdpt+0x7 ;first 512GB
times 512-1 dq 0
entry_pdpt:
dq entry_pde+0*4096+0x7 ;0-1GB
dq entry_pde+1*4096+0x7 ;1-2GB
dq entry_pde+2*4096+0x7 ;2-3GB
dq entry_pde+3*4096+0x7 ;3-4GB
dq entry_pde+4*4096+0x7 ;4-5GB
dq entry_pde+5*4096+0x7 ;5-6GB
dq entry_pde+6*4096+0x7 ;6-7GB
dq entry_pde+7*4096+0x7 ;7-8GB
times 512-8 dq 0
entry_pde: ;8 pde
;dq (0<<21)+0x83 ;0-2MB
times 512*8 dq 0
section .bss
align 4
stack:
resb STACKSIZE ; reserve 16k stack on a doubleword boundary
Code: Select all
ENTRY (loader)
OUTPUT_FORMAT(elf64-x86-64)
PHDRS{
header PT_LOAD;
}
SECTIONS{
. = 0x00100000;
.loaderheader ALIGN (0x1000) :{
*(.loaderheader)
}:header
.text ALIGN (0x1000) :{
*(.text)
}
.rodata ALIGN (0x1000) :{
*(.rodata)
}
.data ALIGN (0x1000) :{
*(.data)
}
.bss : {
sbss = .;
*(COMMON)
*(.bss)
ebss = .;
}
}
Code: Select all
SOURCES_H=
SOURCES_C=
SOURCES_ASM=loader.s
BIN=kernel64.bin
LINKER=linker.ld
OBJS_C=$(SOURCES_C:.c=.o)
OBJS_ASM=$(SOURCES_ASM:.s=.o)
CFLAGS=-Wall -Wextra -nostdlib -nostartfiles -nodefaultlibs -m64
CFLAGS+=-mno-red-zone -fno-stack-protector -std=gnu99 -gdwarf-2
all: $(BIN)
$(BIN): $(OBJS_C) $(OBJS_ASM) $(LINKER)
ld -nostdlib -nodefaultlibs -nostdinc -n -melf_x86_64 -z max-page=0x1000 -T $(LINKER) -o $(BIN) $(OBJS_ASM) $(OBJS_C)
clean:
-rm *.o $(BIN)
$(OBJS_C): $(SOURCES_C) $(SOURCES_H)
gcc -c $(SOURCES_C) $(CFLAGS)
loader.o: loader.s
yasm -g dwarf2 -f elf64 loader.s
.PHONY: clean
objdump -h kernel64.bin:
Sections:
Idx Name Size VMA LMA File off Algn
0 .loaderheader 0000000c 0000000000100000 0000000000100000 00001000 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .text 000000f6 0000000000101000 0000000000101000 00002000 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
...
When "align 8192":
objdump -h kernel64.bin:
Sections:
Idx Name Size VMA LMA File off Algn
0 .loaderheader 0000000c 0000000000100000 0000000000100000 00002000 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .text 000000f6 0000000000101000 0000000000101000 00003000 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
One related thread in forum is http://forum.osdev.org/viewtopic.php?f=1&t=19128 but I cannot solve the problem by adding "-n".