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]

RFC: using ld 2.14 on irix


I've been trying to get ld 2.14 to work on irix6.  In an earlier message,
I rather optimistically said that it seemed to be in good shape.  I'd like
to retract that, please. ;)

Here's a reduced test case:

    ------------------------------------------------------------------
    $ cat foo.c
    extern char __us_rsthread_stdio[];
    extern char __iob[];
    extern char __month_size[];

    void *f1 = __us_rsthread_stdio;
    void *f2 = __iob;
    void *f3 = __month_size;

    int main () { printf ("%p %p %p\n", f1, f2, f3); return 0; }
    ------------------------------------------------------------------

(cheesily borrowing symbols from libc.so).  Compile and link with:

    $ cc foo.c -c
    $ $LD /usr/lib32/crt1.o foo.o /usr/lib32/libc.so.1 /usr/lib32/crtn.o

With $LD=ld (the SGI linker) I get the expected:

    $ ./a.out
    fb51e00 fb52520 fb0d1c8

With $LD set to ld 2.14, I get:

    $ ./a.out
    0 0 0

There seem to be two problems:

    1. the way the GOT is initialised
    2. the contents of .msym

First, the GOT.  Here's what it looks like after linking with ld 2.14:

    ------------------------------------------------------------------
                Index   Content  gp_reladdr   Address
        [         7]: 0x10100960 -32724(gp), 0x101008fc [__Argc]
 ==>    [         8]: 0x0fb52520 -32720(gp), 0x10100900 [__iob]
        [         9]: 0x10000598 -32716(gp), 0x10100904 [exit]
        [        10]: 0x1010061c -32712(gp), 0x10100908 [f1]
        [        11]: 0x1000045c -32708(gp), 0x1010090c [__istart]
 ==>    [        12]: 0x0fb51e00 -32704(gp), 0x10100910 [__us_rsthread_stdio]
        [        13]: 0x100005c0 -32700(gp), 0x10100914 [main]
        [        14]: 0x10100620 -32696(gp), 0x10100918 [f2]
        [        15]: 0x10100624 -32692(gp), 0x1010091c [f3]
 ==>    [        16]: 0x0fb0d1c8 -32688(gp), 0x10100920 [__month_size]
        [        17]: 0x0fb52378 -32684(gp), 0x10100924 [_environ]
        [        18]: 0x10000588 -32680(gp), 0x10100928 [__readenv_sigfpe]
        [        19]: 0x10100950 -32676(gp), 0x1010092c [__Argv]
        [        20]: 0x0fa46210 -32672(gp), 0x10100930 [printf]
    ------------------------------------------------------------------

where the entries marked with "==>" are referenced by dynamic relocations:

    ------------------------------------------------------------------
    Relocation section '.rel.dyn' at offset 0x430 contains 4 entries:
     Offset     Info    Type            Sym.Value  Sym. Name
    00000000  00000000 R_MIPS_NONE      
    10100620  00000c03 R_MIPS_REL32      00000000   __iob
    1010061c  00001003 R_MIPS_REL32      00000000   __us_rsthread_stdio
    10100624  00001403 R_MIPS_REL32      00000000   __month_size
    ------------------------------------------------------------------

As you can see, the GOT entries for external symbols are initialised
with the st_value from libc.so.  The following code in elfxx-mips.c
is responsible for picking this value:

      if (sym->st_value)
        value = sym->st_value;
      else
        {
          /* For an entity defined in a shared object, this will be
             NULL.  (For functions in shared objects for
             which we have created stubs, ST_VALUE will be non-NULL.
             That's because such the functions are now no longer defined
             in a shared object.)  */

          if ((info->shared && h->root.type == bfd_link_hash_undefined)
              || h->root.type == bfd_link_hash_undefweak)
            value = 0;
          else
            value = h->root.u.def.value;
        }

That's fine for QuickStart, but I thought that wasn't supported.
And the current behaviour seems to conflict with the ABI for
non-QuickStart objects.

