unresolvable R_X86_64_32S relocation

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
User avatar
bluecode
Member
Member
Posts: 202
Joined: Wed Nov 17, 2004 12:00 am
Location: Germany
Contact:

unresolvable R_X86_64_32S relocation

Post by bluecode »

hi,

My OS currently has got a protected-mode and a longmode version. I use shared-libraries for libc (and other libraries). Since I use "-z nocopyreloc" for ld, I get "unresolvable R_X86_64_32S relocation" warnings (only about relocations to data in the shared-library) but only in my longmode version. But everything worked fine untill now. Today I had to discover painfully that under some circumstances this leads to real trouble. The following Code resulted from debugging binutil's cxxfilt (I know that this is worse code and non-standard conformant, but it did the job ;-) ):

Code: Select all

// NOTE: _sch_istable is an array of some type and it is in libiberty.so
printf("@ 0x%x\n", &_sch_istable[0]);
printf("@ 0x%x\n", &_sch_istable[c]);
And the output was:
@ 0x70045160
@ 0x90
That looks pretty weird :shock: (c is a character read from stdin)
Then I looked into the build log and found ld complaining about exactly that symbol with a "unresolvable R_X86_64_32S relocation"... So my question is basically how could I fix that :?:
I implemented shared-libraries like this: The code of a shared-library is shared between all process's and the data is copy-on-write. When I load a library I save all the symbols in a global list. If another shared-library or a process needs one of the symbols it looks into that table and the relocation is done with the information from this global table.
The normal ld behaviour would be to copy all data from the shared-libraries into the userspace app. But some libraries (e.g. libc++) need symbols from other libraries (e.g. a FILE structure for stdout). And since I don't want to patch libc++'s code for every process differently, I use -z nocopyreloc. That basically tells ld not to copy the shared-libraries data into the userspace (this would normally be done via a special relocation type), but to use the address from the shared-library. This works fine for x86, but it results in ld warnings on x86-64.

My current compile/link flags for applications (for x86-64) look like this:
C_FLAGS= -std=gnu99 -nostdlib -fno-builtin -Wall -fno-omit-frame-pointer -m64
LD_FLAGS= -z nocopyreloc
Adding -mcmodel=medium did not change anything. iirc I also tried to compile the libraries with fPIC (instead of fpic) and this also did not change a thing.

In case anyone wants to get his/her hands dirty you could do a subversion checkout and try to build lightOS yourself (But that implies building a cross-compiler...).

I hope I posted all the information needed. If there is anything missing, just ask for it :idea:
Last edited by bluecode on Thu Sep 06, 2007 11:49 am, edited 1 time in total.
User avatar
bluecode
Member
Member
Posts: 202
Joined: Wed Nov 17, 2004 12:00 am
Location: Germany
Contact:

Post by bluecode »

I think ld just leaves out the R_X86_64_32S relocation :shock:

My cxxfilt.o looks like:

Code: Select all

 306:	45 89 ec             	mov    %r13d,%r12d
 309:	0f b6 c3             	movzbl %bl,%eax
 30c:	f6 84 00 00 00 00 00 	testb  $0x8c,0x0(%rax,%rax,1)
			30f: R_X86_64_32S	_sch_istable
and objdump shows:
objdump cxxfilt.o -r | grep _sch_istable
000000000000030f R_X86_64_32S _sch_istable
The final executeable looks like:

Code: Select all

  400466:	45 89 ec             	mov    %r13d,%r12d
  400469:	0f b6 c3             	movzbl %bl,%eax
  40046c:	f6 84 00 00 00 00 00 	testb  $0x8c,0x0(%rax,%rax,1)
and the relocation is gone in objdump.
User avatar
bluecode
Member
Member
Posts: 202
Joined: Wed Nov 17, 2004 12:00 am
Location: Germany
Contact:

Post by bluecode »

Ok, I "fixed" the problem: I compile my whole userspace now with -fpic (for x86-64). To get this working I had to do some smaller changes in my elf loader.
Imho this is a hack... Perhaps the large code model fixes that.
speal
Member
Member
Posts: 43
Joined: Wed Mar 07, 2007 10:09 am
Location: Minneapolis, Minnesota
Contact:

Post by speal »

I'm also using the -fPIC option to "fix" this problem. I was told at the time there was basically no penalty for using PIC in long mode, since offsets can be larger. I'll try to find the explanation, but I remember being convinced enough not to look for another solution.

If you plan to keep the entire upper half of address space for the kernel, you'll need to stick with the -fPIC option, since there are no implemented memory models for the 64 bit target that will allow for that range of addresses (thanks GCC). When asked why it wasn't implemented, a GCC developer said "that would be a bad way to do it, so we aren't implementing it." I guess they're saving us from ourselves, but I would have liked the option. This is all as of GCC 4.1.2, however.
User avatar
bluecode
Member
Member
Posts: 202
Joined: Wed Nov 17, 2004 12:00 am
Location: Germany
Contact:

Post by bluecode »

speal wrote:I'm also using the -fPIC option to "fix" this problem.
For me -pic (note the small letters) was sufficient. At least I had no errors/warnings through compiler phase.
I was told at the time there was basically no penalty for using PIC in long mode, since offsets can be larger.
I have the feeling that the code gets slightly bigger. But it is not that worse.
If you plan to keep the entire upper half of address space for the kernel, you'll need to stick with the -fPIC option, since there are no implemented memory models for the 64 bit target that will allow for that range of addresses (thanks GCC).
Well, I stick with mcmodel=kernel.
btw. the gcc roadmap says, that the large code model will be in gcc 4.3.
Post Reply