Page 1 of 1
Linking/initialization trouble
Posted: Sat Mar 27, 2010 4:13 pm
by GenHornet18
Good Day,
So I'm developing a basic kernel following JamesM tutorials (which are a damn good job btw James) and I'm having trouble getting my global variables to initialize with an original value. Specifically the Attribute variable in my screen source file. As I boot my kernel in bochs I get a black screen because the kernel was loaded correctly and the output message was outputted but the Attribute variable isn't set so it outputs black letters (indistinguishable from the background).
After long enough debugging I tracked the problem to what I believe is the linker. I say this because when I link 7 object files together and I get the error and yet when I link only the first 3 object files (required for outputting text) the Attribute value is initialized to what it originally was set as after declaration (i.e unsigned short Attrib = 0x07;). So I'm left wondering why when I link more object files together does this variable fail to become initialized?
Re: Linking/initialization trouble
Posted: Sat Mar 27, 2010 4:38 pm
by Owen
Posting your linker script and makefile would be very helpful
Re: Linking/initialization trouble
Posted: Sat Mar 27, 2010 4:44 pm
by GenHornet18
Sorry, the linker script is:
Code: Select all
OUTPUT_FORMAT("binary")
ENTRY(start)
phys = 0x00010000;
SECTIONS
{
.text phys : AT(phys) {
code = .;
*(.text)
*(.rodata)
. = ALIGN(4096);
}
.data : AT(phys + (data - code))
{
data = .;
*(.data)
. = ALIGN(4096);
}
.bss : AT(phys + (bss - code))
{
bss = .;
*(.bss)
. = ALIGN(4096);
}
end = .;
}
and the makefile(batch):
Code: Select all
echo Creating kernel, please wait...
rem ELF files, create a kernel
nasm -f elf start.asm -o start.o
i686-elf-gcc -Wall -ffreestanding -finline-functions -nostdinc -I./include -c Main.c -o Main.o
i686-elf-gcc -Wall -ffreestanding -finline-functions -nostdinc -I./include -c OutSet.c -o OutSet.o
i686-elf-gcc -Wall -ffreestanding -finline-functions -nostdinc -I./include -c DataSet.c -o DataSet.o
i686-elf-gcc -Wall -ffreestanding -finline-functions -nostdinc -I./include -c DescTables.c -o DescTables.o
i686-elf-gcc -Wall -ffreestanding -finline-functions -nostdinc -I./include -c ISR.c -o ISR.o
i686-elf-gcc -Wall -ffreestanding -finline-functions -nostdinc -I./include -c Timer.c -o Timer.o
i686-elf-gcc -Wall -ffreestanding -finline-functions -nostdinc -I./include -c Paging.c -o Paging.o
i686-elf-ld -T link.ld -o kernel.bin start.o Main.o DataSet.o OutSet.o DescTables.o ISR.o Timer.o Paging.o
echo Finished!
rm *.o
pause
Using this makefile results in an error, while if I don't link the last 4 object files (and remove all references from them) the initialization works. The fault doesn't seem to be in the C files, as they do work as intended.
Re: Linking/initialization trouble
Posted: Sat Mar 27, 2010 6:23 pm
by KotuxGuy
Why are you using i686-elf-ld if you're compiling to a flat binary?
Re: Linking/initialization trouble
Posted: Sat Mar 27, 2010 6:27 pm
by Owen
One thing that catches my eye is
I think probably meant 0x00100000, or 1MB, not 64kb; in fact I'm surprised Grub even loaded it.
Nothing else jumps immediately at me
Re: Linking/initialization trouble
Posted: Sat Mar 27, 2010 6:28 pm
by Owen
KotuxGuy wrote:Why are you using i686-elf-ld if you're compiling to a flat binary?
Because his intermediate objects are ELF files? Because it matches his i686-elf-gcc compiler? Because its the correct version of LD to use?
Re: Linking/initialization trouble
Posted: Sat Mar 27, 2010 7:17 pm
by GenHornet18
KotuxGuy wrote:Why are you using i686-elf-ld if you're compiling to a flat binary?
Everything is ELF so it just seems to match up (if I don't the original LD will complain about not being able to modify a PE object).
Owen wrote:I think probably meant 0x00100000, or 1MB, not 64kb; in fact I'm surprised Grub even loaded it.
Nothing else jumps immediately at me
Now why do you assume I'm using GRUB? My bootloader(2-stage) actually loads the kernel to 10000h [ES=1000h, BX=0].
I don't think there is anything wrong with the bootloader as it does load the kernel to the correct location and transfers control to it. I find it odd though that when there are more object files linked my variables don't initialize correctly. Is there anything wrong with the linker script?
Re: Linking/initialization trouble
Posted: Sun Mar 28, 2010 9:08 am
by js
Possible causes I see (but I may very well be mistaken) :
- where's your .rodata segment ???
- since you're loading your kernel at a very low adress, and errors seem to occur past a certain file size, have you checked nothing's tampering with your data ? (BIOS video, BIOS functions, ...)
Re: Linking/initialization trouble
Posted: Sun Mar 28, 2010 11:09 am
by GenHornet18
js wrote:
where's your .rodata segment ???
- since you're loading your kernel at a very low adress, and errors seem to occur past a certain file size, have you checked nothing's tampering with your data ? (BIOS video, BIOS functions, ...)
Is it necessary to have a segment in the linker script for only *(.rodata) ? I assumed I could combine it with my the *(.text) section?
Based on a hex dump the strings are present in the kernel, and this is all done in protected mode so I don't actually use any BIOS interrupts. The kernel when fully compiled/linked is only 8KB so if the start address is 10000h(phys) then it shouldn't be interfering with any other reserved memory. I will look into relocating to above 1MB, and see if this makes a difference. I still find it odd though, because it will work if I assign a value to 'Attrib' after it's declaration, it just refuses to initialize.
Re: Linking/initialization trouble
Posted: Sun Mar 28, 2010 2:44 pm
by pcmattman
Re: Linking/initialization trouble
Posted: Sun Mar 28, 2010 4:07 pm
by GenHornet18
Well I do have a *(.rodata) section and I have confirmed via hex editor that the strings are present in the file. I've also confirmed that the original value that's to be assigned to the variable 'Attrib' is present in the .data section. So if all the data is there then why does it not get assigned? Could my address somehow be offset?
Re: Linking/initialization trouble
Posted: Sun Mar 28, 2010 7:18 pm
by pcmattman
If you're not using GRUB, you most likely have an error in your code to handle any required relocations in the ELF file. You may also be loading part of your kernel rather than the entire thing (not enough sectors loaded?).
Re: Linking/initialization trouble
Posted: Thu Apr 01, 2010 1:58 pm
by GenHornet18
EDIT: Answered my own question about ELF
Re: Linking/initialization trouble
Posted: Sat Apr 03, 2010 12:38 pm
by GenHornet18
Alright I've isolated the problem but I'm unsure of how to fix it. It seems when the .text section of my linker script is beyond 1 page (4096) the variables don't get initialized (from the .data section). However when the .text section is smaller then 1 page everything seems to be initialized and works properly. So I'm assume this is an aligning issue? Any ideas on how to correct this?
Linker script I'm using:
Code: Select all
OUTPUT_FORMAT(elf32-i386)
ENTRY(start)
SECTIONS
{
.text 0x10100 :
{
code = .;
*(.text)
*(.rodata)
. = ALIGN(4096);
}
.data :
{
data = .;
*(.data)
. = ALIGN(4096);
}
.bss :
{
bss = .;
*(.bss)
. = ALIGN(4096);
}
end = .;
}
and an objdump if it helps:
works-
Code: Select all
kernel.bin: file format elf32-i386
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000f00 00010100 00010100 00000100 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .data 00001000 00011000 00011000 00001000 2**2
CONTENTS, ALLOC, LOAD, DATA
2 .bss 0000000c 00012000 00012000 00002000 2**2
ALLOC
3 .comment 00000036 00000000 00000000 00002000 2**0
CONTENTS, READONLY
fails-
Code: Select all
kernel.bin: file format elf32-i386
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00001f00 00010100 00010100 00000100 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .data 00001000 00012000 00012000 00002000 2**2
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000c60 00013000 00013000 00003000 2**5
ALLOC
3 .comment 0000005a 00000000 00000000 00003000 2**0
CONTENTS, READONLY
Thanks