In terms of the code above, it's the st_value == 0 case that
I'm worried about.  The ABI says:

  --------------------------------------------------------------------
        Section      Type        st_value    GOT Entry     Relocation

  [A]   SHN_UNDEF    STT_FUNC    0           0/QS          1

        SHN_UNDEF    STT_FUNC    stub addr   stub addr     2

        SHN_UNDEF    STT_FUNC    stub addr   != stub addr  3

  [B]   SHN_UNDEF    all others  any         0/QS          1
        SHN_COMMON

  [C]   all others   STT_FUNC    address     stub address  2
                                             != address*

  [D]   all others   all others  address     address       1

        * Stub address must be in this executable and can only be
        applied the first time the GOT is modified.

        Relocation:
        1: resolve immediately or use Quickstart value
        2: add run-time displacement to GOT entry
        3: set GOT entry to stub address plus run-time displacement
  --------------------------------------------------------------------

[A], [B], [C] and [D] are the cases where st_value is or might be 0.
I don't believe GNU ld uses case [C].  And [A], [B] & [D] seem to
imply that if st_value is 0, the GOT entry should also be 0 in
non-QuickStart objects.

Anyway, the ABI also says:

    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.

In the object created by ld 2.14, f1, f2 and f3 are initialised to 0:

    Contents of section .data:
     1010061c 00000000 00000000 00000000           ............    

So the three dynamic relocations will be calculated as:

     A - EA + S

     where A = addend (0 in all three cases)
           EA = contents of GOT
           S = final symbol value

Since libc.so.1 is loaded at its QuickStart address, EA = S,
and all three variables stay as 0.

I guess we could fix this by including the external symbol value
in the relocation field, just like the native linker does:

    a.out:     file format elf32-nbigmips

    Contents of section .data:
     1001400c 0fb51e00 0fb52520 0fb0d1c8           ......% ....    

I have no idea what effect this would have on backwards compatibility.

But from the ABI stuff quoted above, it seems more correct to
initialise the GOT with the (local) st_value in all cases.
Simply replacing the elfxx-mips.c code with:

      value = sym->st_value;

gives the following, which seems correct to me:

    ------------------------------------------------------------------
        [         7]: 0x10100960 -32724(gp), 0x101008fc [__Argc]
 ==>    [         8]: 0x00000000 -32720(gp), 0x10100900 [__iob]
        [         9]: 0x10000598 -32716(gp), 0x10100904 [exit]
        [        10]: 0x1010061c -32712(gp), 0x10100908 [f1]
        [        11]: 0x1000045c -32708(gp), 0x1010090c [__istart]
 ==>    [        12]: 0x00000000 -32704(gp), 0x10100910 [__us_rsthread_stdio]
        [        13]: 0x100005c0 -32700(gp), 0x10100914 [main]
        [        14]: 0x10100620 -32696(gp), 0x10100918 [f2]
        [        15]: 0x10100624 -32692(gp), 0x1010091c [f3]
 ==>    [        16]: 0x00000000 -32688(gp), 0x10100920 [__month_size]
        [        17]: 0x00000000 -32684(gp), 0x10100924 [_environ]
        [        18]: 0x10000588 -32680(gp), 0x10100928 [__readenv_sigfpe]
        [        19]: 0x10100950 -32676(gp), 0x1010092c [__Argv]
        [        20]: 0x00000000 -32672(gp), 0x10100930 [printf]
    ------------------------------------------------------------------

With that change I get slightly better results:

    $ ./a.out
    0 0 fb0d1c8

But then we come to the .msym problem.  We're creating the
.msym entries in _bfd_mips_elf_finish_dynamic_symbol, but that's
_before_ we've sorted .rel.dyn.  So the ms_info field refers to
the unsorted index instead of the final one.  

The ABI says that .msym is an optional section, so we could just
remove it.  That indeed fixes the problem and makes the test case
work correctly.

I've had a go at fixing the problem "properly" though.  I haven't
hacked this area of bfd before, so I'm probably doing it all wrong.
It's for information only. ;)

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.)

