Linking n64 code for irix (part 2/2)

Richard Sandiford rsandifo@redhat.com
Mon Oct 13 19:22:00 GMT 2003


This is the second patch to get GNU ld working for n64 on irix.
Problems/fixes:

  1. As I mentioned a while back, there are some problems with symbol
     preemption on irix.  For example:

cat <<EOF >x.c
int f1 () { return 100; }
int f2 () { return f1 (); }
EOF
cat <<EOF >y.c
int f1 () { return 200; }
int main () { printf ("%d\n", f2 ()); }
EOF
cc -c x.c
$LD x.o -o x.so -shared
cc -c y.c
$LD /usr/lib32/crt1.o y.o x.so /usr/lib32/libc.so /usr/lib32/crtn.o -o y
LD_LIBRARYN32_PATH=`pwd` ./y

     will print 100 rather than 200 with LD==GNU ld.  It's x.so that's
     the problem: swap in a MIPSpro version of it and "y" will work fine.

     This was caused by some half-hearted quickstart info, a bit like
     the earlier .msym problems.  In this case we were emitting .dynamic
     entries for DT_MIPS_CONFLICTNO and DT_MIPS_LIBLISTNO even though we
     made no attempt to create .conflict or .liblist.

     The fix is simply to remove the skeleton DT_MIPS_CONFLICT* and
     DT_MIPS_LIBLIST* code.  I don't think there's any point having
     it as things stand.

     I've also removed some lingering msym stuff that oughtn't to be needed.

  2. MIPSpro still generates ucode info for n64 objects.  It should
     be safe to ignore this.

     At the moment, linking a ucode object with non-ucode objects
     gives errors like:

	./ld/ld-new: y.o: uses different e_flags (0x10) fields than previous modules (0x0)
	Bad value: failed to merge target specific data of file y.o

  3. The code to place the PT_MIPS_OPTIONS header wasn't working.
     Contrary to the comment, it would place the header _before_ PT_PHDR
     in an executable.  Also (as per comment) it would place it at the
     end for a DSO.  The latter causes rld to warn about the header
     being missing.

     For example, taking the n64 version of the test case above:

cat <<EOF >x.c
int f1 () { return 100; }
int f2 () { return f1 (); }
EOF
cat <<EOF >y.c
int f1 () { return 200; }
int main () { printf ("%d\n", f2 ()); }
EOF
cc -c x.c -64
$LD x.o -o x.so -shared -melf64bmip
cc -c y.c -64
$LD /usr/lib64/crt1.o y.o x.so /usr/lib64/libc.so /usr/lib64/crtn.o \
  -o y -melf64bmip
LD_LIBRARY64_PATH=`pwd` ./y

     rld warns:

	./y: rld: Warning: Object /es/scratch/rsandifo/sources/mips-sgi-irix6.5/x.so has a DT_MIPS_OPTIONS tag, but no corresponding
	program header.  This could be the result of file corruption

     The patch places PT_MIPS_OPTIONS after PT_PHDR and PT_INTERP, just like
     we do for PT_MIPS_REGINFO.  This is also what the native linker does.

  4. If we allocate more relocations in .rel.dyn than we actually need,
     DT_REL/DT_RELSZ will describe a region with trailing null relocs.
     This seems to cause rld to ignore _every_ relocation.

     To be honest, I'm not really sure why.  Perhaps it reads the
     relocations last-to-first and assumes that the first null reloc it
     comes across is the one at the beginning of the section.  Anyway...

     The fix is to recalculate DT_RELSZ based on the number of
     relocations we actually needed, not the number we allocated.
     I hope this is OK.

Tested with the last patch.  OK to install?

Richard


bfd/
	* elfxx-mips.c (_bfd_mips_elf_size_dynamic_sections): Don't add
	DT_MIPS_LIBLIST or DT_MIPS_CONFLICT entries.
	(_bfd_mips_elf_finish_dynamic_symbol): Don't handle them.  Don't
	handle DT_MIPS_MSYM.  Set DT_RELSZ based on the number of relocations
	that were needed.
	(_bfd_mips_elf_modify_segment_map): Fix placement of PT_MIPS_OPTIONS.
	(_bfd_mips_elf_merge_private_bfd_data): Ignore EF_MIPS_UCODE.

