Linking crt*.o in 64bit kernel image

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
robbiedobbie
Member
Member
Posts: 36
Joined: Fri May 16, 2014 2:40 pm
Libera.chat IRC: robbiedobbie

Linking crt*.o in 64bit kernel image

Post by robbiedobbie »

Hey all,

I've been working on porting my kernel (which is still in very early stages), to 64bit so that I don't have to go through all the trouble later. I've been succesfull in getting it to switch from 32 to 64 (running from higher half), and running my c/c++ code. However, when I try to link crtbegin.o and crtend.o into the kernel, to get the global constructors working, I get linker errors.

They are being caused by the higher half kernel, but I don't know how to solve it.

The command used to link:

Code: Select all

/home/rob/opt/cross/bin/x86_64-elf-g++ -T linker.ld -nostdlib -ffreestanding -z max-page-size=0x1000 -g -ggdb -o bin/kernel src/bootstrap.o src/start64.o src/crti.o /home/rob/opt/cross/lib/gcc/x86_64-elf/4.9.0/crtbegin.o src/main.o /home/rob/opt/cross/lib/gcc/x86_64-elf/4.9.0/crtend.o src/crtn.o -lgcc
The error it gives:

Code: Select all

/home/rob/opt/cross/lib/gcc/x86_64-elf/4.9.0/crtbegin.o: In function `deregister_tm_clones':
crtstuff.c:(.text+0x1): relocation truncated to fit: R_X86_64_32 against symbol `__TMC_END__' defined in .jcr section in bin/kernel
crtstuff.c:(.text+0x8): relocation truncated to fit: R_X86_64_32S against `.tm_clone_table'
crtstuff.c:(.text+0x21): relocation truncated to fit: R_X86_64_32 against `.tm_clone_table'
/home/rob/opt/cross/lib/gcc/x86_64-elf/4.9.0/crtbegin.o: In function `register_tm_clones':
crtstuff.c:(.text+0x41): relocation truncated to fit: R_X86_64_32 against symbol `__TMC_END__' defined in .jcr section in bin/kernel
crtstuff.c:(.text+0x49): relocation truncated to fit: R_X86_64_32S against `.tm_clone_table'
crtstuff.c:(.text+0x6f): relocation truncated to fit: R_X86_64_32 against `.tm_clone_table'
/home/rob/opt/cross/lib/gcc/x86_64-elf/4.9.0/crtbegin.o: In function `__do_global_dtors_aux':
crtstuff.c:(.text+0x8f): relocation truncated to fit: R_X86_64_32 against symbol `__DTOR_END__' defined in .dtors section in /home/rob/opt/cross/lib/gcc/x86_64-elf/4.9.0/crtend.o
crtstuff.c:(.text+0x96): relocation truncated to fit: R_X86_64_32S against `.dtors'
crtstuff.c:(.text+0xc6): relocation truncated to fit: R_X86_64_32S against `.dtors'
crtstuff.c:(.text+0xe6): relocation truncated to fit: R_X86_64_32 against `.eh_frame'
crtstuff.c:(.text+0xeb): additional relocation overflows omitted from the output
collect2: error: ld returned 1 exit status
My linker.ld:

Code: Select all

kernel_VMA = 0xffff800000000000;
kernel_LMA = 0x100000;

/* start from the entry point */
ENTRY(_bootstrap)
SECTIONS
{
    . = kernel_LMA;

    .text_boot :
    {
        src/bootstrap.o (.text)
    }

    . = . + kernel_VMA;

    .text : AT(ADDR(.text) - kernel_VMA + kernel_LMA)
    {
        code = .;
        *(.text)
		*(.text*)

        /* read only data */
        *(.rodata*)
        *(.rdata*)

        . = ALIGN(4096);
    }

    .data : AT(ADDR(.data) - kernel_VMA + kernel_LMA)
    {
        data = .;
        *(.data)

        . = ALIGN(4096);
    }

    _end_data = .;

    .bss : AT(ADDR(.bss) - kernel_VMA + kernel_LMA)
    {
        *(.bss)
        . = ALIGN(4096);
    }

    .ehframe : AT(ADDR(.ehframe) - kernel_VMA + kernel_LMA)
    {
        ehframe = .;
        *(.ehframe)
        . = ALIGN(4096);
    }

    _end = .;
}
I've tried using -mcmodel=kernel and -mcmodel=medium as switches to the linker, but this didn't make any difference.

Does anyone have an idea how to solve this?

Thank you in advance,

Rob
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Linking crt*.o in 64bit kernel image

Post by Combuster »

Why are the constructor sections missing from your linker script?
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
robbiedobbie
Member
Member
Posts: 36
Joined: Fri May 16, 2014 2:40 pm
Libera.chat IRC: robbiedobbie

Re: Linking crt*.o in 64bit kernel image

Post by robbiedobbie »

That's stupid of me #-o

I tried adding them by adding

Code: Select all

        *(.ctor*)
        *(.dtor*)
to the data section of the linkerscript, but it does not change anything. Am I missing some other sections?
User avatar
xenos
Member
Member
Posts: 1121
Joined: Thu Aug 11, 2005 11:00 pm
Libera.chat IRC: xenos1984
Location: Tartu, Estonia
Contact:

Re: Linking crt*.o in 64bit kernel image

Post by xenos »

For linking your kernel in that address range you need to tell GCC to use the large memory model (add -mcmodel=large). Otherwise it will generate instructions that use 32 bit addresses (which are smaller), and ld cannot fill these with high 64 bit memory addresses. In the large memory model GCC will use 64 bit addresses by default.
Programmers' Hardware Database // GitHub user: xenos1984; OS project: NOS
robbiedobbie
Member
Member
Posts: 36
Joined: Fri May 16, 2014 2:40 pm
Libera.chat IRC: robbiedobbie

Re: Linking crt*.o in 64bit kernel image

Post by robbiedobbie »

I didn't try the large option before, since I though it wasn't implemented yet.

Unfortunately though it doesn't work either. The linker doesn't give an error that it's not implemented, but it still gives the relocation truncated errors.

Now what I find really weird, is that lots of the errors result from sections like jcr, which are for java code according to the elf documentation?
User avatar
Owen
Member
Member
Posts: 1700
Joined: Fri Jun 13, 2008 3:21 pm
Location: Cambridge, United Kingdom
Contact:

Re: Linking crt*.o in 64bit kernel image

Post by Owen »

Code outside the -2GB to 2GB range of the address space requires complex additional considerations (that is, the compiler needs to insert lots of MOVABS instructions and such in order to get full arbitrary 64-bit addresses into registers). The default CRT files are not built with these settings.

Place your kernel in the -2GB region of the address space, i.e. 0xFFFFFFFF80000000 (Build it with -mcmodel=kernel)
User avatar
xenos
Member
Member
Posts: 1121
Joined: Thu Aug 11, 2005 11:00 pm
Libera.chat IRC: xenos1984
Location: Tartu, Estonia
Contact:

Re: Linking crt*.o in 64bit kernel image

Post by xenos »

What does your compiler command line look like?
Programmers' Hardware Database // GitHub user: xenos1984; OS project: NOS
robbiedobbie
Member
Member
Posts: 36
Joined: Fri May 16, 2014 2:40 pm
Libera.chat IRC: robbiedobbie

Re: Linking crt*.o in 64bit kernel image

Post by robbiedobbie »

@Owen
Hmm, I will try with the smaller addresses, but I would prefer using this bigger address.

@XenOS
Currently my whole makefile looks like this: CC=/home/rob/opt/cross/bin/x86_64-elf-gcc

Code: Select all

CXX=/home/rob/opt/cross/bin/x86_64-elf-g++
ASM=yasm

ASMFLAGS=-f elf64
CXXFLAGS= -O2 -std=c++11 -ffreestanding -Wall -Wextra -fno-exceptions -fno-rtti -nostdlib -mcmodel=large
LDFLAGS=-T linker.ld -nostdlib -ffreestanding -z max-page-size=0x1000 -mcmodel=large

LDFLAGSDBG= -g -ggdb
CFLAGSDBG= -g -ggdb
CXXFLAGSDBG= -g -ggdb
ASMFLAGSDBG= -g dwarf2

CRTBEGIN_OBJ:=$(shell $(CC) $(CFLAGS) -print-file-name=crtbegin.o)
CRTEND_OBJ:=$(shell $(CC) $(CFLAGS) -print-file-name=crtend.o)
OBJFILES=src/main.o

default: release

all: clean release

debug: LDFLAGS+=${LDFLAGSDBG}
debug: ASMFLAGS+=${ASMFLAGSDBG}
debug: CFLAGS+=$(CFLAGSDBG)
debug: CXXFLAGS+=$(CXXFLAGSDBG)
debug: release

release: src/bootstrap.o src/start64.o src/crti.o ${OBJFILES} src/crtn.o
	mkdir -p bin
	${CXX} ${LDFLAGS} -o bin/kernel src/bootstrap.o src/start64.o src/crti.o ${CRTBEGIN_OBJ} ${OBJFILES} ${CRTEND_OBJ} src/crtn.o -mcmodel=large -lgcc 

.s.o:
	${ASM} ${ASMFLAGS} -o $@ $<
.c.o:
	${CXX} ${CXXFLAGS} -o $@ -c $<

clean:
	rm -Rf src/*.o
User avatar
bluemoon
Member
Member
Posts: 1761
Joined: Wed Dec 01, 2010 3:41 am
Location: Hong Kong

Re: Linking crt*.o in 64bit kernel image

Post by bluemoon »

robbiedobbie wrote:Hmm, I will try with the smaller addresses, but I would prefer using this bigger address.
May I know the reason?

note that mcmodel=kernel only require the static code to put in the address range. It do not restrict the use of 64-bit data pointers and function pointers.
robbiedobbie
Member
Member
Posts: 36
Joined: Fri May 16, 2014 2:40 pm
Libera.chat IRC: robbiedobbie

Re: Linking crt*.o in 64bit kernel image

Post by robbiedobbie »

There was no real reason for the kernel design or something. It was more like, it should be possible, so I wanna try it :P
robbiedobbie
Member
Member
Posts: 36
Joined: Fri May 16, 2014 2:40 pm
Libera.chat IRC: robbiedobbie

Re: Linking crt*.o in 64bit kernel image

Post by robbiedobbie »

Ok, so I have been changing everything to the other base adress, but still have similar issues.

I'm now using -mcmodel=kernel on the compilation of my c files and on my link command. There are less errors, but the following remain:

Code: Select all

/home/rob/opt/cross/bin/x86_64-elf-g++ -T linker.ld -nostdlib -ffreestanding -z max-page-size=0x1000 -mcmodel=kernel -g -ggdb -o bin/kernel src/bootstrap.o src/start64.o src/crti.o /home/rob/opt/cross/lib/gcc/x86_64-elf/4.9.0/crtbegin.o src/main.o /home/rob/opt/cross/lib/gcc/x86_64-elf/4.9.0/crtend.o src/crtn.o -lgcc 
/home/rob/opt/cross/lib/gcc/x86_64-elf/4.9.0/crtbegin.o: In function `deregister_tm_clones':
crtstuff.c:(.text+0x1): relocation truncated to fit: R_X86_64_32 against symbol `__TMC_END__' defined in .jcr section in bin/kernel
crtstuff.c:(.text+0x21): relocation truncated to fit: R_X86_64_32 against `.tm_clone_table'
/home/rob/opt/cross/lib/gcc/x86_64-elf/4.9.0/crtbegin.o: In function `register_tm_clones':
crtstuff.c:(.text+0x41): relocation truncated to fit: R_X86_64_32 against symbol `__TMC_END__' defined in .jcr section in bin/kernel
crtstuff.c:(.text+0x6f): relocation truncated to fit: R_X86_64_32 against `.tm_clone_table'
/home/rob/opt/cross/lib/gcc/x86_64-elf/4.9.0/crtbegin.o: In function `__do_global_dtors_aux':
crtstuff.c:(.text+0x8f): relocation truncated to fit: R_X86_64_32 against symbol `__DTOR_END__' defined in .dtors section in /home/rob/opt/cross/lib/gcc/x86_64-elf/4.9.0/crtend.o
crtstuff.c:(.text+0xe6): relocation truncated to fit: R_X86_64_32 against `.eh_frame'
/home/rob/opt/cross/lib/gcc/x86_64-elf/4.9.0/crtbegin.o: In function `frame_dummy':
crtstuff.c:(.text+0x10f): relocation truncated to fit: R_X86_64_32 against `.bss'
crtstuff.c:(.text+0x114): relocation truncated to fit: R_X86_64_32 against `.eh_frame'
crtstuff.c:(.text+0x11e): relocation truncated to fit: R_X86_64_32 against `.jcr'
/home/rob/opt/cross/lib/gcc/x86_64-elf/4.9.0/crtend.o: In function `__do_global_ctors_aux':
crtstuff.c:(.text+0x6): relocation truncated to fit: R_X86_64_32 against `.ctors'
collect2: error: ld returned 1 exit status
Since I figgured that the crtstuff.c is compiled with the compilation of the crosscompiler, I also tried to compile the whole crosscompiler again with -mcmodel=kernel, which didn't result in any improvements.