Anyway, what do you think?  Am I just talking rubbish here? ;)

Richard


	* elfxx-mips.c (_bfd_mips_elf_finish_dynamic_symbol): Always
	initialize a GOT entry to the symbol's st_value.

Index: bfd/elfxx-mips.c
===================================================================
RCS file: /cvs/src/src/bfd/elfxx-mips.c,v
retrieving revision 1.51.4.3
diff -c -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 07:29:20 -0000
*************** _bfd_mips_elf_finish_dynamic_symbol (out
*** 6749,6770 ****
        bfd_vma offset;
        bfd_vma value;
  
!       if (sym->st_value)
! 	value = sym->st_value;
!       else
! 	{
! 	  /* For an entity defined in a shared object, this will be
! 	     NULL.  (For functions in shared objects for
! 	     which we have created stubs, ST_VALUE will be non-NULL.
! 	     That's because such the functions are now no longer defined
! 	     in a shared object.)  */
! 
! 	  if ((info->shared && h->root.type == bfd_link_hash_undefined)
! 	      || h->root.type == bfd_link_hash_undefweak)
! 	    value = 0;
! 	  else
! 	    value = h->root.u.def.value;
! 	}
        offset = mips_elf_global_got_index (dynobj, output_bfd, h);
        MIPS_ELF_PUT_WORD (output_bfd, value, sgot->contents + offset);
      }
--- 6777,6783 ----
        bfd_vma offset;
        bfd_vma value;
  
