This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: RFC: using ld 2.14 on irix


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]