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]

PATCH: Fix MIPS DT_MIPS_UNREFEXTNO


DT_MIPS_UNREFEXTNO should hold an index into the dynamic symbol
table. The index is the entry of the first external symbol that is not
referenced within the object. We just put output section count there.
I don't think it is right. Also we may leave a gap between the GOT and
non-GOT symbols. This patch tries to fix them.


H.J.
----
bfd/

2005-03-16  H.J. Lu  <hongjiu.lu@intel.com>

	* elfxx-mips.c (mips_got_info): Add first_unref_global_dynindx.
	(mips_elf_hash_sort_data): Add min_non_got_dynindx.
	(mips_elf_sort_hash_table_1): New.
	(mips_elf_sort_hash_table): Call mips_elf_sort_hash_table_1 to
	make sure there is no gap between the GOT and non-GOT symbols. 
	Set first_unref_global_dynindx from min_non_got_dynindx.
	(mips_elf_sort_hash_table_f): Set min_non_got_dynindx.
	(_bfd_mips_elf_finish_dynamic_sections): Set DT_MIPS_UNREFEXTNO
	with first_unref_global_dynindx.
	(_bfd_mips_elf_final_link): Don't count sections. Pass 1 to
	mips_elf_sort_hash_table.

ld/testsuite/

2005-03-16  H.J. Lu  <hongjiu.lu@intel.com>

	* ld-mips-elf/multi-got-1.d: Update MIPS_UNREFEXTNO.
	* ld-mips-elf/tls-multi-got-1.r: Likewise.

--- binutils/bfd/elfxx-mips.c.unref	2005-03-16 11:44:25.000000000 -0800
+++ binutils/bfd/elfxx-mips.c	2005-03-16 13:12:11.441612984 -0800
@@ -85,6 +85,10 @@ struct mips_got_info
   /* The global symbol in the GOT with the lowest index in the dynamic
      symbol table.  */
   struct elf_link_hash_entry *global_gotsym;
+  /* The index into the dynamic symbol table which is the entry of the
+     first external symbol that is not referenced within the same
+     object.  */
+  long first_unref_global_dynindx;
   /* The number of global .got entries.  */
   unsigned int global_gotno;
   /* The number of .got slots used for TLS.  */
@@ -200,6 +204,9 @@ struct mips_elf_hash_sort_data
   /* The greatest dynamic symbol table index not corresponding to a
      symbol without a GOT entry.  */
   long max_non_got_dynindx;
+  /* The least dynamic symbol table index not corresponding to a
+     symbol without a GOT entry.  */
+  long min_non_got_dynindx;
 };
 
 /* The MIPS ELF linker needs additional information for each symbol in
@@ -2523,20 +2530,15 @@ mips_elf_create_local_got_entry (bfd *ab
    _bfd_mips_elf_size_dynamic_sections, this value is 1.  Afterward, the
    section symbols are added and the count is higher.  */
 
