Linker problems, I think...
Linker problems, I think...
I wish I didn't have to join this forum asking questions, but I've been completely stuck for several days on this issue.
I've been working a bit on-and-off on my hobby kernel project, things are going great. I finished my bootloader a few days ago, managed to write some cool memory management routines, but nothing outside main.c worked, despite being compiled and linked without any kinds of error or warning messages.
I tried rewriting the routines, adding printlining, removing the code within them, absolutely nothing except what was in main.c worked.
After moving all my external code to main.c, everything suddenly started working fine.
Checking the assembly, I see that all my calls to functions outside main.c, jumps to JNBE instructions that in turn jump to themselves.
Does anyone know a possible cause for this?
I'm using LD 2.13, GCC 2.8.1, and NASM 0.98.39.
Edit:
The strangest thing just happened; if I declare a function pointer that points to a function outside main.c, and call that one, it works all of a sudden =S
Edit 2:
Nevermind the last edit, it worked a couple of times and then stopped working for no reason.
I've been working a bit on-and-off on my hobby kernel project, things are going great. I finished my bootloader a few days ago, managed to write some cool memory management routines, but nothing outside main.c worked, despite being compiled and linked without any kinds of error or warning messages.
I tried rewriting the routines, adding printlining, removing the code within them, absolutely nothing except what was in main.c worked.
After moving all my external code to main.c, everything suddenly started working fine.
Checking the assembly, I see that all my calls to functions outside main.c, jumps to JNBE instructions that in turn jump to themselves.
Does anyone know a possible cause for this?
I'm using LD 2.13, GCC 2.8.1, and NASM 0.98.39.
Edit:
The strangest thing just happened; if I declare a function pointer that points to a function outside main.c, and call that one, it works all of a sudden =S
Edit 2:
Nevermind the last edit, it worked a couple of times and then stopped working for no reason.
- carbonBased
- Member
- Posts: 382
- Joined: Sat Nov 20, 2004 12:00 am
- Location: Wellesley, Ontario, Canada
- Contact:
Thanks for your reply!
No it was not a typo =S
Using the newest GCC I get HUGE object files that do not work at all for some reason(Yes, I changed the bootloader to load the entire oversized image), -Os doesn't really help.
Anyway, here's my crummy batch makefile(Merge simply merges the two bin files.)
To make matters worse, now there's another problem; if I put too much stuff in main.c, it simply hangs the same way it does when calling something from a different file.
No it was not a typo =S
Using the newest GCC I get HUGE object files that do not work at all for some reason(Yes, I changed the bootloader to load the entire oversized image), -Os doesn't really help.
Anyway, here's my crummy batch makefile
Code: Select all
echo off
cls
nasm -f bin -o bootloader.bin bootloader.asm
nasm -f aout -o entry.o main.asm
gcc -v
gcc -Wall -O3 -fstrength-reduce -ffreestanding -nostdlib -nostartfiles -fomit-frame-pointer -nostdinc -fno-builtin -c -o main.o main.c
gcc -Wall -O3 -fstrength-reduce -ffreestanding -nostdlib -nostartfiles -fomit-frame-pointer -nostdinc -fno-builtin -c -o conio.o conio.c
ld -T link.ld -o kernel.bin entry.o main.o conio.o
del *.o
merge a.img bootloader.bin kernel.bin
To make matters worse, now there's another problem; if I put too much stuff in main.c, it simply hangs the same way it does when calling something from a different file.
you are doing this in 32bit right?
also I have had this problem before
assuming your bootloader doesn't do relocations(as almost none do) you must set where all the global data is(local vars work because they are on the stack) to do this you add this to your linker options/args
and then just replace 0x100000 with wherever your bootloader loads your kernel
also I have had this problem before
assuming your bootloader doesn't do relocations(as almost none do) you must set where all the global data is(local vars work because they are on the stack) to do this you add this to your linker options/args
Code: Select all
-Ttext 0x100000
Yes, I am doing this in 32 bit, with A20 enabled (If that makes any difference).
Here's the linker script I use to link all the stuff together, I'm not sure if it's correct in any way, but it seems to work.I am rather certain that my kernel is located at code_seg + 0x100000, because it does jump to the correct instructions at first (jmp code_sel:0x100000).
I have noticed that I cannot do anything worthwhile where I jump though, loading a new GDT simply crashes the thing.
Here's the linker script I use to link all the stuff together, I'm not sure if it's correct in any way, but it seems to work.
Code: Select all
OUTPUT_FORMAT("binary")
ENTRY(entry)
phys_addr = 0x00100000;
SECTIONS
{
.text phys_addr : AT(phys_addr) {
code_loc = .;
*(.text)
. = ALIGN(8192);
}
.data : AT(phys_addr + (data_loc - code_loc))
{
data_loc = .;
*(.data)
. = ALIGN(8192);
}
.bss : AT(phys_addr + (bss_loc - code_loc))
{
bss_loc = .;
*(.bss)
. = ALIGN(8192);
}
end = .;
}
I have noticed that I cannot do anything worthwhile where I jump though, loading a new GDT simply crashes the thing.
- carbonBased
- Member
- Posts: 382
- Joined: Sat Nov 20, 2004 12:00 am
- Location: Wellesley, Ontario, Canada
- Contact:
What's your .asm look like? Have you made sure that everything is encapsulated inside a .text or .data section (ie, will it be positioned correctly via your linker script?).Thomac wrote: No it was not a typo =S
Using the newest GCC I get HUGE object files that do not work at all for some reason(Yes, I changed the bootloader to load the entire oversized image), -Os doesn't really help.
Usually when I see large object files it's because something hasn't been put into an actual section, and so starts at address 0, while .text is at 1MB... inbetween there's a million nops, or 0's.
--Jeff
Edit: I've been able to isolate the problem; it is the linker allright.
If I use "ld -T link.ld -o kernel.bin entry.o conio.o" instead of "ld -T link.ld -o kernel.bin entry.o main.o conio.o", all the stuff in conio.o works.
If I use "ld -T link.ld -o kernel.bin entry.o conio.o main.o", it doesn't work, as usual.
Could it be the linker script, or perhaps the linker itself?
Bootloader:Startup stuff:
If I use "ld -T link.ld -o kernel.bin entry.o conio.o" instead of "ld -T link.ld -o kernel.bin entry.o main.o conio.o", all the stuff in conio.o works.
If I use "ld -T link.ld -o kernel.bin entry.o conio.o main.o", it doesn't work, as usual.
Could it be the linker script, or perhaps the linker itself?
Bootloader:
Code: Select all
[BITS 16]
[ORG 7C00h]
jmp boot
;-------------------Variables-------------------;
drive db 0
;-----------------End Variables-----------------;
;----------------------GDT----------------------;
gdtr:
dw gdt_end-gdt-1
dd gdt
gdt:
null_sel equ $-gdt
dd 0x0
dd 0x0
code_sel equ $-gdt
dw 0xFFFF
dw 0x0
db 0x0
db 0x9A
db 0xCF
db 0x0
data_sel equ $-gdt
dw 0xFFFF
dw 0x0
db 0x0
db 0x92
db 0xCF
db 0x0
gdt_end:
;--------------------End GDT--------------------;
;-------------------Functions-------------------;
panic:
mov byte [gs:0],al
mov byte [gs:1],0x04
cli
hlt
try_enable_a20:
cli
call enable_A20_primary
call kbdc_status
test al, 2
jnz .success
call enable_A20_secondary
call kbdc_status
test al, 2
jnz .success
xor ax, ax
ret
.success:
mov ax, -1
ret
enable_A20_secondary:
call kbdc_command
mov al, 0xDF
out 0x64, al
ret
enable_A20_primary:
call kbdc_status
push ax
call kbdc_command
mov al, 0xD1
out 0x64, al
call kbdc_command
pop ax
or al, 00000010b
out 0x60, al
ret
kbdc_command:
xor ax, ax
in al, 0x64
test ax, 2
jnz kbdc_command
ret
kbdc_data:
xor ax, ax
in al, 0x64
test al, 1
jz kbdc_data
ret
kbdc_status:
call kbdc_command
mov al, 0xD0
out 0x64, al
call kbdc_data
xor ax, ax
in al, 0x60
ret
;-----------------End Functions-----------------;
boot:
mov [drive], dl
mov ax, cs
mov ds, ax
mov es, ax
mov fs, ax
mov al, 17
mov ah, 02h
mov ss, ax
mov sp, 0x200
mov ax, 0xB800
mov gs, ax
call try_enable_a20
or ax, ax
jnz .a20_enabled
mov al, 'P'
call panic
.a20_enabled:
sti
mov cx, 0x3
.try_load_kernel:
push cx
mov ah, 0x2
mov al, 0x2
mov ch, 0x0
mov cl, 0x2
mov dh, 0x0
mov dl, [drive]
mov bx, 0xFFFF
mov es, bx
mov bx, 0x10
int 13h
jnc .kernel_loaded
pop cx
loop .try_load_kernel
mov al, 'L'
call panic
.kernel_loaded:
cli
lgdt [gdtr]
mov eax, cr0
or al, 0x1
mov cr0, eax
jmp code_sel:flush
[BITS 32]
flush:
mov eax, data_sel
mov ds, eax
mov es, eax
mov fs, eax
mov gs, eax
mov ss, eax
mov esp, 0xFFFF
mov eax, gdtr
jmp code_sel:0x100000
hlt
times 510-($-$$) db 0
dw 0xAA55
Code: Select all
SECTION .text
[BITS 32]
[EXTERN _kernel_entry]
[GLOBAL entry]
entry:
[GLOBAL _entry]
_entry:
mov esp, _sys_stack
push eax
call _kernel_entry ;Calls the C kernel entry
cli
hlt
jmp $
SECTION .bss
resb 16384
_sys_stack:
Okay, I rewrote the entire thing in ASM, and changed the object file format to ELF, but I still can't do things the way I want.
For some reason I cannot modify or access anything in .data or .bss, the only thing that works is .text(Which fails once I reach a critical size).
I believe there must be some problem with the linker, I've tried using a newer version of LD, but the newer versions whine about non-pe operations being executed on a non-pe file.
For some reason I cannot modify or access anything in .data or .bss, the only thing that works is .text(Which fails once I reach a critical size).
I believe there must be some problem with the linker, I've tried using a newer version of LD, but the newer versions whine about non-pe operations being executed on a non-pe file.