Higher Half kernel load, linker error
Posted: Thu Mar 18, 2021 4:55 am
Hi all,
what this time i'm trying to do is to load the kernel in the higher half, starting from address 0xC0000000.
First thing i did was update the bootloader to map the kernel memory into higher half (i mapped the first 4mb) and i'm using 2mb pages:
(i hope that i understood correctly what was needed to do, and that the code above is not totally wrong! )
Then i updated the linker script (i have to admit that despite all the tutorials i read the linker script is that thing that i have an idea of what they does... but still haven't totally understood them):
Ok the code aove is copied from the wiki tutorial https://wiki.osdev.org/Higher_Half_x86_Bare_Bones, probably i need to adapt it to my actual code.
Btw now when i try to compile the os i'm getting this linker error:
where tagfb and tagmem are containing multiboot header information. I think that the problem is mostly in the linker script that needs probably to be adapted, but not sure what i need to change.
Can someone help me?
And another question: if i understood correctly, having mapped the kernel in the higher half, and having mapped the first 4mb of memory now the VGA memory (i know is deprecated , and i'm planning to remove it soon) that starts at 0xb8000 now should start at 0xC00b8000, correct?
Also another question: reading the tutorial it says that while mappin the kernel, text, and .rodata are now marked as writable, but i'm not sure how i should map them as not writable (i mean i think they are just portion of memory, so maybe they are in a segment that contains other parts that has to be writable?)
EDIT 1
Ok, did some tests, and i'm sure is my linker script that is messed up. But as said above, the more i try to understand it, the more foggy is my knowledge of it lol.
Btw what i understood is that the sections are messed up, and it has to be adapted to my kernel. and what i understood is that the portion of the code that does the reloctation must be still accessible on the lower half, so those sections should be declared in the 0x100000 part of the linker.
Actually i have the following sections:
Is that a progress?
P.s i'm using Nasm to compile the assembly.
End of edit 1
Edit 2
Ok digging into the forum i found, that in order to link properly all references, i had to add the -mcmodel=large to the gcc compile flags.
Now it links correctly, but now when it boots up, is probably causing a triple fault when trying to enable paging.
Now i'm not sure what can be the problem: it can be related on how i mapped the kernel in the pagetable, or i stil lshould investigate the linker script?
End of edit 2
what this time i'm trying to do is to load the kernel in the higher half, starting from address 0xC0000000.
First thing i did was update the bootloader to map the kernel memory into higher half (i mapped the first 4mb) and i'm using 2mb pages:
Code: Select all
; Now time to map the kernel in the higher half
mov eax, hhk_p2_table
or eax, 0b11
mov dword [fbb_p2_table + 0], eax
mov eax, 0x00000000 ; This is the base address of the kernel
or eax, 0b10000011
mov [hhk_p2_table + 0], eax
mov eax, 0x00200000
or eax, 0b10000011
mov [hhk_p2_table + 8 * 1], eax ; Multiply by 1 just to highlight the entry number
; All set... now we are nearly ready to enter into 64 bit
; Is possible to move into cr3 only from another register
; So let's move p4_table address into eax first
; then into cr3
mov eax, (p4_table - KERNEL_VIRTUAL_BASE_ADDRESS)
mov cr3, eax
Then i updated the linker script (i have to admit that despite all the tutorials i read the linker script is that thing that i have an idea of what they does... but still haven't totally understood them):
Code: Select all
ENTRY(start)
SECTIONS {
. = 0x00100000;
_kernel_start =.;
.boot :
{
/* Be sure that multiboot header is at the beginning */
*(.multiboot_header)
}
.text :
{
*(.text)
}
. += 0xC0000000;
/* Add a symbol that indicates the start address of the kernel. */
.text ALIGN (4K) : AT (ADDR (.text) - 0xC0000000)
{
*(.text)
}
.rodata ALIGN (4K) : AT (ADDR (.rodata) - 0xC0000000)
{
*(.rodata)
}
.data ALIGN (4K) : AT (ADDR (.data) - 0xC0000000)
{
*(.data)
}
.bss ALIGN (4K) : AT (ADDR (.bss) - 0xC0000000)
{
*(COMMON)
*(.bss)
*(.bootstrap_stack)
}
_kernel_end = .;
}
Btw now when i try to compile the os i'm getting this linker error:
Code: Select all
main.c:(.text+0x59): relocation truncated to fit: R_X86_64_PC32 against symbol `tagfb' defined in .bss section in build/kernel/main.o
main.c:(.text+0x65): relocation truncated to fit: R_X86_64_PC32 against symbol `tagfb' defined in .bss section in build/kernel/main.o
main.c:(.text+0x96): relocation truncated to fit: R_X86_64_PC32 against symbol `tagfb' defined in .bss section in build/kernel/main.o
main.c:(.text+0xc6): relocation truncated to fit: R_X86_64_PC32 against symbol `tagfb' defined in .bss section in build/kernel/main.o
main.c:(.text+0xf6): relocation truncated to fit: R_X86_64_PC32 against symbol `tagfb' defined in .bss section in build/kernel/main.o
main.c:(.text+0x127): relocation truncated to fit: R_X86_64_PC32 against symbol `tagfb' defined in .bss section in build/kernel/main.o
main.c:(.text+0x158): relocation truncated to fit: R_X86_64_PC32 against symbol `tagfb' defined in .bss section in build/kernel/main.o
main.c:(.text+0x17e): relocation truncated to fit: R_X86_64_PC32 against symbol `tagfb' defined in .bss section in build/kernel/main.o
main.c:(.text+0x1b9): relocation truncated to fit: R_X86_64_PC32 against symbol `tagmem' defined in .bss section in build/kernel/main.o
main.c:(.text+0x1d5): relocation truncated to fit: R_X86_64_PC32 against symbol `tagmem' defined in .bss section in build/kernel/main.o
Can someone help me?
And another question: if i understood correctly, having mapped the kernel in the higher half, and having mapped the first 4mb of memory now the VGA memory (i know is deprecated , and i'm planning to remove it soon) that starts at 0xb8000 now should start at 0xC00b8000, correct?
Also another question: reading the tutorial it says that while mappin the kernel, text, and .rodata are now marked as writable, but i'm not sure how i should map them as not writable (i mean i think they are just portion of memory, so maybe they are in a segment that contains other parts that has to be writable?)
EDIT 1
Ok, did some tests, and i'm sure is my linker script that is messed up. But as said above, the more i try to understand it, the more foggy is my knowledge of it lol.
Btw what i understood is that the sections are messed up, and it has to be adapted to my kernel. and what i understood is that the portion of the code that does the reloctation must be still accessible on the lower half, so those sections should be declared in the 0x100000 part of the linker.
Actually i have the following sections:
- section .multiboot_header -> in the multiboot header file
- section .text -> The bootloader code
- section .bss -> Still in the bootloader file with the page tables data
- section .rodata -> with the gdt data
- Section text has become .multiboot.text and i updated the linker script replacing the .text part (in the 0x100000 area) with: .multiboot.text
- I also added a section .text that starts right after paging is enabled (that should now refer to the kernel in the higher_half),
- label higher_half and code to load it just after the paging is enabled. This is my change:
Code: Select all
lea ebx, [higher_half] jmp ebx section .text higher_half: ;gdt load code ;and jmp to C function.
Code: Select all
psf.c:(.text+0x55): relocation truncated to fit: R_X86_64_32S against symbol `_binary_fonts_default_psf_start' defined in .data section in build/default.o
psf.c:(.text+0x75): relocation truncated to fit: R_X86_64_32S against symbol `_binary_fonts_default_psf_start' defined in .data section in build/default.o
build/kernel/arch/x86_64/cpu/idt.o: in function `interrupts_handler':
idt.c:(.text+0x14): relocation truncated to fit: R_X86_64_32S against `.rodata'
build/kernel/arch/x86_64/cpu/idt.o: in function `init_idt':
idt.c:(.text+0x96): relocation truncated to fit: R_X86_64_32S against `.bss'
build/kernel/arch/x86_64/cpu/idt.o: in function `set_idt_entry':
idt.c:(.text+0x4ea): relocation truncated to fit: R_X86_64_32S against `.bss'
idt.c:(.text+0x4f5): relocation truncated to fit: R_X86_64_32S against `.bss'
idt.c:(.text+0x504): relocation truncated to fit: R_X86_64_32S against `.bss'
idt.c:(.text+0x50a): relocation truncated to fit: R_X86_64_32S against `.bss'
idt.c:(.text+0x511): relocation truncated to fit: R_X86_64_32S against `.bss'
idt.c:(.text+0x518): relocation truncated to fit: R_X86_64_32S against `.bss'
P.s i'm using Nasm to compile the assembly.
End of edit 1
Edit 2
Ok digging into the forum i found, that in order to link properly all references, i had to add the -mcmodel=large to the gcc compile flags.
Now it links correctly, but now when it boots up, is probably causing a triple fault when trying to enable paging.
Now i'm not sure what can be the problem: it can be related on how i mapped the kernel in the pagetable, or i stil lshould investigate the linker script?
End of edit 2