Infamous relocation problem amd64

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
jangalian2
Posts: 9
Joined: Fri Apr 11, 2008 12:36 am

Infamous relocation problem amd64

Post by jangalian2 »

Hi,
I started to rewrite my OS in 64 bits, but I'm stuck with this ******* message "relocation truncated to fit: R_X86_64_32S against `.data'"
I suppose that this is due to the fact that the code generated has 32 bits pointers or similar even if I use elf64-x86-64 as output format.
I tried with GCC options -mcmodel=medium/kernel -fpic/PIC but none worked for me.
My standard compilation flags are CFLAGS=-O2 -fomit-frame-pointer -nostdinc -I $(INCLUDE_PATH) -Wall
Am I missing something?
To retain compatibility with my old loader I've linked my kernel to run at 0x0c0010000 (real addr 0x10000) and everything compiles until the .code64 tag in assembly file is reached.
Such instructions :
leaq boot_isr_msg,%rax

are truncated to fit a 32 bit pointer and prevents the generation of the image file.
Can anybody help me? How am I supposed to produce 64(52) bits addressing in my kernel?
I've studied manuals and searched for days but with no fortune!
Thanks in advance!
Attachments
link.rules.64.txt
This is my linker script added for clarity
(649 Bytes) Downloaded 84 times
User avatar
JamesM
Member
Member
Posts: 2935
Joined: Tue Jul 10, 2007 5:27 am
Location: York, United Kingdom
Contact:

Post by JamesM »

Hi,

A google found this page, in which a gcc board member suggests using the flag -mcmodel=medium.

Try that and see if it works.

Cheers,

James

EDIT: our project's cxxflags also include "-mcmodel=kernel". Try that as well.
jangalian2
Posts: 9
Joined: Fri Apr 11, 2008 12:36 am

Post by jangalian2 »

JamesM wrote:Hi,

A google found this page, in which a gcc board member suggests using the flag -mcmodel=medium.

Try that and see if it works.

Cheers,

James

EDIT: our project's cxxflags also include "-mcmodel=kernel". Try that as well.
I've tried everything before posting, with no results :( You guys are my last hope , at least until the -mcmodel=large will be supported
User avatar
Zenith
Member
Member
Posts: 224
Joined: Tue Apr 10, 2007 4:42 pm

Post by Zenith »

A few things:

- Are you using a seperate elf32 loader for your file, GRUB (no elf64 support), GRUB2, or is the 32-bit bootstrap code compiled into the executable as well?

- Make sure you're using a 64-bit (x86_64-pc-elf-gcc) cross-compiler!

- Also, make sure to add .code32 at the top of any 32-bit assembly files

- AFAIK, GCC 4.3 supports -mcmodel=large (I'm using it right now)

There should be a wiki tutorial on how to compile and load a 64-bit kernel... I'll get on it. :)
"Sufficiently advanced stupidity is indistinguishable from malice."
jangalian2
Posts: 9
Joined: Fri Apr 11, 2008 12:36 am

Post by jangalian2 »

karekare0 wrote:A few things:

- Are you using a seperate elf32 loader for your file, GRUB (no elf64 support), GRUB2, or is the 32-bit bootstrap code compiled into the executable as well?
No, I use a self developed OS loader, which works well - I have only this compile problem
karekare0 wrote: - Make sure you're using a 64-bit (x86_64-pc-elf-gcc) cross-compiler!
I'm pretty sure the result is an elf x86_64...
karekare0 wrote: - Also, make sure to add .code32 at the top of any 32-bit assembly files
I use the .code32 to initialize long mode, then I switch to .code64 just before reloading CS.
karekare0 wrote: - AFAIK, GCC 4.3 supports -mcmodel=large (I'm using it right now)
I'm compiling it just now!

karekare0 wrote: There should be a wiki tutorial on how to compile and load a 64-bit kernel... I'll get on it. :)
This is a very precious information, I'll have a look on it. But I'm confident that the -mcmodel=large will solve the problem,,,
Thanks!
jangalian2
Posts: 9
Joined: Fri Apr 11, 2008 12:36 am

LD still does not link....

Post by jangalian2 »

:( I've recompiled gcc 4.3.0 (nearly 4 hours on my poor notebook!) so I'm able to compile my sources using the -mcmodel=large. But GNU LD does not link so I don't know what else to do :evil:. Am I missing some linker option? Have I to compile binutils?
May be I'm wrong on the logic - the kernel is linked to be at 0x0c0010000 when it really is at 0x10000.
Thanks!
User avatar
Zenith
Member
Member
Posts: 224
Joined: Tue Apr 10, 2007 4:42 pm

Post by Zenith »

Note that it should by 0x100000, not 0x10000. You're forgetting one zero. :wink:

If you're linking your kernel to 0xc0100000, make sure your code enters virtual memory too.

Also, what error does GNU LD give? I'm assuming you're using a cross-compiled LD, right?
"Sufficiently advanced stupidity is indistinguishable from malice."
jangalian2
Posts: 9
Joined: Fri Apr 11, 2008 12:36 am

Post by jangalian2 »

karekare0 wrote:Note that it should by 0x100000, not 0x10000. You're forgetting one zero. :wink:

If you're linking your kernel to 0xc0100000, make sure your code enters virtual memory too.

Yes, I'm running my small kernel at 0x10000 in low memory by design, but I've compiled it as if it is 3 Gb above. I put the paging tables at 0x100000 (absolute address) so I have to patch every address (eg gdt-0x0c0000000) until I reload segments in long mode, when pages from 0x0c0000000 to 0x0c0200000 are mapped to point the first two megs of ram.
karekare0 wrote:Also, what error does GNU LD give? I'm assuming you're using a cross-compiled LD, right?
No I'm not using a cross compiler at this stage; Note that I'm not having execution issues (my setup code works), the problem is that istructions like the following:

leaq isr_msg,%rax #-> causes the relocation problem
leaq isr_msg-0x0c0000000,%rax #-> assembles well

Since the virtual memory is enabled they are both equivalent.
My linker invocation is
ld -M --cref -o kernel.img -T link.rules.64 -nodefaultlibs -nostdlib -Map kernel.map *.o
where link.rules.64 is the linker script posted in my first post.
jangalian2
Posts: 9
Joined: Fri Apr 11, 2008 12:36 am

Force gcc to generate large memory model on asm sources

Post by jangalian2 »

My problem is that the GCC insists to generate 32 bits addressing on .text coming from asm files; code from C files is true 64 bit in both code and pointers.
So the question is obvious: how can I force the generation of 64 bits addressing in assembly files? Is there something which overrides the .code64 statement?
My relevant CFLAGS are:

-c -O2 -mcmodel=large -m64 -fomit-frame-pointer -nostdinc -nostdlib -ffreestanding -Wall

I use GCC 4.3.0 and recompiled binutils
Any help? Thanks!
jangalian2
Posts: 9
Joined: Fri Apr 11, 2008 12:36 am

SOLVED!!!!

Post by jangalian2 »

The solution is to change the asm from:

lealq my_C_func,%rax / movq $my_C_func,%rax
(which generates the truncation error)

to:

movabsq $my_C_func,%rax

which forces GCC to generate the absolute address.

This may be obvious for the most of you, but I report this because this stupid thing was like a thorn twisted in my side....

Matteo
Post Reply