!       value = sym->st_value;
        offset = mips_elf_global_got_index (dynobj, output_bfd, h);
        MIPS_ELF_PUT_WORD (output_bfd, value, sgot->contents + offset);
      }
	* elfxx-mips.c (_bfd_mips_elf_create_dynamic_sections): Disable
	the creation of .msym.

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 09:14:17 -0000
@@ -4913,7 +4913,7 @@ _bfd_mips_elf_create_dynamic_sections (a
   /* Create the .msym section on IRIX6.  It is used by the dynamic
      linker to speed up dynamic relocations, and to avoid computing
      the ELF hash for symbols.  */
-  if (IRIX_COMPAT (abfd) == ict_irix6
+  if (IRIX_COMPAT (abfd) == ict_irix6 && 0
       && !mips_elf_create_msym_section (abfd))
     return FALSE;
 
	* elfxx-mips.c (mips_elf_link_hash_entry): Remove min_dyn_reloc_index.
	(mips_elf_link_hash_newfunc): Don't set it.
	(mips_elf_create_dynamic_relocation): Likewise.
	(_bfd_mips_elf_copy_indirect_symbol): Likewise.
	(bfd_mips_elf_swap_msym_in): Reenable.
	(mips_elf_adjust_msym_indices): New function.
	(_bfd_mips_elf_finish_dynamic_symbol): Just use a 0 symbol index.
	(_bfd_mips_elf_finish_dynamic_sections): After sorting .rel.dyn,
	go through .msym and set up the ms_info fields appropriately.

Index: bfd/elfxx-mips.c
===================================================================
RCS file: /cvs/src/src/bfd/elfxx-mips.c,v
retrieving revision 1.51.4.3
diff -c -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 07:27:59 -0000
*************** struct mips_elf_link_hash_entry
*** 189,198 ****
       a readonly section.  */
    bfd_boolean readonly_reloc;
  
-   /* The index of the first dynamic relocation (in the .rel.dyn
-      section) against this symbol.  */
-   unsigned int min_dyn_reloc_index;
- 
    /* We must not create a stub for a symbol that has relocations
       related to taking the function's address, i.e. any but
       R_MIPS_CALL*16 ones -- see "MIPS ABI Supplement, 3rd Edition",
--- 189,194 ----
*************** static void bfd_elf32_swap_compact_rel_o
*** 391,400 ****
    PARAMS ((bfd *, const Elf32_compact_rel *, Elf32_External_compact_rel *));
  static void bfd_elf32_swap_crinfo_out
    PARAMS ((bfd *, const Elf32_crinfo *, Elf32_External_crinfo *));
- #if 0
  static void bfd_mips_elf_swap_msym_in
    PARAMS ((bfd *, const Elf32_External_Msym *, Elf32_Internal_Msym *));
- #endif
  static void bfd_mips_elf_swap_msym_out
    PARAMS ((bfd *, const Elf32_Internal_Msym *, Elf32_External_Msym *));
  static int sort_dynamic_relocs
--- 387,394 ----
*************** static bfd_boolean mips_elf_create_got_s
*** 446,451 ****
--- 440,447 ----
    PARAMS ((bfd *, struct bfd_link_info *, bfd_boolean));
  static asection *mips_elf_create_msym_section
    PARAMS ((bfd *));
+ static void mips_elf_adjust_msym_indices
+   PARAMS ((bfd *, asection *, asection *));
  static bfd_reloc_status_type mips_elf_calculate_relocation
    PARAMS ((bfd *, bfd *, asection *, struct bfd_link_info *,
  	   const Elf_Internal_Rela *, bfd_vma, reloc_howto_type *,
*************** mips_elf_link_hash_newfunc (entry, table
*** 732,738 ****
        ret->esym.ifd = -2;
        ret->possibly_dynamic_relocs = 0;
        ret->readonly_reloc = FALSE;
-       ret->min_dyn_reloc_index = 0;
        ret->no_fn_stub = FALSE;
        ret->fn_stub = NULL;
        ret->need_fn_stub = FALSE;
--- 728,733 ----
*************** bfd_elf32_swap_crinfo_out (abfd, in, ex)
*** 1194,1200 ****
    H_PUT_32 (abfd, in->vaddr, ex->vaddr);
  }
  
- #if 0
  /* Swap in an MSYM entry.  */
  
  static void
--- 1189,1194 ----
*************** bfd_mips_elf_swap_msym_in (abfd, ex, in)
*** 1206,1212 ****
    in->ms_hash_value = H_GET_32 (abfd, ex->ms_hash_value);
    in->ms_info = H_GET_32 (abfd, ex->ms_info);
  }
! #endif
  /* Swap out an MSYM entry.  */
  
  static void
--- 1200,1206 ----
    in->ms_hash_value = H_GET_32 (abfd, ex->ms_hash_value);
    in->ms_info = H_GET_32 (abfd, ex->ms_info);
  }
! 
  /* Swap out an MSYM entry.  */
  
  static void
*************** mips_elf_create_msym_section (abfd)
*** 2944,2949 ****
--- 2938,2981 ----
  
    return s;
  }
+ 
+ /* Adjust the contents of .msym after sorting the dynamic relocations.
+    RELDYN and MSYM are the two sections involved.  */
+ 
+ static void
+ mips_elf_adjust_msym_indices (abfd, reldyn, msym)
+      bfd *abfd;
+      asection *reldyn, *msym;
+ {
+   size_t i, entsize, lastsym;
+ 
+   entsize = MIPS_ELF_REL_SIZE (abfd);
+   lastsym = (size_t) -1;
+ 
+   for (i = entsize; i < reldyn->_raw_size; i += entsize)
+     {
+       size_t sym;
+       Elf_Internal_Rela reloc[3];
+ 
+       (*get_elf_backend_data (abfd)->s->swap_reloc_in)
+ 	(abfd, reldyn->contents + i, reloc);
+       sym = ELF_R_SYM (abfd, reloc[0].r_info);
+       if (sym != lastsym)
+ 	{
+ 	  /* This is the first .rel.dyn entry for this symbol.
+ 	     Get the symbol's .msym record and adjust the ms_info
+ 	     field appropriately.  */
+ 	  Elf32_Internal_Msym entry;
+ 
+ 	  bfd_mips_elf_swap_msym_in
+ 	    (abfd, (Elf32_External_Msym *) msym->contents + sym, &entry);
+ 	  entry.ms_info = ELF32_MS_INFO (i / entsize, 1);
+ 	  bfd_mips_elf_swap_msym_out
+ 	    (abfd, &entry, (Elf32_External_Msym *) msym->contents + sym);
+ 	  lastsym = sym;
+ 	}
+     }
+ }
  
  /* Calculate the value produced by the RELOCATION (which comes from
     the INPUT_BFD).  The ADDEND is the addend to use for this
*************** mips_elf_create_dynamic_relocation (outp
*** 3984,3996 ****
        (output_bfd, &outrel[0],
         (sreloc->contents + sreloc->reloc_count * sizeof (Elf32_External_Rel)));
  
-   /* Record the index of the first relocation referencing H.  This
-      information is later emitted in the .msym section.  */
-   if (h != NULL
-       && (h->min_dyn_reloc_index == 0
- 	  || sreloc->reloc_count < h->min_dyn_reloc_index))
-     h->min_dyn_reloc_index = sreloc->reloc_count;
- 
    /* We've now added another relocation.  */
    ++sreloc->reloc_count;
  
