Page 1 of 1
64-bit LD giving headaches
Posted: Wed Oct 04, 2006 12:33 pm
by Candy
I've finally (yes, that took half a year) gotten the kernel to the linker step. It's really annoying me though, as the linker refuses to do even the most basic things.
When running it without a linker script, it gives this:
Code: Select all
x86_64-pc-elf-ld: warning: cannot find entry symbol _start; defaulting to ffffffffc0000000
x86_64-pc-elf-ld: disk/kernel/kernel: Not enough room for program headers (allocated 2, need 6)
Section to Segment mapping:
Segment Sections...
00: LOAD: .ctors
01: LOAD: .init
02: LOAD: .text
03: LOAD: .data
04: LOAD: .eh_frame
05: LOAD: .dtors
x86_64-pc-elf-ld: final link failed: Bad value
The first is to be explained. The second, however, is what's causing me a headache.
I got to trying it without linker script as it didn't really listen to my linker script anyway. I am trying to specify it to put ctors, init, text, data and dtors in the output file at 4k-aligned blocks. It seems to just align it on a megabyte boundary at random, preferring to keep the lower 20 bits from the actual load address. This leads to a lot of annoyance, since it creates a kernel binary of slightly over 2.5 megabytes for about 64k of object files. Messing around with it I can't seem to find how to force something at a given location. Anybody got an idea? Brendan, do you have experience with this?
Re:64-bit LD giving headaches
Posted: Wed Oct 04, 2006 12:53 pm
by Candy
Ok, without linker script it can link from a single binary input. I need to specify where to load, however, so I tried again. The current result crashes most applications:
Code: Select all
candy@blackbox:~/atlantisos$ ls -l disk/kernel/kernel.x86_64-pc-elf
-rw-r--r-- 1 candy users 5774519251 2006-10-04 20:53 disk/kernel/kernel.x86_64-pc-elf
That's a bit more than the input. Anybody?
Re:64-bit LD giving headaches
Posted: Wed Oct 04, 2006 2:50 pm
by Candy
Last bit for the day, the current linker script hack:
Code: Select all
OUTPUT_FORMAT("elf64-x86-64")
ENTRY("_start")
SECTIONS {
. = ALIGN(0x1000);
.init 0xFFFFFFFFD0000000 : AT(0x90000) {
*(.init*)
init_ctors_begin = .;
*(.ctors)
init_ctors_end = .;
}
. = ALIGN(0x1000);
.text 0xFFFFFFFFC0000000 : AT(0x100000) {
*(.text*)
*(.rodata)
}
. = ALIGN(0x1000);
.data 0xFFFFFFFFC4000000 : AT(0x100000 + SIZEOF(.text)) {
*(.data)
*(COMMON)
kernel_max_mem = .;
}
.bss (ADDR(.data) + SIZEOF(.data)) : AT(LOADADDR(.data) + SIZEOF(.data)) {
*(.bss)
}
/DISCARD/ : {
*(.eh_frame)
*(.fini*)
*(.dtors)
*(_Z*)
*(.comment)
}
}
The output of objdump -p
Code: Select all
disk/kernel/kernel.x86_64-pc-elf
disk/kernel/kernel.x86_64-pc-elf: file format elf64-x86-64
Program Header:
LOAD off 0x0000000000000000 vaddr 0xffffffffcff00000 paddr 0xfffffffffff90000 align 2**20
filesz 0x00000000001000a0 memsz 0x00000000001000a0 flags rwx
LOAD off 0x0000000000200000 vaddr 0xffffffffc0000000 paddr 0x0000000000100000 align 2**20
filesz 0x0000000000006273 memsz 0x0000000000006273 flags r-x
LOAD off 0x0000000000300000 vaddr 0xffffffffc4000000 paddr 0x0000000000106273 align 2**20
filesz 0x0000000000000048 memsz 0x0000000000003210 flags rw-
I strongly suspect (almost know for sure) that it's ending up with these addresses because it's somehow wanted to align the segments on megabyte boundaries (as seen in the last bit) and that it should have the lowest 20 bits identical with the virtual address (which is, in theory, good). The problem is that I can't figure out why it is aligning stuff on megabyte boundaries, nor how I can convince it to align on, say, 4-kilobyte boundaries. I've tried to use something called BLOCK too, but that didn't appear to help (error when adding it as loose value, causing lots of relocation overflows when added to the address).
I'm using GCC 4.1.1 crosscompiled for the x86_64-pc-elf target. No special options were given to the linker. The compiler output is aligned, max, to 12 bits (which is the gdt in the bss section). I'm compiling with the following ccflags:
Code: Select all
CCFLAGS = -mtune=nocona -m64 -mcmodel=kernel -fno-exceptions -Iinclude -fshort-enums -Wno-long-long -fno-rtti -std=gnu++98 -Wall -Werror -Wextra -pedantic -pedantic-errors
.
The compile should be for my machine (just a tryout whether that helped - didn't), 64-bit (same), kernel-model (helped with relocations, not much with the rest). The rest are for the compiler to shout at me as much as it can and to not use some stupid default values (kernel needs no exceptions, no rtti, I need my includes, I want short enums as per the standard and I don't care that c++ doesn't have long longs, I need them).
Re:64-bit LD giving headaches
Posted: Wed Oct 04, 2006 7:15 pm
by B.E
from what I can see
x86_64-pc-elf-ld: warning: cannot find entry symbol _start; defaulting to ffffffffc0000000
_start is not defined in your code, or not declared global.
I have not looked into linker scipts that much, but i just did a google search and you can do something like this
to align you a 4kb boundry.
Re:64-bit LD giving headaches
Posted: Tue Oct 10, 2006 11:26 am
by hendric
Hi,Candy.I 'm wondering about your work on 64-bit mode. As my work, I found gcc could not place symbols anywhere.That's to say, you must place code sections at lower 2GB but free placing for data, as gcc didn't implement "large mode". How do you solve the problem? And as what's my x86-64 gcc done, functions with variable parameters could not be processed correctly (Unknown xmm instructions such as movaps xmm0,xxxx appeared.). Did you meet it?
Regards!
Re:64-bit LD giving headaches
Posted: Tue Oct 10, 2006 12:01 pm
by Habbit
hendric wrote:
That's to say, you must place code sections at lower 2GB but free placing for data, as gcc didn't implement "large mode".
What version of GCC are you using? I have G++ 4.1.1 and IIRC, it had full longmode support (that is 48 bit for now).
Re:64-bit LD giving headaches
Posted: Tue Oct 10, 2006 1:49 pm
by Candy
hendric wrote:
Hi,Candy.I 'm wondering about your work on 64-bit mode. As my work, I found gcc could not place symbols anywhere.That's to say, you must place code sections at lower 2GB but free placing for data, as gcc didn't implement "large mode". How do you solve the problem? And as what's my x86-64 gcc done, functions with variable parameters could not be processed correctly (Unknown xmm instructions such as movaps xmm0,xxxx appeared.). Did you meet it?
Regards!
I haven't tried printing complex numbers (not in mathematical sense) from a printf-like function but movaps says you're trying to move two of them at a time. Are you compiling for the right model?
I "solved" the 2GB problem by using the recommended hack, -mcmodel=kernel. That inverts your 2GB and puts you at the top (literally). You can still only use the top 2GB. I was planning on using that for the mapping of the pagetables but okay, then I'll move them to the lower half limit of the top of the memory.
The large model is implemented, but is intently disabled and has been like that for years now. It lacks a few minor details, mainly code-related, which say that your code can't be spread over more than 2GB. That kind of forces you to put it in 2gb, but I would've liked to be able to pick the 2GB it should go to.
One lesson I've learned however is that you should really not mix up physical and virtual addresses. It tried to align to 2GB alignment in the upper example where I got a 5.7GB kernel.
I've "solved" the huge-kernel problem by using -N, but that's not a true solution. I compress it too, so it's not a big deal (not like I was going to memory-map it from a compressed file) but it's still annoying that it won't just listen.
Re:64-bit LD giving headaches
Posted: Tue Oct 10, 2006 10:31 pm
by hendric
As a mail from gcc mailinglist,we know in fact Jan Hubicka has implemented
large model support already, and it should go into gcc 4.3:
http://gcc.gnu.org/wiki/large-model
Projects planned for gcc 4.3 are listed here:
http://gcc.gnu.org/wiki/GCC_4.3_Release_Planning
Sounds cool, isn't it?