This is the mail archive of the binutils@sourceware.org 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]

[15/21] Avoid writing duplicate XCOFF symbols


If two bfds refer to the same imported symbol, we'll copy both
XTY_ER symbols to the output file.  This shows up as duplicate
"U" entries the nm output.

Also, if two bfds define the same non-common symbol, we'll currently
add an output symbol for both of them.  This might matter more
for XCOFF than other targets because there are cases where we
deliberately accept duplicates (see xcoff_link_add_symbols).
Then again, it might not.  The main reason for fixing the
problem is that it paves the way for AIX C_WEAKEXT support.

As I mentioned when describing an earlier patch, the relocation
marking code currently marks the target symbol's hash entry
_and_ its csect.  This too is wrong for multiple definitions;
the chosen definition might not be provided by the current input_bfd.
As above, this is more of an issue for weak support, which is added
in a later patch.

OK to install?

Richard


include/coff/
	* xcoff.h (XCOFF_ALLOCATED): New flag.

bfd/
	* xcofflink.c (xcoff_mark): When walking the relocations,
	only mark the target symbol or the target section, not both.
	(xcoff_final_definition_p): New function.
	(xcoff_keep_symbol_p): Use it to check whether an external XCOFF
	symbol is a valid definition of the associated output symbol.
	Use XCOFF_ALLOCATED to stop the same hash table entry having
	two output symbols.
	(bfd_xcoff_size_dynamic_sections): Set XCOFF_ALLOCATED when
	keeping a symbol.
	(xcoff_link_input_bfd): Use xcoff_final_definition_p.

ld/testsuite/
	* ld-powerpc/aix-no-dup-syms-1a.s, ld-powerpc/aix-no-dup-syms-1b.s,
	ld-powerpc/aix-no-dup-syms-1.ex, ld-powerpc/aix-no-dup-syms-1.im,
	ld-powerpc/aix-no-dup-syms-1-dso.dnd,
	ld-powerpc/aix-no-dup-syms-1-dso.drd,
	ld-powerpc/aix-no-dup-syms-1-dso.nd,
	ld-powerpc/aix-no-dup-syms-1-dso.rd,
	ld-powerpc/aix-no-dup-syms-1-rel.nd,
	ld-powerpc/aix-no-dup-syms-1-rel.rd: New tests.
	* ld-powerpc/aix52.exp: Run them.

Index: include/coff/xcoff.h
===================================================================
--- include/coff/xcoff.h	2009-03-10 13:46:23.000000000 +0000
+++ include/coff/xcoff.h	2009-03-10 13:49:33.000000000 +0000
@@ -318,6 +318,8 @@ #define XCOFF_SYSCALL32        0x0000800
 #define XCOFF_SYSCALL64        0x00010000 
 /* Symbol was not explicitly defined by the time it was marked.  */
 #define XCOFF_WAS_UNDEFINED    0x00020000
+/* We have assigned an output XCOFF entry to this symbol.  */
+#define XCOFF_ALLOCATED	       0x00040000
 
 /* The XCOFF linker hash table.  */
 