--- 4021,4026 ----
*************** _bfd_mips_elf_finish_dynamic_symbol (out
*** 6689,6699 ****
    asection *smsym;
    struct mips_got_info *g, *gg;
    const char *name;
-   struct mips_elf_link_hash_entry *mh;
  
    dynobj = elf_hash_table (info)->dynobj;
    gval = sym->st_value;
-   mh = (struct mips_elf_link_hash_entry *) h;
  
    if (h->plt.offset != (bfd_vma) -1)
      {
--- 6719,6727 ----
*************** _bfd_mips_elf_finish_dynamic_symbol (out
*** 6831,6837 ****
        msym.ms_hash_value = bfd_elf_hash (h->root.root.string);
        /* It is undocumented what the `1' indicates, but IRIX6 uses
  	 this value.  */
!       msym.ms_info = ELF32_MS_INFO (mh->min_dyn_reloc_index, 1);
        bfd_mips_elf_swap_msym_out
  	(dynobj, &msym,
  	 ((Elf32_External_Msym *) smsym->contents) + h->dynindx);
--- 6837,6843 ----
        msym.ms_hash_value = bfd_elf_hash (h->root.root.string);
        /* It is undocumented what the `1' indicates, but IRIX6 uses
  	 this value.  */
!       msym.ms_info = ELF32_MS_INFO (0, 1);
        bfd_mips_elf_swap_msym_out
  	(dynobj, &msym,
  	 ((Elf32_External_Msym *) smsym->contents) + h->dynindx);
*************** _bfd_mips_elf_finish_dynamic_sections (o
*** 7236,7242 ****
  		 (size_t) s->reloc_count - 1,
  		 sizeof (Elf32_External_Rel), sort_dynamic_relocs);
        }
!   }
  
    return TRUE;
  }
--- 7242,7251 ----
  		 (size_t) s->reloc_count - 1,
  		 sizeof (Elf32_External_Rel), sort_dynamic_relocs);
        }
! 
!     if (s != 0 && smsym != 0)
!       mips_elf_adjust_msym_indices (output_bfd, s, smsym);
!   }		
  
    return TRUE;
  }
*************** _bfd_mips_elf_copy_indirect_symbol (bed,
*** 7778,7787 ****
    dirmips->possibly_dynamic_relocs += indmips->possibly_dynamic_relocs;
    if (indmips->readonly_reloc)
      dirmips->readonly_reloc = TRUE;
-   if (dirmips->min_dyn_reloc_index == 0
-       || (indmips->min_dyn_reloc_index != 0
- 	  && indmips->min_dyn_reloc_index < dirmips->min_dyn_reloc_index))
-     dirmips->min_dyn_reloc_index = indmips->min_dyn_reloc_index;
    if (indmips->no_fn_stub)
      dirmips->no_fn_stub = TRUE;
  }
--- 7787,7792 ----

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