Page 1 of 2
relocation truncated to fit: R_X86_64_32...
Posted: Tue Jun 08, 2010 3:00 pm
by proxy
It's the error that everyone sees when they first try to port to x86_64
.
I was able to work around this by using
and this works very well. Unfortunately, it also creates
very inefficient code.
Basically, every single call will end up being compiled to something like this:
And I mean, every call.
I found this surprising, I figured that gcc would be smart enough to use 32-bit relative displacements at least when the two functions are in the same translation unit (same file). But alas it does this for every single call. I know gcc is being safe, but has anyone figured out a way to indentify the cause of these relocation errors and code around them?
As far as I can tell, linux works around this by putting it's kernel code in the last 2GB of the address space and using
. I (like some others as far as I can tell) have opted for a 50/50 split in long mode. The errors only occur on a few objects and are almost exclusively in virtual destructors (sometimes empty ones!).
What are people's experiences with this?
Re: relocation truncated to fit: R_X86_64_32...
Posted: Tue Jun 08, 2010 3:26 pm
by gerryg400
I've been using mcmodel=kernel.
It's working fine normally, but occasionally I find there are functions in newlib that I can't link to. I don't know why I can link to some and not others. I must admit I haven't investigated this issue yet because so far the functions I've needed have been okay.
I'll look into this tonight. I suspect eventually I'll have 2 versions of newlib. One for the kernel and one for apps.
Re: relocation truncated to fit: R_X86_64_32...
Posted: Tue Jun 08, 2010 3:29 pm
by proxy
Yea, i've been playing around with it too and the issue often happens in my libc and libstdc++ that i've written for my kernel space (one day i'll open source them
).
Anyway, I've found that I was able to get away with "-fPIC -mcmodel=small" and it produces better code. calls that can be direct are, the only inefficiency is now it uses a bunch of rip relative addresses when a dealing with globals. But this is certainly better than having every single call be an indirect one!
Re: relocation truncated to fit: R_X86_64_32...
Posted: Tue Jun 08, 2010 4:24 pm
by Owen
Whats wrong with placing the kernel code in the upper 2GB? You can put other data (Heap or other structures) wherever you want - you just need to put the code in the top.
Re: relocation truncated to fit: R_X86_64_32...
Posted: Tue Jun 08, 2010 4:40 pm
by gerryg400
Whats wrong with placing the kernel code in the upper 2GB? You can put other data (Heap or other structures) wherever you want - you just need to put the code in the top.
There's no problem with that. But you apparently need to have all your code compiled with the same memory mode. And it's not clear to me exactly why.
Consider the following:
- kernel is -2GB
- library is large model.
If the kernel calls a library function that uses data or calls another function
even if the function or data is defined in the same .o file in the library file, ld complains. Why does it need to do that?
Code: Select all
/Users/gerryg/artix/usr/x86_64-artix/lib/libc.a(lib_a-printf.o): In function `_printf_r':
/Users/gerryg/tools/newlib-build/x86_64-artix/newlib/libc/stdio/../../../../../newlib-1.18.0/newlib/libc/stdio/printf.c:29: relocation truncated to fit: R_X86_64_32 against `.text'
If the kernel calls a function that doesn't access any data or call other functions e.g. strcpy, all is okay
Re: relocation truncated to fit: R_X86_64_32...
Posted: Tue Jun 08, 2010 4:55 pm
by proxy
Well, I am putting my kernel at 0xffff800000200000 mainly because it makes the initial paging dirt simple. I just 1:1 map the first few megs of memory in both the 0th and 255th entries of the PML4 and jump high. When I do this, i map the same PDP to both entries of the PML4. If i put it into the upper 2GB I don't think it would be quite so easy to reuse the same PDP.
Re: relocation truncated to fit: R_X86_64_32...
Posted: Tue Jun 08, 2010 5:51 pm
by gerryg400
To use the -2GB plan you'll need to map common pgdirs. It's the same idea but just one level down. pgdirs cover 1GB you'll need two to cover the entire -mcmodel=kernel space.
Re: relocation truncated to fit: R_X86_64_32...
Posted: Tue Jun 08, 2010 6:39 pm
by Owen
proxy wrote:Well, I am putting my kernel at 0xffff800000200000 mainly because it makes the initial paging dirt simple. I just 1:1 map the first few megs of memory in both the 0th and 255th entries of the PML4 and jump high. When I do this, i map the same PDP to both entries of the PML4. If i put it into the upper 2GB I don't think it would be quite so easy to reuse the same PDP.
Duplicate the first entry of the PDPT too. Erase it when you erase the PML4E. Simple.
Re: relocation truncated to fit: R_X86_64_32...
Posted: Tue Jun 08, 2010 9:24 pm
by gerryg400
I confirmed that gcc seems always to let LD resolve the address of all function calls even when functions are in the same file and it would be possible for it to resolve rip relative function calls itself. -fPIC seems to change that.
I've also had a little look and I believe the cause of my problem, at least, is that gcc generates 2 different relocation types for 32 bit register moves, depending on the memory model and the register size. e.g. For a (32bit) mov to a 64 bit register it uses a R_X86_64_32S and for a mov to a 32 bit register it generates a R_X86_64_32. The type of instruction chosen depends on the memory model. According to the ABI these two relocation types seem identical to me, but ld thinks they are different. Maybe they are different.
Bottom line is that I will need to have 2 versions of newlib. One with -mcmodel=kernel, one with -mcmodel=small (the default) for user space programs.
Does anyone know any reason we can't put -fPIC as a default option ?
Re: relocation truncated to fit: R_X86_64_32...
Posted: Wed Jun 09, 2010 3:19 am
by gerryg400
Just got newlib compiling with -mcmodel=kernel. Links well with my kernel finally. Now I have access to malloc from within my memory manager.
Does anyone know whether -mcmodel=kernel needs to be a the -2GB mark? Or would it work at any upper half address as long as it were 2GB aligned ?
Re: relocation truncated to fit: R_X86_64_32...
Posted: Wed Jun 09, 2010 6:05 am
by Owen
gerryg400 wrote:I confirmed that gcc seems always to let LD resolve the address of all function calls even when functions are in the same file and it would be possible for it to resolve rip relative function calls itself. -fPIC seems to change that.
I've also had a little look and I believe the cause of my problem, at least, is that gcc generates 2 different relocation types for 32 bit register moves, depending on the memory model and the register size. e.g. For a (32bit) mov to a 64 bit register it uses a R_X86_64_32S and for a mov to a 32 bit register it generates a R_X86_64_32. The type of instruction chosen depends on the memory model. According to the ABI these two relocation types seem identical to me, but ld thinks they are different. Maybe they are different.
Bottom line is that I will need to have 2 versions of newlib. One with -mcmodel=kernel, one with -mcmodel=small (the default) for user space programs.
Does anyone know any reason we can't put -fPIC as a default option ?
I'm gonna guesss... The S in "R_X86_23S" means "signed" or "sign extended"
Re: relocation truncated to fit: R_X86_64_32...
Posted: Thu Jun 10, 2010 6:57 am
by pcmattman
gerryg400 wrote:Just got newlib compiling with -mcmodel=kernel. Links well with my kernel finally.
Can you compile newlib with -fPIC? It's been an awful long time since I built an x86_64 newlib, but it should be able to compile with -fPIC and shouldn't need mcmodel directives to compile. It should then link in to whatever you give it. If I remember right.
Re: relocation truncated to fit: R_X86_64_32...
Posted: Thu Jun 10, 2010 7:20 am
by gerryg400
Yes, it compiles, links and runs. So, which should I use ? -fPIC or -mcmodel=kernel ?
Re: relocation truncated to fit: R_X86_64_32...
Posted: Thu Jun 10, 2010 7:24 am
by pcmattman
For a library I'd be inclined to say -fPIC. One significant bonus of -fPIC is that later you can extract all the object files from your libc and recompile them into a shared object, without recompiling newlib from scratch. You also avoid having the compiler "optimise" by hardcoding addresses which might conflict with your kernel.
Re: relocation truncated to fit: R_X86_64_32...
Posted: Thu Jun 10, 2010 8:07 am
by gerryg400
I had a look at the generated code for -fPIC and -mcmodel. It only really differs significantly when global variables are accessed. -fPIC uses rip relative addressing which looks slightly bigger and is I imagine slightly slower. I don't suppose there are many globals in newlib, so it probably doesn't matter too much. I'm gonna go with -mcmodel=kernel though.