This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Re: RFC: using ld 2.14 on irix
- From: Richard Sandiford <rsandifo at redhat dot com>
- To: binutils at sources dot redhat dot com
- Date: 14 Jun 2003 20:08:12 +0100
- Subject: Re: RFC: using ld 2.14 on irix
- References: <wvnk7bprop0.fsf@talisman.cambridge.redhat.com>
Richard Sandiford <rsandifo@redhat.com> writes:
> With these changes I was able to successfully bootstrap gcc 3.4
> using GNU as & ld. There seem to be some problems with the DSOs
> it created, looking at that now. (The DSOs created by the unpatched
> linker fail too, so it might not be caused by these patches.)
Hmm, beginning to wish I'd stuck to gcc. ;)
To quote the R_MIPS_REL32 passage again:
> The value EA used by the dynamic linker to relocate an R_MIPS_REL32
> relocation depends on its r_symndx value. If the relocation entry
> r_symndx is less than DT_MIPS_GOTSYM, the value of EA is the symbol
> st_value plus displacement. Otherwise, the value of EA is the
> value in the GOT entry corresponding to the relocation entry
> r_symndx.
and the R_MIPS_REL32 equation is:
> A - EA + S
where A is the in-place addend and S is the final symbol value.
So if a relocation is against a global symbol, the process seems to be:
- subtract the initial contents of the symbol's GOT entry
- add in the symbol's final value
(Note: I think the passage must mean the initial value of the
GOT entry since the final value will usually be S.)
My previous two patches seem to make ld follow this definition
for externally-defined symbols. But we still have a problem with
locally-defined ones. Test case:
$ cat gromit.c
int x = 2;
int *y = &x;
$ cat print.c
extern int *y;
int main ()
{
printf ("%p\n", y);
if (y != 0)
printf ("%x\n", *y);
return 0;
}
Compile as:
$ cc -c gromit.o
$ cc -c print.o
Link as:
$ $LD gromit.o -o gromit.so -shared
$ $LD /usr/lib32/crt1.o print.o gromit.so /usr/lib32/libc.so.1 \
/usr/lib32/crtn.o -rpath `pwd`
With LD set to the native linker, I get the expected:
$ ./a.out
5ff74000
2
Substitute ld 2.14 without any patches:
$ ./a.out
0
Likewise after applying the patches from my previous message.
Looking at the gromit.so produced by 2.14, the data section is:
Contents of section .data:
600e0440 00000002 00000000 ........
^^^^^^^^ "y"
The single GOT entry for global symbols is:
Index Content gp_reladdr Address
[ 7]: 0x600e0440 -32724(gp), 0x600e067c [x]
and the relocations are:
Relocation section '.rel.dyn' at offset 0x420 contains 2 entries:
Offset Info Type Sym.Value Sym. Name
00000000 00000000 R_MIPS_NONE
600e0444 00002003 R_MIPS_REL32 600e0440 x
gromit.so is loaded at its natural address, so y is set to:
A - EA + S
0 + 0x600e0440 - 0x600e0440 = 0
I think the intent is that A should be initialised to EA plus any
offset. The patch below seems to do that and produces a "fixed"
gromit.so. Initial tests suggest it also builds a working
libstdc++.so, which the old ld didn't. I'm now running a full
bootstrap with the patch applied.
Repeating the experiment for o32 shows the same thing.
I.e. ld 2.14 didn't work, but the patched linker did.
I also tried linking in other dummy DSOs so that gromit.so
isn't always loaded at DT_MIPS_BASE_ADDRESS. The patch still
seems to work in this case.
Unfortunately, the patch breaks mipsel-linux-gnu. glibc seems to have
a very different idea about how to apply R_MIPS_REL32. Looking at
dl-machine.h (2.2.5 and 2.3.2), it adjusts the GOT before applying any
relocations, then it adds the (final) GOT entries to the relocation fields.
Am I going insane, or is there really a fundamental difference here?
If the latter, is it a known problem? I don't see how we can keep
both glibc and irix rld happy.
Richard
PS. Symbol preemption doesn't seem to work on irix with 2.14.
That's the least of my worries at the moment, though...
* bfd/elfxx-mips.c (mips_elf_create_dynamic_relocation): If the output
bfd defines a global symbol, add its value to the relocation field.
Index: bfd/elfxx-mips.c
===================================================================
RCS file: /cvs/src/src/bfd/elfxx-mips.c,v
retrieving revision 1.51.4.3
diff -u -d -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.51.4.3 elfxx-mips.c
--- bfd/elfxx-mips.c 30 May 2003 20:13:05 -0000 1.51.4.3
+++ bfd/elfxx-mips.c 14 Jun 2003 19:06:44 -0000
@@ -3886,6 +3886,7 @@ mips_elf_create_dynamic_relocation (outp
else
{
long indx;
+ bfd_boolean undefined_p;
/* We must now calculate the dynamic symbol table index to use
in the relocation. */
@@ -3898,6 +3899,8 @@ mips_elf_create_dynamic_relocation (outp
become local. */
if (indx == -1)
indx = 0;
+ undefined_p = ((h->root.elf_link_hash_flags
+ & ELF_LINK_HASH_DEF_REGULAR) == 0);
}
else
{
@@ -3927,13 +3930,14 @@ mips_elf_create_dynamic_relocation (outp
useful, after all. This should be a bit more efficient
as well. */
indx = 0;
+ undefined_p = FALSE;
}
/* If the relocation was previously an absolute relocation and
this symbol will not be referred to by the relocation, we must
adjust it by the value we give it in the dynamic symbol table.
Otherwise leave the job up to the dynamic linker. */
- if (!indx && r_type != R_MIPS_REL32)
+ if (!undefined_p && r_type != R_MIPS_REL32)
*addendp += symbol;
/* The relocation is always an REL32 relocation because we don't