It looks like my crtbegin.o is simply incompatible with memory adresses like this. How can I solve this?
PinkyNoBrain
Posts: 22
Joined: Mon Oct 29, 2007 10:49 am

Re: Linking crt*.o in 64bit kernel image

Post by PinkyNoBrain »

Hi robbiedobbie,

I encountered the same issue myself when trying to add c++ global constructor calling to my 64bit higher half kernel and think i may have found a solution :D

Its a bit ugly but this is what i did:
  • (as you say) crtbegin.o and crtend.o are built from crtstuff.c during compilation of the crosscompiler so i rebuilt my crosscompiler and piped the build output to a file
  • I borrowed crtstuff.c and included it in my own source files
  • I greped the build output file for crtstuff.c which gave me the two commands used to build it (once for crtbegin.o and once for crtend.o)
  • I added entries fro crtbegin.o and crtend.o to my makefile, building with the commands identified above
  • I had to update some of the -I statements in the compile commands to include some directories from the gcc source bundle
  • I also added -mcmodel=kernel to both command
  • After all that i was able to build my own crtbegin.o and crtend.o and use them to call my global constrctuors :D
This is not an ideal solution but i think its preferable to remaking the whole of libgcc with mcmodel=kernel. Hopefully its clear and it works for you.

Let me know if you need any more details,

Thanks,

Pinky
robbiedobbie
Member
Member
Posts: 36
Joined: Fri May 16, 2014 2:40 pm
Libera.chat IRC: robbiedobbie

Re: Linking crt*.o in 64bit kernel image

Post by robbiedobbie »

Hi PinkyNoBrain,

I never noticed your reply, but I want to thank you, since it actually did help!

I started over from scratch recently, and again encountered the problem of having a higher half 64bit kernel and linking crtbegin.o and crtend.o. I got it working by seperately compiling crtstuff.c with mcmodel=kernel./

Thank you!
nbdd0121
Member
Member
Posts: 60
Joined: Thu Jul 25, 2013 8:10 am

Re: Linking crt*.o in 64bit kernel image

Post by nbdd0121 »

I found this when I encountered the same problem, and I eventually solved this. I just post here for a note: what I do is add CFLAGS_FOR_TARGET='-g -O2 -mcmodel=large' when making all-target-libgcc.
Post Reply