Index: bfd/xcofflink.c
===================================================================
--- bfd/xcofflink.c	2009-03-10 13:48:48.000000000 +0000
+++ bfd/xcofflink.c	2009-03-10 13:49:33.000000000 +0000
@@ -2504,7 +2504,6 @@ xcoff_mark (struct bfd_link_info *info, 
 	  relend = rel + sec->reloc_count;
 	  for (; rel < relend; rel++)
 	    {
-	      asection *rsec;
 	      struct xcoff_link_hash_entry *h;
 
 	      if ((unsigned int) rel->r_symndx
@@ -2512,21 +2511,25 @@ xcoff_mark (struct bfd_link_info *info, 
 		continue;
 
 	      h = obj_xcoff_sym_hashes (sec->owner)[rel->r_symndx];
-	      if (h != NULL
-		  && (h->flags & XCOFF_MARK) == 0)
+	      if (h != NULL)
 		{
-		  if (! xcoff_mark_symbol (info, h))
-		    return FALSE;
+		  if ((h->flags & XCOFF_MARK) == 0)
+		    {
+		      if (!xcoff_mark_symbol (info, h))
+			return FALSE;
+		    }
 		}
-
-	      rsec = xcoff_data (sec->owner)->csects[rel->r_symndx];
-	      if (rsec != NULL
-		  && !bfd_is_und_section (rsec)
-		  && !bfd_is_abs_section (rsec)
-		  && (rsec->flags & SEC_MARK) == 0)
+	      else
 		{
-		  if (! xcoff_mark (info, rsec))
-		    return FALSE;
+		  asection *rsec;
+
+		  rsec = xcoff_data (sec->owner)->csects[rel->r_symndx];
+		  if (rsec != NULL
+		      && (rsec->flags & SEC_MARK) == 0)
+		    {
+		      if (!xcoff_mark (info, rsec))
+			return FALSE;
+		    }
 		}
 
 	      /* See if this reloc needs to be copied into the .loader
@@ -2826,6 +2829,36 @@ bfd_xcoff_record_link_assignment (bfd *o
 
 /* Add a symbol to the .loader symbols, if necessary.  */
 
+/* INPUT_BFD has an external symbol associated with hash table entry H
+   and csect CSECT.   Return true if INPUT_BFD defines H.  */
+
+static bfd_boolean
+xcoff_final_definition_p (bfd *input_bfd, struct xcoff_link_hash_entry *h,
+			  asection *csect)
+{
+  switch (h->root.type)
+    {
+    case bfd_link_hash_defined:
+    case bfd_link_hash_defweak:
+      /* No input bfd owns absolute symbols.  They are written by
+	 xcoff_write_global_symbol instead.  */
+      return (!bfd_is_abs_section (csect)
+	      && h->root.u.def.section == csect);
+
+    case bfd_link_hash_common:
+      return h->root.u.c.p->section->owner == input_bfd;
+
+    case bfd_link_hash_undefined:
+    case bfd_link_hash_undefweak:
+      /* We can't treat undef.abfd as the owner because that bfd
+	 might be a dynamic object.  Allow any bfd to claim it.  */
+      return TRUE;
+
+    default:
+      abort ();
+    }
+}
+
 static bfd_boolean
 xcoff_build_ldsyms (struct xcoff_link_hash_entry *h, void * p)
 {
@@ -3036,23 +3069,17 @@ xcoff_keep_symbol_p (struct bfd_link_inf
   if (info->strip == strip_all)
     return 0;
 
-  /* We can ignore external references that were resolved by the link.  */
-  smtyp = SMTYP_SMTYP (aux->x_csect.x_smtyp);
-  if (isym->n_sclass == C_EXT
-      && smtyp == XTY_ER
-      && h->root.type != bfd_link_hash_undefined)
-    return 0;
-
-  /* We can ignore common symbols if they got defined somewhere else.  */
-  if (isym->n_sclass == C_EXT
-      && smtyp == XTY_CM
-      && (h->root.type != bfd_link_hash_common
-	  || h->root.u.c.p->section != csect)
-      && (h->root.type != bfd_link_hash_defined
-	  || h->root.u.def.section != csect))
-    return 0;
+  /* Discard symbols that are defined elsewhere.  */
+  if (isym->n_sclass == C_EXT)
+    {
+      if ((h->flags & XCOFF_ALLOCATED) != 0)
+	return 0;
+      if (!xcoff_final_definition_p (input_bfd, h, csect))
+	return 0;
+    }
 
   /* If we're discarding local symbols, check whether ISYM is local.  */
+  smtyp = SMTYP_SMTYP (aux->x_csect.x_smtyp);
   if (info->discard == discard_all
       && isym->n_sclass != C_EXT
       && (isym->n_sclass != C_HIDEXT || smtyp != XTY_SD))
@@ -3513,6 +3540,8 @@ bfd_xcoff_size_dynamic_sections (bfd *ou
 		}
 	      else
 		*debug_index = -1;
+	      if (*sym_hash != 0)
+		(*sym_hash)->flags |= XCOFF_ALLOCATED;
 	      if (*lineno_counts > 0)
 		csect->output_section->lineno_count += *lineno_counts;
 	    }
@@ -3690,8 +3719,7 @@ #define N_BTSHFT n_btshft
       if (isymp->n_sclass == C_EXT
 	  && *sym_hash != NULL
 	  && (*sym_hash)->ldsym != NULL
-	  && (smtyp != XTY_ER
-	      || (*sym_hash)->root.type == bfd_link_hash_undefined))
+	  && xcoff_final_definition_p (input_bfd, *sym_hash, *csectpp))
 	{
 	  struct xcoff_link_hash_entry *h;
 	  struct internal_ldsym *ldsym;
Index: ld/testsuite/ld-powerpc/aix-no-dup-syms-1a.s
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-no-dup-syms-1a.s	2009-03-10 13:49:33.000000000 +0000
@@ -0,0 +1,9 @@
+	.globl	x
+	.csect	x[RW]
+x:
+	.long	4
+	.globl	x1
+	.csect	x1[RW]
+x1:
+	.long	x
+	.long	foo
Index: ld/testsuite/ld-powerpc/aix-no-dup-syms-1b.s
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-no-dup-syms-1b.s	2009-03-10 13:49:33.000000000 +0000
@@ -0,0 +1,9 @@
+	.globl	x
+	.csect	x[RW]
+x:
+	.long	8
+	.globl	x2
+	.csect	x2[RW]
+x2:
+	.long	x
+	.long	foo
Index: ld/testsuite/ld-powerpc/aix-no-dup-syms-1.ex
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-no-dup-syms-1.ex	2009-03-10 13:49:33.000000000 +0000
@@ -0,0 +1,3 @@
+x
+x1
+x2
Index: ld/testsuite/ld-powerpc/aix-no-dup-syms-1.im
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-no-dup-syms-1.im	2009-03-10 13:49:33.000000000 +0000
@@ -0,0 +1,1 @@
+foo
Index: ld/testsuite/ld-powerpc/aix-no-dup-syms-1-dso.dnd
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-no-dup-syms-1-dso.dnd	2009-03-10 13:49:33.000000000 +0000
@@ -0,0 +1,4 @@
+ *         U foo
+0*10000000 D x
+0*10000004 D x1
+0*10000014 D x2
Index: ld/testsuite/ld-powerpc/aix-no-dup-syms-1-dso.drd
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-no-dup-syms-1-dso.drd	2009-03-10 13:49:33.000000000 +0000
@@ -0,0 +1,9 @@
+
+.*
+
+DYNAMIC RELOCATION RECORDS
+OFFSET * TYPE * VALUE 
+0*10000004 R_POS(|_32) * \.data
+0*10000008 R_POS(|_32) * foo
+0*10000014 R_POS(|_32) * \.data
+0*10000018 R_POS(|_32) * foo
Index: ld/testsuite/ld-powerpc/aix-no-dup-syms-1-dso.nd
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-no-dup-syms-1-dso.nd	2009-03-10 13:49:33.000000000 +0000
@@ -0,0 +1,8 @@
+ *         U foo
+0*10000000 d x
+0*10000000 D x
+0*10000010 d x
+0*10000004 d x1
+0*10000004 D x1
+0*10000014 d x2
+0*10000014 D x2
Index: ld/testsuite/ld-powerpc/aix-no-dup-syms-1-dso.rd
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-no-dup-syms-1-dso.rd	2009-03-10 13:49:33.000000000 +0000
@@ -0,0 +1,9 @@
+
+.*
+
+RELOCATION RECORDS FOR \[\.data\]:
+OFFSET * TYPE * VALUE 
+0+04 R_POS(|_32) * x\+0xf*f0000000
+0+08 R_POS(|_32) * foo
+0+14 R_POS(|_32) * x\+0xf*effffff0
+0+18 R_POS(|_32) * foo
Index: ld/testsuite/ld-powerpc/aix-no-dup-syms-1-rel.nd
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-no-dup-syms-1-rel.nd	2009-03-10 13:49:33.000000000 +0000
@@ -0,0 +1,8 @@
+ +   U foo
+0+00 d x
+0+00 D x
+0+10 d x
+0+04 d x1
+0+04 D x1
+0+14 d x2
+0+14 D x2
Index: ld/testsuite/ld-powerpc/aix-no-dup-syms-1-rel.rd
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-no-dup-syms-1-rel.rd	2009-03-10 13:49:33.000000000 +0000
@@ -0,0 +1,9 @@
+
+.*
+
+RELOCATION RECORDS FOR \[\.data\]:
+OFFSET * TYPE * VALUE 
+0+04 R_POS(|_32) * x
+0+08 R_POS(|_32) * foo
+0+14 R_POS(|_32) * x\+0xf+0
+0+18 R_POS(|_32) * foo
Index: ld/testsuite/ld-powerpc/aix52.exp
===================================================================
--- ld/testsuite/ld-powerpc/aix52.exp	2009-03-10 13:48:48.000000000 +0000
+++ ld/testsuite/ld-powerpc/aix52.exp	2009-03-10 13:49:33.000000000 +0000
@@ -96,6 +96,18 @@ set aix52tests {
      {{objdump -h aix-core-sec-3.hd}}
      "aix-core-sec-3.so"}
 
+    {"Duplicate symbol check 1 (rel)" "-r"
+     "" {aix-no-dup-syms-1a.s aix-no-dup-syms-1b.s}
+     {{nm {} aix-no-dup-syms-1-rel.nd} {objdump -r aix-no-dup-syms-1-rel.rd}}
+     "aix-no-dup-syms-1.o"}
+
+    {"Duplicate symbol check 1 (shared)"
+     "-shared --allow-multiple-definition -bI:aix-no-dup-syms-1.im -bE:aix-no-dup-syms-1.ex"
+     "" {aix-no-dup-syms-1a.s aix-no-dup-syms-1b.s}
+     {{nm {} aix-no-dup-syms-1-dso.nd} {objdump -r aix-no-dup-syms-1-dso.rd}
+      {nm -D aix-no-dup-syms-1-dso.dnd} {objdump -R aix-no-dup-syms-1-dso.drd}}
+     "aix-no-dup-syms-1.so"}
+
     {"Glink test 1"
      "-shared -bE:aix-glink-1.ex --unresolved-symbols=ignore-all"
      "" {aix-glink-1.s}


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