ld/testsuite/
	* ld-mips-elf/multi-got-1.d (RELSZ): Don't include the size of the
	trailing null relocs.

Index: bfd/elfxx-mips.c
===================================================================
RCS file: /cvs/src/src/bfd/elfxx-mips.c,v
retrieving revision 1.76
diff -c -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.76 elfxx-mips.c
*** bfd/elfxx-mips.c	30 Sep 2003 16:17:11 -0000	1.76
--- bfd/elfxx-mips.c	13 Oct 2003 19:00:37 -0000
*************** _bfd_mips_elf_size_dynamic_sections (out
*** 6085,6114 ****
  	    return FALSE;
  	}
  
-       if (SGI_COMPAT (output_bfd))
- 	{
- 	  if (!MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_CONFLICTNO, 0))
- 	    return FALSE;
- 	}
- 
-       if (SGI_COMPAT (output_bfd))
- 	{
- 	  if (!MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_LIBLISTNO, 0))
- 	    return FALSE;
- 	}
- 
-       if (bfd_get_section_by_name (dynobj, ".conflict") != NULL)
- 	{
- 	  if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_CONFLICT, 0))
- 	    return FALSE;
- 
- 	  s = bfd_get_section_by_name (dynobj, ".liblist");
- 	  BFD_ASSERT (s != NULL);
- 
- 	  if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_LIBLIST, 0))
- 	    return FALSE;
- 	}
- 
        if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_RLD_VERSION, 0))
  	return FALSE;
  