-static bfd_boolean
-mips_elf_sort_hash_table (struct bfd_link_info *info, unsigned long max_local)
-{
-  struct mips_elf_hash_sort_data hsd;
-  struct mips_got_info *g;
-  bfd *dynobj;
-
-  dynobj = elf_hash_table (info)->dynobj;
-
-  g = mips_elf_got_info (dynobj, NULL);
-
-  hsd.low = NULL;
-  hsd.max_unref_got_dynindx =
-  hsd.min_got_dynindx = elf_hash_table (info)->dynsymcount
+static void
+mips_elf_sort_hash_table_1 (struct bfd_link_info *info,
+			    unsigned long max_local,
+			    struct mips_got_info *g,
+			    struct mips_elf_hash_sort_data *hsd)
+{
+  hsd->low = NULL;
+  hsd->max_unref_got_dynindx =
+  hsd->min_got_dynindx = elf_hash_table (info)->dynsymcount
     /* In the multi-got case, assigned_gotno of the master got_info
        indicate the number of entries that aren't referenced in the
        primary GOT, but that must have entries because there are
@@ -2545,15 +2547,38 @@ mips_elf_sort_hash_table (struct bfd_lin
        don't prevent other entries that are referenced from getting
        too large offsets.  */
     - (g->next ? g->assigned_gotno : 0);
-  hsd.max_non_got_dynindx = max_local;
+  hsd->min_non_got_dynindx = 0;
+  hsd->max_non_got_dynindx = max_local;
   mips_elf_link_hash_traverse (((struct mips_elf_link_hash_table *)
 				elf_hash_table (info)),
 			       mips_elf_sort_hash_table_f,
-			       &hsd);
+			       hsd);
+}
+
+static bfd_boolean
+mips_elf_sort_hash_table (struct bfd_link_info *info,
+			  unsigned long max_local)
+{
+  struct mips_elf_hash_sort_data hsd;
+  struct mips_got_info *g;
+  bfd *dynobj;
+
+  dynobj = elf_hash_table (info)->dynobj;
+
+  g = mips_elf_got_info (dynobj, NULL);
+
+  mips_elf_sort_hash_table_1 (info, max_local, g, &hsd);
+
+  /* There should be no gap between the GOT and non-GOT symbols.  */
+  if (hsd.max_non_got_dynindx < hsd.min_got_dynindx)
+    mips_elf_sort_hash_table_1 (info, (max_local
+				       + hsd.min_got_dynindx
+				       - hsd.max_non_got_dynindx),
+				g, &hsd);
 
   /* There should have been enough room in the symbol table to
      accommodate both the GOT and non-GOT symbols.  */
-  BFD_ASSERT (hsd.max_non_got_dynindx <= hsd.min_got_dynindx);
+  BFD_ASSERT (hsd.max_non_got_dynindx == hsd.min_got_dynindx);
   BFD_ASSERT ((unsigned long)hsd.max_unref_got_dynindx
 	      <= elf_hash_table (info)->dynsymcount);
 
@@ -2561,6 +2586,8 @@ mips_elf_sort_hash_table (struct bfd_lin
      table index in the GOT.  */
   g->global_gotsym = hsd.low;
 
+  g->first_unref_global_dynindx = hsd.min_non_got_dynindx;
+
   return TRUE;
 }
 
@@ -2594,7 +2621,12 @@ mips_elf_sort_hash_table_f (struct mips_
       h->root.dynindx = hsd->max_unref_got_dynindx++;
     }
   else if (h->root.got.offset != 1)
-    h->root.dynindx = hsd->max_non_got_dynindx++;
+    {
+      /* Record it for DT_MIPS_UNREFEXTNO.  */
+      if (hsd->min_non_got_dynindx == 0)
+	hsd->min_non_got_dynindx = hsd->max_non_got_dynindx;
+      h->root.dynindx = hsd->max_non_got_dynindx++;
+    }
   else
     {
       BFD_ASSERT (h->tls_type == GOT_NORMAL);
@@ -7632,7 +7664,7 @@ _bfd_mips_elf_finish_dynamic_sections (b
 	      /* The index into the dynamic symbol table which is the
 		 entry of the first external symbol that is not
 		 referenced within the same object.  */
-	      dyn.d_un.d_val = bfd_count_sections (output_bfd) + 1;
+	      dyn.d_un.d_val = gg->first_unref_global_dynindx;
 	      break;
 
 	    case DT_MIPS_GOTSYM:
@@ -8907,6 +8939,7 @@ _bfd_mips_elf_final_link (bfd *abfd, str
       bfd *dynobj;
       asection *got;
       struct mips_got_info *g;
+#if 0
       bfd_size_type dynsecsymcount;
 
       /* When we resort, we must tell mips_elf_sort_hash_table what
@@ -8927,8 +8960,9 @@ _bfd_mips_elf_final_link (bfd *abfd, str
 		&& !(*bed->elf_backend_omit_section_dynsym) (abfd, info, p))
 	      ++ dynsecsymcount;
 	}
+#endif
       
-      if (! mips_elf_sort_hash_table (info, dynsecsymcount + 1))
+      if (! mips_elf_sort_hash_table (info, 1))
 	return FALSE;
 
       /* Make sure we didn't grow the global .got region.  */
--- binutils/ld/testsuite/ld-mips-elf/multi-got-1.d.unref	2005-02-11 09:28:26.000000000 -0800
+++ binutils/ld/testsuite/ld-mips-elf/multi-got-1.d	2005-03-16 13:00:03.000000000 -0800
@@ -22,7 +22,7 @@ Dynamic section at offset 0xcc contains 
  0x70000006 \(MIPS_BASE_ADDRESS\)          0
  0x7000000a \(MIPS_LOCAL_GOTNO\)           12
  0x70000011 \(MIPS_SYMTABNO\)              16399
- 0x70000012 \(MIPS_UNREFEXTNO\)            14
+ 0x70000012 \(MIPS_UNREFEXTNO\)            6
  0x70000013 \(MIPS_GOTSYM\)                0xf
  0x00000000 \(NULL\)                       0x0
 
--- binutils/ld/testsuite/ld-mips-elf/tls-multi-got-1.r.unref	2005-03-02 13:22:57.000000000 -0800
+++ binutils/ld/testsuite/ld-mips-elf/tls-multi-got-1.r	2005-03-16 13:02:58.000000000 -0800
@@ -16,7 +16,7 @@ Dynamic section at offset 0xec contains 
  0x70000006 \(MIPS_BASE_ADDRESS\)          0
  0x7000000a \(MIPS_LOCAL_GOTNO\)           13
  0x70000011 \(MIPS_SYMTABNO\)              20018
- 0x70000012 \(MIPS_UNREFEXTNO\)            15
+ 0x70000012 \(MIPS_UNREFEXTNO\)            7
  0x70000013 \(MIPS_GOTSYM\)                0x12
  0x0000001e \(FLAGS\)                      STATIC_TLS
  0x00000000 \(NULL\)                       0x0


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