--- 6085,6090 ----
*************** _bfd_mips_elf_finish_dynamic_sections (o
*** 6878,6890 ****
  
  	    case DT_PLTGOT:
  	      name = ".got";
- 	      goto get_vma;
- 	    case DT_MIPS_CONFLICT:
- 	      name = ".conflict";
- 	      goto get_vma;
- 	    case DT_MIPS_LIBLIST:
- 	      name = ".liblist";
- 	    get_vma:
  	      s = bfd_get_section_by_name (output_bfd, name);
  	      BFD_ASSERT (s != NULL);
  	      dyn.d_un.d_ptr = s->vma;
--- 6854,6859 ----
*************** _bfd_mips_elf_finish_dynamic_sections (o
*** 6898,6924 ****
  	      dyn.d_un.d_val = RHF_NOTPOT; /* XXX */
  	      break;
  
- 	    case DT_MIPS_CONFLICTNO:
- 	      name = ".conflict";
- 	      elemsize = sizeof (Elf32_Conflict);
- 	      goto set_elemno;
- 
- 	    case DT_MIPS_LIBLISTNO:
- 	      name = ".liblist";
- 	      elemsize = sizeof (Elf32_Lib);
- 	    set_elemno:
- 	      s = bfd_get_section_by_name (output_bfd, name);
- 	      if (s != NULL)
- 		{
- 		  if (s->_cooked_size != 0)
- 		    dyn.d_un.d_val = s->_cooked_size / elemsize;
- 		  else
- 		    dyn.d_un.d_val = s->_raw_size / elemsize;
- 		}
- 	      else
- 		dyn.d_un.d_val = 0;
- 	      break;
- 
  	    case DT_MIPS_TIME_STAMP:
  	      time ((time_t *) &dyn.d_un.d_val);
  	      break;
--- 6867,6872 ----
*************** _bfd_mips_elf_finish_dynamic_sections (o
*** 6986,6994 ****
  	      dyn.d_un.d_ptr = s->vma;
  	      break;
  
! 	    case DT_MIPS_MSYM:
! 	      s = (bfd_get_section_by_name (output_bfd, ".msym"));
! 	      dyn.d_un.d_ptr = s->vma;
  	      break;
  
  	    default:
--- 6934,6949 ----
  	      dyn.d_un.d_ptr = s->vma;
  	      break;
  
! 	    case DT_RELSZ:
! 	      /* Reduce DT_RELSZ to account for any relocations we
! 		 decided not to make.  This is for the n64 irix rld,
! 		 which doesn't seem to apply any relocations if there
! 		 are trailing null entries.  */
! 	      s = mips_elf_rel_dyn_section (dynobj, FALSE);
! 	      dyn.d_un.d_val = (s->reloc_count
! 				* (ABI_64_P (output_bfd)
! 				   ? sizeof (Elf64_Mips_External_Rel)
! 				   : sizeof (Elf32_External_Rel)));
  	      break;
  
  	    default:
*************** _bfd_mips_elf_modify_segment_map (abfd)
*** 7369,7375 ****
  
    /* For IRIX 6, we don't have .mdebug sections, nor does anything but
       .dynamic end up in PT_DYNAMIC.  However, we do have to insert a
!      PT_OPTIONS segment immediately following the program header
       table.  */
    if (NEWABI_P (abfd)
        /* On non-IRIX6 new abi, we'll have already created a segment
--- 7324,7330 ----
  
    /* For IRIX 6, we don't have .mdebug sections, nor does anything but
       .dynamic end up in PT_DYNAMIC.  However, we do have to insert a
!      PT_MIPS_OPTIONS segment immediately following the program header
       table.  */
    if (NEWABI_P (abfd)
        /* On non-IRIX6 new abi, we'll have already created a segment
*************** _bfd_mips_elf_modify_segment_map (abfd)
*** 7386,7400 ****
  	{
  	  struct elf_segment_map *options_segment;
  
! 	  /* Usually, there's a program header table.  But, sometimes
! 	     there's not (like when running the `ld' testsuite).  So,
! 	     if there's no program header table, we just put the
! 	     options segment at the end.  */
! 	  for (pm = &elf_tdata (abfd)->segment_map;
! 	       *pm != NULL;
! 	       pm = &(*pm)->next)
! 	    if ((*pm)->p_type == PT_PHDR)
! 	      break;
  
  	  amt = sizeof (struct elf_segment_map);
  	  options_segment = bfd_zalloc (abfd, amt);
--- 7341,7351 ----
  	{
  	  struct elf_segment_map *options_segment;
  
! 	  pm = &elf_tdata (abfd)->segment_map;
! 	  while (*pm != NULL
! 		 && ((*pm)->p_type == PT_PHDR
! 		     || (*pm)->p_type == PT_INTERP))
! 	    pm = &(*pm)->next;
  
  	  amt = sizeof (struct elf_segment_map);
  	  options_segment = bfd_zalloc (abfd, amt);
*************** _bfd_mips_elf_merge_private_bfd_data (ib
*** 9084,9089 ****
--- 9035,9045 ----
       doesn't seem to matter.  */
    new_flags &= ~EF_MIPS_XGOT;
    old_flags &= ~EF_MIPS_XGOT;
+ 
+   /* MIPSpro generates ucode info in n64 objects.  Again, we should
+      just be able to ignore this.  */
+   new_flags &= ~EF_MIPS_UCODE;
+   old_flags &= ~EF_MIPS_UCODE;
  
    if (new_flags == old_flags)
      return TRUE;
Index: ld/testsuite/ld-mips-elf/multi-got-1.d
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-mips-elf/multi-got-1.d,v
retrieving revision 1.3
diff -c -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.3 multi-got-1.d
*** ld/testsuite/ld-mips-elf/multi-got-1.d	11 Jun 2003 21:01:48 -0000	1.3
--- ld/testsuite/ld-mips-elf/multi-got-1.d	13 Oct 2003 19:00:40 -0000
*************** Dynamic segment at offset 0xcc contains 
*** 15,21 ****
   0x00000015 \(DEBUG\)                      0x0
   0x00000003 \(PLTGOT\)                     0xe3ba0
   0x00000011 \(REL\)                        0x83b34
!  0x00000012 \(RELSZ\)                      65624 \(bytes\)
   0x00000013 \(RELENT\)                     8 \(bytes\)
   0x70000001 \(MIPS_RLD_VERSION\)           1
   0x70000005 \(MIPS_FLAGS\)                 NOTPOT
--- 15,21 ----
   0x00000015 \(DEBUG\)                      0x0
   0x00000003 \(PLTGOT\)                     0xe3ba0
   0x00000011 \(REL\)                        0x83b34
!  0x00000012 \(RELSZ\)                      65544 \(bytes\)
   0x00000013 \(RELENT\)                     8 \(bytes\)
   0x70000001 \(MIPS_RLD_VERSION\)           1
   0x70000005 \(MIPS_FLAGS\)                 NOTPOT



More information about the Binutils mailing list