[16/21] Add AIX weak support

Richard Sandiford richards@transitive.com
Tue Mar 10 14:45:00 GMT 2009


This patch adds support for AIX C_WEAKEXT symbols.

Unfortunately, there seems to be some historical baggage here.
The AIX port was originally developed before AIX 5.2 came out,
and at that time AIX did not support weak symbols.  We had this
GNU-specific C_WEAKEXT definition instead:

#define C_WEAKEXT	127	/* weak symbol -- GNU extension.  */

We wrote out BSF_WEAK symbols using this C_WEAKEXT, and read C_WEAKEXT
symbols as BSF_WEAK, but for XCOFF we did little else.  The linker didn't
even enter weak symbols into the hash table, so a simple test like:

--------------------------------------------------------------------------
#!/bin/bash
set -eu
cat <<EOF >f1.s
	.weak	foo
	.csect	foo[RW]
foo:
	.long	1
EOF
cat <<EOF >f2.s
	.globl	bar
	.csect	bar[RW]
bar:
	.long	foo
EOF
cat <<EOF >exports
bar
EOF
./gas/as-new f1.s -o f1.o
./gas/as-new f2.s -o f2.o
./ld/ld-new f1.o f2.o -o f.so -shared -bnogc -bE:exports
--------------------------------------------------------------------------

failed with:

f2.o:fake:(.rw+0x0): undefined reference to `foo'

Weak support was added in AIX 5.2, which used a C_WEAKEXT value of 111
instead of 127.  The following patch added this alternative value:

2003-12-02  Graham Reed <grahamr@algorithmics.com>

	* internal.h (C_WEAKEXT): Add alternative value for AIX 5.2
	based targets.

However, no other changes were made, so weak symbols were still
essentially unsupported.  The testcase above still fails for AIX 5.2.

The AIX semantics of C_WEAKEXT are very different from what we implement
at the moment.  The symbols behave similarly to C_EXT and C_HIDEXT,
in that:

  (a) they should have auxillary csect information
  (b) they may have auxillary function information

But despite the problems above, I don't think it's appropriate to
change the meaning of GNU C_WEAKEXT symbols.  The new behaviour
should apply to AIX C_WEAKEXT only.  I've therefore added a new
C_AIX_WEAKEXT symbol type and made the new code use that instead
of C_WEAKEXT.  The general principle (which I think is used quite
a lot in binutils) is that:

  - We should handle existing C_AIX_WEAKEXT symbols without trying
    to be puritanical about the configured AIX version.  That is,
    we shouldn't refuse to handle existing C_AIX_WEAKEXT symbols
    simply because we were configured for AIX 5.1 or below.

  - We should only use the new features if they're supported.

As well as C_WEAKEXT, AIX 5.2 added a new L_WEAK flag for dynamic
(.loader) symbols.  The patch handles that too.

The main non-obvious change is to xcoff_link_add_dynamic_symbols.
This function looks at each symbol S defined by dynamic object D
and currently does the following:

  (1) If S was previously unknown, the function assumes that D defines S.
      It indicates this by setting S's symbol type to bfd_link_hash_undefined
      and pointing undef.abfd at D.

  (2) If S was previously undefined, and no dynamic definition has yet
      been found, the function again assumes that D defines S.  It indicates
      this by leaving S's type as-is (bfd_link_hash_undefined or _undefweak)
      and pointing undef.abfd at D.

  (3) If S previously had an unknown symbol class (XMC_UA), or was
      previously marked as _undefined or _undefweak, the function sets
      its symbol class to the one found in B.

(1) and (2) are sensible enough, but I take issue with (3).  If D doesn't
define S, I don't think it's right to copy the symbol class found in D to S.
We should stick with whatever the defining bfd said.

I think it makes more sense to skip any symbols that D doesn't define.
This makes the current logic more obvious, but more importantly,
it's then easier to see how weak support should fit in.

OK to install?

Richard


include/coff/
	* internal.h (C_AIX_WEAKEXT): New macro.
	(C_WEAKEXT): Use the GNU definition in the generic part of the file,
	and conditionally reset it to C_AIX_WEAKEXT in the XCOFF part of
	the file.
	(CSECT_SYM_P): New macro.
	* xcoff.h (L_WEAK): Define.
	(EXTERN_SYM_P): New macro.

bfd/
	* coffcode.h (coff_pointerize_aux_hook): Update CSECT_SYM_P to
	check whether a symbol has csect information.
	(coff_print_aux): Likewise.
	* coff-rs6000.c (_bfd_xcoff_swap_aux_in): Handle auxillary csect
	information for C_AIX_WEAKEXT too.
	(_bfd_xcoff_swap_aux_out): Likewise.
	(xcoff_reloc_type_br): Handle defweak symbols too.
	* coff64-rs6000.c (_bfd_xcoff64_swap_aux_in): Handle auxillary csect
	information for C_AIX_WEAKEXT too.
	(_bfd_xcoff64_swap_aux_out): Likewise.
	(xcoff64_reloc_type_br): Handle defweak symbols too.
	* coffgen.c (coff_print_symbol): Handle auxillary function
	information for C_AIX_WEAKEXT too.
	* xcofflink.c (_bfd_xcoff_canonicalize_dynamic_symtab): Set BSF_WEAK
	instead of BSF_GLOBAL if the L_WEAK flag is set.
	(xcoff_dynamic_definition_p): New function.
	(xcoff_link_add_dynamic_symbols): Use it to decide whether ldsym
	defines h.  Don't change h if ldsym isn't the definition.  Otherwise,
	always take the symbol class from the ldsym.  Use weak bfd symbol
	types for weak ldsyms.
	(xcoff_link_add_symbols): Use CSECT_SYM_P and EXTERN_SYM_P.
	Fix the check for whether a definition is from a shared object.
	Allow redefinitions of weak symbols.
	(xcoff_link_check_ar_symbols): Use EXTERN_SYM_P.
	(xcoff_keep_symbol_p): Likewise.
	(bfd_xcoff_size_dynamic_sections): Use CSECT_SYM_P.
	(xcoff_link_input_bfd): Use CSECT_SYM_P and EXTERN_SYM_P.
	Add .loader entries for C_AIX_WEAKEXT as well as C_EXT symbols,
	but mark them as L_WEAK.
	(xcoff_write_global_symbol): Treat weak symbols as C_AIX_WEAKEXT
	instead of C_EXT if C_AIX_WEAKEXT == C_WEAKEXT.

gas/
	* config/tc-ppc.c (ppc_frob_symbol): Add csect information for
	C_AIX_WEAKEXT too.

ld/testsuite/
	* ld-powerpc/aix-glink-2a.s, ld-powerpc/aix-glink-2a.ex,
	ld-powerpc/aix-glink-2b.s, ld-powerpc/aix-glink-2c.s,
	ld-powerpc/aix-glink-2c.ex, ld-powerpc/aix-glink-2d.s,
	ld-powerpc/aix-glink-2-32.dd, ld-powerpc/aix-glink-2-64.dd,
	ld-powerpc/aix-weak-1a.s, ld-powerpc/aix-weak-1b.s,
	ld-powerpc/aix-weak-1-rel.hd, ld-powerpc/aix-weak-1-rel.nd,
	ld-powerpc/aix-weak-1-dso.hd, ld-powerpc/aix-weak-1-dso.nd,
	ld-powerpc/aix-weak-1-dso.dnd, ld-powerpc/aix-weak-1.ex,
	ld-powerpc/aix-weak-2a.s, ld-powerpc/aix-weak-2a.ex,
	ld-powerpc/aix-weak-2a.nd, ld-powerpc/aix-weak-2b.s,
	ld-powerpc/aix-weak-2b.nd, ld-powerpc/aix-weak-2c.s,
	ld-powerpc/aix-weak-2c.ex, ld-powerpc/aix-weak-2c.nd,
	ld-powerpc/aix-weak-2c.od, ld-powerpc/aix-weak-3a.s,
	ld-powerpc/aix-weak-3a.ex, ld-powerpc/aix-weak-3b.s,
	ld-powerpc/aix-weak-3b.ex, ld-powerpc/aix-weak-3-32.d,
	ld-powerpc/aix-weak-3-32.dd, ld-powerpc/aix-weak-3-64.d,
	ld-powerpc/aix-weak-3-64.dd: New tests.
	* ld-powerpc/aix52.exp: Run them.  Replace tmp/aix-* with
	tmp/aix64-* in 64-bit ld options.

Index: include/coff/internal.h
===================================================================
--- include/coff/internal.h	2009-03-10 13:38:52.000000000 +0000
+++ include/coff/internal.h	2009-03-10 13:51:47.000000000 +0000
@@ -273,12 +273,7 @@ #define C_FILE		103	/* file name			*/
 #define C_LINE		104	/* line # reformatted as symbol table entry */
 #define C_ALIAS	 	105	/* duplicate tag		*/
 #define C_HIDDEN	106	/* ext symbol in dmert public lib */
-
-#if defined _AIX52 || defined AIX_WEAK_SUPPORT
-#define C_WEAKEXT	111	/* weak symbol -- AIX standard.  */
-#else
 #define C_WEAKEXT	127	/* weak symbol -- GNU extension.  */
-#endif
 
 /* New storage classes for TI COFF */
 #define C_UEXT		19	/* Tentative external definition */
@@ -311,6 +306,12 @@ #define C_VERSION       108     /* coff 
 #define C_HIDEXT        107	/* Un-named external symbol */
 #define C_BINCL         108	/* Marks beginning of include file */
 #define C_EINCL         109	/* Marks ending of include file */
+#define C_AIX_WEAKEXT   111	/* AIX definition of C_WEAKEXT.  */
+
+#if defined _AIX52 || defined AIX_WEAK_SUPPORT
+#undef C_WEAKEXT
+#define C_WEAKEXT       C_AIX_WEAKEXT
+#endif
 
  /* storage classes for stab symbols for RS/6000 */
 #define C_GSYM          (0x80)
@@ -336,6 +337,10 @@ #define C_THUMBLABEL    (128 + C_LABEL)	
 #define C_THUMBEXTFUNC  (C_THUMBEXT  + 20)	/* 150 */
 #define C_THUMBSTATFUNC (C_THUMBSTAT + 20)	/* 151 */
 
+/* True if XCOFF symbols of class CLASS have auxillary csect information.  */
+#define CSECT_SYM_P(CLASS) \
+  ((CLASS) == C_EXT || (CLASS) == C_AIX_WEAKEXT || (CLASS) == C_HIDEXT)
+
 /********************** SECTION HEADER **********************/
 
 #define SCNNMLEN (8)
Index: include/coff/xcoff.h
===================================================================
--- include/coff/xcoff.h	2009-03-10 13:49:33.000000000 +0000
+++ include/coff/xcoff.h	2009-03-10 13:51:47.000000000 +0000
@@ -214,6 +214,8 @@ #define L_IMPORT (0x40)
 #define L_ENTRY (0x20)
 /* Exported symbol.  */
 #define L_EXPORT (0x10)
+/* Weak symbol.  */
+#define L_WEAK (0x08)
 
 /* The ldrel structure.  This is used to represent a reloc in the
    .loader section.  */
@@ -644,4 +646,8 @@ #define arch_xhdr(bfd) \
 #define arch_xhdr_big(bfd) \
   ((struct xcoff_ar_hdr_big *) arch_eltdata (bfd)->arch_header)
 
+/* True if symbols of class CLASS are external.  */
+#define EXTERN_SYM_P(CLASS) \
+  ((CLASS) == C_EXT || (CLASS) == C_AIX_WEAKEXT)
+
 #endif /* _INTERNAL_XCOFF_H */
Index: bfd/coffcode.h
===================================================================
--- bfd/coffcode.h	2009-03-10 13:38:52.000000000 +0000
+++ bfd/coffcode.h	2009-03-10 13:51:47.000000000 +0000
@@ -2416,7 +2416,7 @@ #define symname_in_debug_hook \
 #define FORCE_SYMNAMES_IN_STRINGS
 #endif
 
-/* Handle the csect auxent of a C_EXT or C_HIDEXT symbol.  */
+/* Handle the csect auxent of a C_EXT, C_AIX_WEAKEXT or C_HIDEXT symbol.  */
 
 static bfd_boolean
 coff_pointerize_aux_hook (bfd *abfd ATTRIBUTE_UNUSED,
@@ -2427,7 +2427,7 @@ coff_pointerize_aux_hook (bfd *abfd ATTR
 {
   int class = symbol->u.syment.n_sclass;
 
-  if ((class == C_EXT || class == C_HIDEXT)
+  if (CSECT_SYM_P (class)
       && indaux + 1 == symbol->u.syment.n_numaux)
     {
       if (SMTYP_SMTYP (aux->u.auxent.x_csect.x_smtyp) == XTY_LD)
@@ -2485,8 +2485,7 @@ coff_print_aux (bfd *abfd ATTRIBUTE_UNUS
 		unsigned int indaux ATTRIBUTE_UNUSED)
 {
 #ifdef RS6000COFF_C
-  if ((symbol->u.syment.n_sclass == C_EXT
-       || symbol->u.syment.n_sclass == C_HIDEXT)
+  if (CSECT_SYM_P (symbol->u.syment.n_sclass)
       && indaux + 1 == symbol->u.syment.n_numaux)
     {
       /* This is a csect entry.  */
Index: bfd/coff-rs6000.c
===================================================================
--- bfd/coff-rs6000.c	2009-03-10 13:46:23.000000000 +0000
+++ bfd/coff-rs6000.c	2009-03-10 13:51:47.000000000 +0000
@@ -422,6 +422,7 @@ _bfd_xcoff_swap_aux_in (abfd, ext1, type
 
       /* RS/6000 "csect" auxents */
     case C_EXT:
+    case C_AIX_WEAKEXT:
     case C_HIDEXT:
       if (indx + 1 == numaux)
 	{
@@ -531,6 +532,7 @@ _bfd_xcoff_swap_aux_out (abfd, inp, type
 
       /* RS/6000 "csect" auxents */
     case C_EXT:
+    case C_AIX_WEAKEXT:
     case C_HIDEXT:
       if (indx + 1 == numaux)
 	{
@@ -2963,7 +2965,8 @@ xcoff_reloc_type_br (input_bfd, input_se
      going to global linkage code, we can replace the load with a
      cror.  */
   if (NULL != h
-      && bfd_link_hash_defined == h->root.type
+      && (bfd_link_hash_defined == h->root.type
+	  || bfd_link_hash_defweak == h->root.type)
       && section_offset + 8 <= input_section->size)
     {
       bfd_byte *pnext;
@@ -3008,7 +3011,8 @@ xcoff_reloc_type_br (input_bfd, input_se
   howto->dst_mask = howto->src_mask;
 
   if (h != NULL
-      && h->root.type == bfd_link_hash_defined
+      && (h->root.type == bfd_link_hash_defined
+	  || h->root.type == bfd_link_hash_defweak)
       && bfd_is_abs_section (h->root.u.def.section)
       && section_offset + 4 <= input_section->size)
     {
Index: bfd/coff64-rs6000.c
===================================================================
--- bfd/coff64-rs6000.c	2009-03-10 13:46:23.000000000 +0000
+++ bfd/coff64-rs6000.c	2009-03-10 13:51:47.000000000 +0000
@@ -381,6 +381,7 @@ _bfd_xcoff64_swap_aux_in (abfd, ext1, ty
 
       /* RS/6000 "csect" auxents */
     case C_EXT:
+    case C_AIX_WEAKEXT:
     case C_HIDEXT:
       if (indx + 1 == numaux)
 	{
@@ -473,6 +474,7 @@ _bfd_xcoff64_swap_aux_out (abfd, inp, ty
 
       /* RS/6000 "csect" auxents */
     case C_EXT:
+    case C_AIX_WEAKEXT:
     case C_HIDEXT:
       if (indx + 1 == numaux)
 	{
@@ -1133,7 +1135,8 @@ xcoff64_reloc_type_br (input_bfd, input_
      going to global linkage code, we can replace the load with a
      cror.  */
   if (NULL != h
-      && bfd_link_hash_defined == h->root.type
+      && (bfd_link_hash_defined == h->root.type
+	  || bfd_link_hash_defweak == h->root.type)
       && section_offset + 8 <= input_section->size)
     {
       bfd_byte *pnext;
@@ -1176,7 +1179,8 @@ xcoff64_reloc_type_br (input_bfd, input_
   howto->dst_mask = howto->src_mask;
 
   if (h != NULL
-      && h->root.type == bfd_link_hash_defined
+      && (h->root.type == bfd_link_hash_defined
+	  || h->root.type == bfd_link_hash_defweak)
       && bfd_is_abs_section (h->root.u.def.section)
       && section_offset + 4 <= input_section->size)
     {
Index: bfd/coffgen.c
===================================================================
--- bfd/coffgen.c	2009-03-10 13:38:52.000000000 +0000
+++ bfd/coffgen.c	2009-03-10 13:51:47.000000000 +0000
@@ -2006,6 +2006,7 @@ coff_print_symbol (bfd *abfd,
 		    }
 		    /* Otherwise fall through.  */
 		case C_EXT:
+		case C_AIX_WEAKEXT:
 		  if (ISFCN (combined->u.syment.n_type))
 		    {
 		      long next, llnos;
Index: bfd/xcofflink.c
===================================================================
--- bfd/xcofflink.c	2009-03-10 13:49:33.000000000 +0000
+++ bfd/xcofflink.c	2009-03-10 13:51:47.000000000 +0000
@@ -258,7 +258,12 @@ _bfd_xcoff_canonicalize_dynamic_symtab (
 
       symbuf->symbol.flags = BSF_NO_FLAGS;
       if ((ldsym.l_smtype & L_EXPORT) != 0)
-	symbuf->symbol.flags |= BSF_GLOBAL;
+	{
+	  if ((ldsym.l_smtype & L_WEAK) != 0)
+	    symbuf->symbol.flags |= BSF_WEAK;
+	  else
+	    symbuf->symbol.flags |= BSF_GLOBAL;
+	}
 
       /* FIXME: We have no way to record the other information stored
 	 with the loader symbol.  */
@@ -540,6 +545,36 @@ xcoff_read_internal_relocs (bfd *abfd,
 					 require_internal, internal_relocs);
 }
 
+/* H is the bfd symbol associated with exported .loader symbol LDSYM.
+   Return true if LDSYM defines H.  */
+
+static bfd_boolean
+xcoff_dynamic_definition_p (struct xcoff_link_hash_entry *h,
+			    struct internal_ldsym *ldsym)
+{
+  /* If we didn't know about H before processing LDSYM, LDSYM
+     definitely defines H.  */
+  if (h->root.type == bfd_link_hash_new)
+    return TRUE;
+
+  /* If H is currently a weak dynamic symbol, and if LDSYM is a strong
+     dynamic symbol, LDSYM trumps the current definition of H.  */
+  if ((ldsym->l_smtype & L_WEAK) == 0
+      && (h->flags & XCOFF_DEF_DYNAMIC) != 0
+      && (h->flags & XCOFF_DEF_REGULAR) == 0
+      && (h->root.type == bfd_link_hash_defweak
+	  || h->root.type == bfd_link_hash_undefweak))
+    return TRUE;
+
+  /* If H is currently undefined, LDSYM defines it.  */
+  if ((h->flags & XCOFF_DEF_DYNAMIC) == 0
+      && (h->root.type == bfd_link_hash_undefined
+	  || h->root.type == bfd_link_hash_undefweak))
+    return TRUE;
+
+  return FALSE;
+}
+
 /* This function is used to add symbols from a dynamic object to the
    global symbol table.  */
 
@@ -638,43 +673,33 @@ xcoff_link_add_dynamic_symbols (bfd *abf
       if (h == NULL)
 	return FALSE;
 
-      h->flags |= XCOFF_DEF_DYNAMIC;
-
-      /* If the symbol is undefined, and the BFD it was found in is
-	 not a dynamic object, change the BFD to this dynamic object,
-	 so that we can get the correct import file ID.  */
-      if ((h->root.type == bfd_link_hash_undefined
-	   || h->root.type == bfd_link_hash_undefweak)
-	  && (h->root.u.undef.abfd == NULL
-	      || (h->root.u.undef.abfd->flags & DYNAMIC) == 0))
-	h->root.u.undef.abfd = abfd;
-
-      if (h->root.type == bfd_link_hash_new)
-	{
-	  h->root.type = bfd_link_hash_undefined;
-	  h->root.u.undef.abfd = abfd;
-	  /* We do not want to add this to the undefined symbol list.  */
-	}
-
-      if (h->smclas == XMC_UA
-	  || h->root.type == bfd_link_hash_undefined
-	  || h->root.type == bfd_link_hash_undefweak)
-	h->smclas = ldsym.l_smclas;
-
-      /* Unless this is an XMC_XO symbol, we don't bother to actually
-	 define it, since we don't have a section to put it in anyhow.
-	 Instead, the relocation routines handle the DEF_DYNAMIC flag
-	 correctly.  */
+      if (!xcoff_dynamic_definition_p (h, &ldsym))
+	continue;
 
-      if (h->smclas == XMC_XO
-	  && (h->root.type == bfd_link_hash_undefined
-	      || h->root.type == bfd_link_hash_undefweak))
+      h->flags |= XCOFF_DEF_DYNAMIC;
+      h->smclas = ldsym.l_smclas;
+      if (h->smclas == XMC_XO)
 	{
 	  /* This symbol has an absolute value.  */
-	  h->root.type = bfd_link_hash_defined;
+	  if ((ldsym.l_smtype & L_WEAK) != 0)
+	    h->root.type = bfd_link_hash_defweak;
+	  else
+	    h->root.type = bfd_link_hash_defined;
 	  h->root.u.def.section = bfd_abs_section_ptr;
 	  h->root.u.def.value = ldsym.l_value;
 	}
+      else
+	{
+	  /* Otherwise, we don't bother to actually define the symbol,
+	     since we don't have a section to put it in anyhow.
+	     We assume instead that an undefined XCOFF_DEF_DYNAMIC symbol
+	     should be imported from the symbol's undef.abfd.  */
+	  if ((ldsym.l_smtype & L_WEAK) != 0)
+	    h->root.type = bfd_link_hash_undefweak;
+	  else
+	    h->root.type = bfd_link_hash_undefined;
+	  h->root.u.undef.abfd = abfd;
+	}
 
       /* If this symbol defines a function descriptor, then it
 	 implicitly defines the function code as well.  */
@@ -701,33 +726,30 @@ xcoff_link_add_dynamic_symbols (bfd *abf
 	      if (hds == NULL)
 		return FALSE;
 
-	      if (hds->root.type == bfd_link_hash_new)
+	      hds->descriptor = h;
+	      h->descriptor = hds;
+	    }
+
+	  if (xcoff_dynamic_definition_p (hds, &ldsym))
+	    {
+	      hds->root.type = h->root.type;
+	      hds->flags |= XCOFF_DEF_DYNAMIC;
+	      if (h->smclas == XMC_XO)
 		{
-		  hds->root.type = bfd_link_hash_undefined;
+		  /* An absolute symbol appears to actually define code, not a
+		     function descriptor.  This is how some math functions are
+		     implemented on AIX 4.1.  */
+		  hds->smclas = XMC_XO;
+		  hds->root.u.def.section = bfd_abs_section_ptr;
+		  hds->root.u.def.value = ldsym.l_value;
+		}
+	      else
+		{
+		  hds->smclas = XMC_PR;
 		  hds->root.u.undef.abfd = abfd;
 		  /* We do not want to add this to the undefined
 		     symbol list.  */
 		}
-
-	      hds->descriptor = h;
-	      h->descriptor = hds;
-	    }
-
-	  hds->flags |= XCOFF_DEF_DYNAMIC;
-	  if (hds->smclas == XMC_UA)
-	    hds->smclas = XMC_PR;
-
-	  /* An absolute symbol appears to actually define code, not a
-	     function descriptor.  This is how some math functions are
-	     implemented on AIX 4.1.  */
-	  if (h->smclas == XMC_XO
-	      && (hds->root.type == bfd_link_hash_undefined
-		  || hds->root.type == bfd_link_hash_undefweak))
-	    {
-	      hds->smclas = XMC_XO;
-	      hds->root.type = bfd_link_hash_defined;
-	      hds->root.u.def.section = bfd_abs_section_ptr;
-	      hds->root.u.def.value = ldsym.l_value;
 	    }
 	}
     }
@@ -1087,7 +1109,6 @@ #define N_BTSHFT n_btshft
       const char *name;
       char buf[SYMNMLEN + 1];
       int smtyp;
-      flagword flags;
       asection *section;
       bfd_vma value;
       struct xcoff_link_hash_entry *set_toc;
@@ -1096,7 +1117,7 @@ #define N_BTSHFT n_btshft
 
       /* In this pass we are only interested in symbols with csect
 	 information.  */
-      if (sym.n_sclass != C_EXT && sym.n_sclass != C_HIDEXT)
+      if (!CSECT_SYM_P (sym.n_sclass))
 	{
 	  /* Set csect_cache,
 	     Normally csect is a .pr, .rw  etc. created in the loop
@@ -1216,7 +1237,6 @@ #define N_BTSHFT n_btshft
 
       smtyp = SMTYP_SMTYP (aux.x_csect.x_smtyp);
 
-      flags = BSF_GLOBAL;
       section = NULL;
       value = 0;
       set_toc = NULL;
@@ -1327,7 +1347,7 @@ #define N_BTSHFT n_btshft
 		  erelsym = ((bfd_byte *) obj_coff_external_syms (abfd)
 			     + rel->r_symndx * symesz);
 		  bfd_coff_swap_sym_in (abfd, (void *) erelsym, (void *) &relsym);
-		  if (relsym.n_sclass == C_EXT)
+		  if (EXTERN_SYM_P (relsym.n_sclass))
 		    {
 		      const char *relname;
 		      char relbuf[SYMNMLEN + 1];
@@ -1482,9 +1502,9 @@ #define N_BTSHFT n_btshft
 	    if (first_csect == NULL)
 	      first_csect = csect;
 
-	    /* If this symbol is C_EXT, we treat it as starting at the
+	    /* If this symbol is external, we treat it as starting at the
 	       beginning of the newly created section.  */
-	    if (sym.n_sclass == C_EXT)
+	    if (EXTERN_SYM_P (sym.n_sclass))
 	      {
 		section = csect;
 		value = 0;
@@ -1573,7 +1593,7 @@ #define N_BTSHFT n_btshft
 	  if (first_csect == NULL)
 	    first_csect = csect;
 
-	  if (sym.n_sclass == C_EXT)
+	  if (EXTERN_SYM_P (sym.n_sclass))
 	    {
 	      csect->flags |= SEC_IS_COMMON;
 	      csect->size = 0;
@@ -1614,9 +1634,10 @@ #define N_BTSHFT n_btshft
       /* Now we have enough information to add the symbol to the
 	 linker hash table.  */
 
-      if (sym.n_sclass == C_EXT)
+      if (EXTERN_SYM_P (sym.n_sclass))
 	{
 	  bfd_boolean copy;
+	  flagword flags;
 
 	  BFD_ASSERT (section != NULL);
 
@@ -1687,8 +1708,8 @@ #define N_BTSHFT n_btshft
 		      section = bfd_und_section_ptr;
 		      value = 0;
 		    }
-		  else if (((*sym_hash)->root.u.def.section->owner->flags
-			    & DYNAMIC) != 0)
+		  else if (((*sym_hash)->flags & XCOFF_DEF_REGULAR) == 0
+			   && ((*sym_hash)->flags & XCOFF_DEF_DYNAMIC) != 0)
 		    {
 		      /* The existing symbol is from a shared library.
 			 Replace it.  */
@@ -1704,6 +1725,12 @@ #define N_BTSHFT n_btshft
 		      section = bfd_und_section_ptr;
 		      value = 0;
 		    }
+		  else if (sym.n_sclass == C_AIX_WEAKEXT
+			   || (*sym_hash)->root.type == bfd_link_hash_defweak)
+		    {
+		      /* At least one of the definitions is weak.
+			 Allow the normal rules to take effect.  */
+		    }
 		  else if ((*sym_hash)->root.u.undef.next != NULL
 			   || info->hash->undefs_tail == &(*sym_hash)->root)
 		    {
@@ -1723,8 +1750,7 @@ #define N_BTSHFT n_btshft
 		    }
 		}
 	      else if (((*sym_hash)->flags & XCOFF_MULTIPLY_DEFINED) != 0
-		       && ((*sym_hash)->root.type == bfd_link_hash_defined
-			   || (*sym_hash)->root.type == bfd_link_hash_defweak)
+		       && (*sym_hash)->root.type == bfd_link_hash_defined
 		       && (bfd_is_und_section (section)
 			   || bfd_is_com_section (section)))
 		{
@@ -1759,6 +1785,7 @@ #define N_BTSHFT n_btshft
 	     a second time from the csects.  */
 	  BFD_ASSERT (last_real->next == first_csect);
 	  last_real->next = NULL;
+	  flags = (sym.n_sclass == C_EXT ? BSF_GLOBAL : BSF_WEAK);
 	  if (! (_bfd_generic_link_add_one_symbol
 		 (info, abfd, name, flags, section, value,
 		  NULL, copy, TRUE,
@@ -2073,7 +2100,7 @@ xcoff_link_check_ar_symbols (bfd *abfd,
 
       bfd_coff_swap_sym_in (abfd, (void *) esym, (void *) &sym);
 
-      if (sym.n_sclass == C_EXT && sym.n_scnum != N_UNDEF)
+      if (EXTERN_SYM_P (sym.n_sclass) && sym.n_scnum != N_UNDEF)
 	{
 	  const char *name;
 	  char buf[SYMNMLEN + 1];
@@ -3070,7 +3097,7 @@ xcoff_keep_symbol_p (struct bfd_link_inf
     return 0;
 
   /* Discard symbols that are defined elsewhere.  */
-  if (isym->n_sclass == C_EXT)
+  if (EXTERN_SYM_P (isym->n_sclass))
     {
       if ((h->flags & XCOFF_ALLOCATED) != 0)
 	return 0;
@@ -3081,7 +3108,7 @@ xcoff_keep_symbol_p (struct bfd_link_inf
   /* 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
+      && !EXTERN_SYM_P (isym->n_sclass)
       && (isym->n_sclass != C_HIDEXT || smtyp != XTY_SD))
     return 0;
 
@@ -3109,7 +3136,7 @@ xcoff_keep_symbol_p (struct bfd_link_inf
 	return 0;
 
       if (info->discard == discard_l
-	  && isym->n_sclass != C_EXT
+	  && !EXTERN_SYM_P (isym->n_sclass)
 	  && (isym->n_sclass != C_HIDEXT || smtyp != XTY_SD)
 	  && bfd_is_local_label_name (input_bfd, name))
 	return 0;
@@ -3495,9 +3522,8 @@ bfd_xcoff_size_dynamic_sections (bfd *ou
 
 	  bfd_coff_swap_sym_in (sub, esym, &sym);
 
-	  /* If this is a C_EXT or C_HIDEXT symbol, we need the csect
-	     information too.  */
-	  if (sym.n_sclass == C_EXT || sym.n_sclass == C_HIDEXT)
+	  /* Read in the csect information, if any.  */
+	  if (CSECT_SYM_P (sym.n_sclass))
 	    {
 	      BFD_ASSERT (sym.n_numaux > 0);
 	      bfd_coff_swap_aux_in (sub, esym + symesz * sym.n_numaux,
@@ -3698,9 +3724,8 @@ #define N_BTSHFT n_btshft
 
       bfd_coff_swap_sym_in (input_bfd, (void *) esym, (void *) isymp);
 
-      /* If this is a C_EXT or C_HIDEXT symbol, we need the csect
-	 information.  */
-      if (isymp->n_sclass == C_EXT || isymp->n_sclass == C_HIDEXT)
+      /* Read in the csect information, if any.  */
+      if (CSECT_SYM_P (isymp->n_sclass))
 	{
 	  BFD_ASSERT (isymp->n_numaux > 0);
 	  bfd_coff_swap_aux_in (input_bfd,
@@ -3716,7 +3741,7 @@ #define N_BTSHFT n_btshft
 	 .loader symbol information.  If this is an external symbol
 	 reference to a defined symbol, though, then wait until we get
 	 to the definition.  */
-      if (isymp->n_sclass == C_EXT
+      if (EXTERN_SYM_P (isymp->n_sclass)
 	  && *sym_hash != NULL
 	  && (*sym_hash)->ldsym != NULL
 	  && xcoff_final_definition_p (input_bfd, *sym_hash, *csectpp))
@@ -3751,6 +3776,8 @@ #define N_BTSHFT n_btshft
 	    ldsym->l_smtype |= L_EXPORT;
 	  if ((h->flags & XCOFF_ENTRY) != 0)
 	    ldsym->l_smtype |= L_ENTRY;
+	  if (isymp->n_sclass == C_AIX_WEAKEXT)
+	    ldsym->l_smtype |= L_WEAK;
 
 	  ldsym->l_smclas = aux.x_csect.x_smclas;
 
@@ -3812,7 +3839,7 @@ #define N_BTSHFT n_btshft
 	  /* Assign the next unused index to this symbol.  */
 	  *indexp = output_index;
 
-	  if (isymp->n_sclass == C_EXT)
+	  if (EXTERN_SYM_P (isymp->n_sclass))
 	    {
 	      BFD_ASSERT (*sym_hash != NULL);
 	      (*sym_hash)->indx = output_index;
@@ -4018,8 +4045,7 @@ #define N_BTSHFT n_btshft
 		      aux.x_file.x_n.x_offset = STRING_SIZE_SIZE + indx;
 		    }
 		}
-	      else if ((isymp->n_sclass == C_EXT
-			|| isymp->n_sclass == C_HIDEXT)
+	      else if (CSECT_SYM_P (isymp->n_sclass)
 		       && i + 1 == isymp->n_numaux)
 		{
 
@@ -4098,8 +4124,7 @@ #define N_BTSHFT n_btshft
 	      /* Copy over the line numbers, unless we are stripping
 		 them.  We do this on a symbol by symbol basis in
 		 order to more easily handle garbage collection.  */
-	      if ((isymp->n_sclass == C_EXT
-		   || isymp->n_sclass == C_HIDEXT)
+	      if (CSECT_SYM_P (isymp->n_sclass)
 		  && i == 0
 		  && isymp->n_numaux > 1
 		  && ISFCN (isymp->n_type)
@@ -5194,7 +5219,11 @@ xcoff_write_global_symbol (struct xcoff_
     {
       isym.n_value = 0;
       isym.n_scnum = N_UNDEF;
-      isym.n_sclass = C_EXT;
+      if (h->root.type == bfd_link_hash_undefweak
+	  && C_WEAKEXT == C_AIX_WEAKEXT)
+	isym.n_sclass = C_WEAKEXT;
+      else
+	isym.n_sclass = C_EXT;
       aux.x_csect.x_smtyp = XTY_ER;
     }
   else if ((h->root.type == bfd_link_hash_defined
@@ -5204,7 +5233,11 @@ xcoff_write_global_symbol (struct xcoff_
       BFD_ASSERT (bfd_is_abs_section (h->root.u.def.section));
       isym.n_value = h->root.u.def.value;
       isym.n_scnum = N_UNDEF;
-      isym.n_sclass = C_EXT;
+      if (h->root.type == bfd_link_hash_undefweak
+	  && C_WEAKEXT == C_AIX_WEAKEXT)
+	isym.n_sclass = C_WEAKEXT;
+      else
+	isym.n_sclass = C_EXT;
       aux.x_csect.x_smtyp = XTY_ER;
     }
   else if (h->root.type == bfd_link_hash_defined
@@ -5266,7 +5299,11 @@ xcoff_write_global_symbol (struct xcoff_
       /* We just output an SD symbol.  Now output an LD symbol.  */
       h->indx += 2;
 
-      isym.n_sclass = C_EXT;
+      if (h->root.type == bfd_link_hash_undefweak
+	  && C_WEAKEXT == C_AIX_WEAKEXT)
+	isym.n_sclass = C_WEAKEXT;
+      else
+	isym.n_sclass = C_EXT;
       bfd_coff_swap_sym_out (output_bfd, (void *) &isym, (void *) outsym);
       outsym += bfd_coff_symesz (output_bfd);
 
Index: gas/config/tc-ppc.c
===================================================================
--- gas/config/tc-ppc.c	2009-03-10 13:46:12.000000000 +0000
+++ gas/config/tc-ppc.c	2009-03-10 13:51:47.000000000 +0000
@@ -5046,6 +5046,7 @@ ppc_frob_symbol (symbolS *sym)
     S_SET_STORAGE_CLASS (sym, C_HIDEXT);
 
   if (S_GET_STORAGE_CLASS (sym) == C_EXT
+      || S_GET_STORAGE_CLASS (sym) == C_AIX_WEAKEXT
       || S_GET_STORAGE_CLASS (sym) == C_HIDEXT)
     {
       int i;
Index: ld/testsuite/ld-powerpc/aix-glink-2a.s
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-glink-2a.s	2009-03-10 13:51:47.000000000 +0000
@@ -0,0 +1,41 @@
+	.toc
+
+	.macro	defabs,type,name,value
+	\type	\name
+	\name	= \value
+	.endm
+
+	.macro	deffun,type,name,fn
+	\type	\name
+	.csect	\name\()[DS]
+\name\():
+	.if	size == 32
+	.long	.\name\()[PR],TOC[TC0],0
+	.else
+	.llong	.\name\()[PR],TOC[TC0],0
+	.endif
+
+	.globl	.\name
+	.csect	.\name\()[PR]
+.\name\():
+	nop
+	.endm
+
+	.macro	defdata,type,name,contents
+	\type	\name
+	.csect	\name\()[RW]
+\name\():
+	.long	\contents
+	.endm
+
+	defabs	.globl,a1,0xf100
+	deffun	.globl,a2
+	defdata	.globl,a3,0x1100
+
+	defabs	.globl,b1,0xf200
+	deffun	.globl,b2
+	defdata	.globl,b3,0x2200
+
+	defabs	.weak,c1,0xf300
+	deffun	.weak,c2
+	defdata	.weak,c3,0x3300
Index: ld/testsuite/ld-powerpc/aix-glink-2a.ex
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-glink-2a.ex	2009-03-10 13:51:47.000000000 +0000
@@ -0,0 +1,9 @@
+a1
+a2
+a3
+b1
+b2
+b3
+c1
+c2
+c3
Index: ld/testsuite/ld-powerpc/aix-glink-2b.s
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-glink-2b.s	2009-03-10 13:51:47.000000000 +0000
@@ -0,0 +1,12 @@
+	.toc
+
+	.macro	deffun,type,name
+	.globl	.\name
+	.csect	.\name\()[PR]
+.\name\():
+	nop
+	.endm
+
+	deffun	.globl,b1
+	deffun	.globl,b2
+	deffun	.globl,b3
Index: ld/testsuite/ld-powerpc/aix-glink-2c.s
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-glink-2c.s	2009-03-10 13:51:47.000000000 +0000
@@ -0,0 +1,33 @@
+	.toc
+
+	.macro	defabs,type,name,value
+	\type	\name
+	\name	= \value
+	.endm
+
+	.macro	deffun,type,name
+	\type	\name
+	.csect	\name\()[DS]
+\name\():
+	.long	\name\()[PR],TOC[TC0],0
+
+	.globl	.\name
+	.csect	.\name\()[PR]
+.\name\():
+	nop
+	.endm
+
+	.macro	defdata,type,name,contents
+	\type	\name
+	.csect	\name\()[RW]
+\name\():
+	.long	\contents
+	.endm
+
+	defabs	.globl,a1,0xf400
+	deffun	.globl,a2
+	defdata	.globl,a3,0x4400
+
+	defabs	.globl,c1,0xf500
+	deffun	.globl,c2
+	defdata	.globl,c3,0x5500
Index: ld/testsuite/ld-powerpc/aix-glink-2c.ex
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-glink-2c.ex	2009-03-10 13:51:47.000000000 +0000
@@ -0,0 +1,6 @@
+a1
+a2
+a3
+c1
+c2
+c3
Index: ld/testsuite/ld-powerpc/aix-glink-2d.s
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-glink-2d.s	2009-03-10 13:51:47.000000000 +0000
@@ -0,0 +1,12 @@
+	.globl	.main
+	.csect	.main[PR]
+.main:
+	bl	.a1
+	bl	.a2
+	bl	.a3
+	bl	.b1
+	bl	.b2
+	bl	.b3
+	bl	.c1
+	bl	.c2
+	bl	.c3
Index: ld/testsuite/ld-powerpc/aix-glink-2-32.dd
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-glink-2-32.dd	2009-03-10 13:51:47.000000000 +0000
@@ -0,0 +1,69 @@
+
+tmpdir/aix-glink-2:     file format aixcoff-rs6000
+
+
+Disassembly of section \.text:
+
+10000000 <\.b1>:
+10000000:	60 00 00 00 	oril    r0,r0,0
+
+10000004 <\.b2>:
+10000004:	60 00 00 00 	oril    r0,r0,0
+
+10000008 <\.b3>:
+10000008:	60 00 00 00 	oril    r0,r0,0
+
+1000000c <\.main>:
+1000000c:	48 00 f1 03 	bla     f100 <.*>
+10000010:	48 00 00 21 	bl      10000030 <\.a2>
+10000014:	48 00 00 41 	bl      10000054 <\.a3>
+10000018:	4b ff ff e9 	bl      10000000 <\.b1>
+1000001c:	4b ff ff e9 	bl      10000004 <\.b2>
+10000020:	4b ff ff e9 	bl      10000008 <\.b3>
+10000024:	48 00 f5 03 	bla     f500 <.*>
+10000028:	48 00 00 51 	bl      10000078 <\.c2>
+1000002c:	48 00 00 71 	bl      1000009c <\.c3>
+
+10000030 <\.a2>:
+10000030:	81 82 00 00 	l       r12,0\(r2\)
+10000034:	90 41 00 14 	st      r2,20\(r1\)
+10000038:	80 0c 00 00 	l       r0,0\(r12\)
+1000003c:	80 4c 00 04 	l       r2,4\(r12\)
+10000040:	7c 09 03 a6 	mtctr   r0
+10000044:	4e 80 04 20 	bctr
+10000048:	00 00 00 00 	\.long 0x0
+1000004c:	00 0c 80 00 	\.long 0xc8000
+10000050:	00 00 00 00 	\.long 0x0
+
+10000054 <\.a3>:
+10000054:	81 82 00 04 	l       r12,4\(r2\)
+10000058:	90 41 00 14 	st      r2,20\(r1\)
+1000005c:	80 0c 00 00 	l       r0,0\(r12\)
+10000060:	80 4c 00 04 	l       r2,4\(r12\)
+10000064:	7c 09 03 a6 	mtctr   r0
+10000068:	4e 80 04 20 	bctr
+1000006c:	00 00 00 00 	\.long 0x0
+10000070:	00 0c 80 00 	\.long 0xc8000
+10000074:	00 00 00 00 	\.long 0x0
+
+10000078 <\.c2>:
+10000078:	81 82 00 08 	l       r12,8\(r2\)
+1000007c:	90 41 00 14 	st      r2,20\(r1\)
+10000080:	80 0c 00 00 	l       r0,0\(r12\)
+10000084:	80 4c 00 04 	l       r2,4\(r12\)
+10000088:	7c 09 03 a6 	mtctr   r0
+1000008c:	4e 80 04 20 	bctr
+10000090:	00 00 00 00 	\.long 0x0
+10000094:	00 0c 80 00 	\.long 0xc8000
+10000098:	00 00 00 00 	\.long 0x0
+
+1000009c <\.c3>:
+1000009c:	81 82 00 0c 	l       r12,12\(r2\)
+100000a0:	90 41 00 14 	st      r2,20\(r1\)
+100000a4:	80 0c 00 00 	l       r0,0\(r12\)
+100000a8:	80 4c 00 04 	l       r2,4\(r12\)
+100000ac:	7c 09 03 a6 	mtctr   r0
+100000b0:	4e 80 04 20 	bctr
+100000b4:	00 00 00 00 	\.long 0x0
+100000b8:	00 0c 80 00 	\.long 0xc8000
+100000bc:	00 00 00 00 	\.long 0x0
Index: ld/testsuite/ld-powerpc/aix-glink-2-64.dd
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-glink-2-64.dd	2009-03-10 13:51:47.000000000 +0000
@@ -0,0 +1,73 @@
+
+tmpdir/aix64-glink-2:     file format aix5coff64-rs6000
+
+
+Disassembly of section \.text:
+
+0000000010000000 <\.b1>:
+    10000000:	60 00 00 00 	nop
+
+0000000010000004 <\.b2>:
+    10000004:	60 00 00 00 	nop
+
+0000000010000008 <\.b3>:
+    10000008:	60 00 00 00 	nop
+
+000000001000000c <\.main>:
+    1000000c:	48 00 f1 03 	bla     f100 <.*>
+    10000010:	48 00 00 21 	bl      10000030 <\.a2>
+    10000014:	48 00 00 45 	bl      10000058 <\.a3>
+    10000018:	4b ff ff e9 	bl      10000000 <\.b1>
+    1000001c:	4b ff ff e9 	bl      10000004 <\.b2>
+    10000020:	4b ff ff e9 	bl      10000008 <\.b3>
+    10000024:	48 00 f5 03 	bla     f500 <.*>
+    10000028:	48 00 00 59 	bl      10000080 <\.c2>
+    1000002c:	48 00 00 7d 	bl      100000a8 <\.c3>
+
+0000000010000030 <\.a2>:
+    10000030:	e9 82 00 00 	ld      r12,0\(r2\)
+    10000034:	f8 41 00 28 	std     r2,40\(r1\)
+    10000038:	e8 0c 00 00 	ld      r0,0\(r12\)
+    1000003c:	e8 4c 00 08 	ld      r2,8\(r12\)
+    10000040:	7c 09 03 a6 	mtctr   r0
+    10000044:	4e 80 04 20 	bctr
+    10000048:	00 00 00 00 	\.long 0x0
+    1000004c:	00 0c a0 00 	\.long 0xca000
+    10000050:	00 00 00 00 	\.long 0x0
+    10000054:	00 00 00 18 	\.long 0x18
+
+0000000010000058 <\.a3>:
+    10000058:	e9 82 00 08 	ld      r12,8\(r2\)
+    1000005c:	f8 41 00 28 	std     r2,40\(r1\)
+    10000060:	e8 0c 00 00 	ld      r0,0\(r12\)
+    10000064:	e8 4c 00 08 	ld      r2,8\(r12\)
+    10000068:	7c 09 03 a6 	mtctr   r0
+    1000006c:	4e 80 04 20 	bctr
+    10000070:	00 00 00 00 	\.long 0x0
+    10000074:	00 0c a0 00 	\.long 0xca000
+    10000078:	00 00 00 00 	\.long 0x0
+    1000007c:	00 00 00 18 	\.long 0x18
+
+0000000010000080 <\.c2>:
+    10000080:	e9 82 00 10 	ld      r12,16\(r2\)
+    10000084:	f8 41 00 28 	std     r2,40\(r1\)
+    10000088:	e8 0c 00 00 	ld      r0,0\(r12\)
+    1000008c:	e8 4c 00 08 	ld      r2,8\(r12\)
+    10000090:	7c 09 03 a6 	mtctr   r0
+    10000094:	4e 80 04 20 	bctr
+    10000098:	00 00 00 00 	\.long 0x0
+    1000009c:	00 0c a0 00 	\.long 0xca000
+    100000a0:	00 00 00 00 	\.long 0x0
+    100000a4:	00 00 00 18 	\.long 0x18
+
+00000000100000a8 <\.c3>:
+    100000a8:	e9 82 00 18 	ld      r12,24\(r2\)
+    100000ac:	f8 41 00 28 	std     r2,40\(r1\)
+    100000b0:	e8 0c 00 00 	ld      r0,0\(r12\)
+    100000b4:	e8 4c 00 08 	ld      r2,8\(r12\)
+    100000b8:	7c 09 03 a6 	mtctr   r0
+    100000bc:	4e 80 04 20 	bctr
+    100000c0:	00 00 00 00 	\.long 0x0
+    100000c4:	00 0c a0 00 	\.long 0xca000
+    100000c8:	00 00 00 00 	\.long 0x0
+    100000cc:	00 00 00 18 	\.long 0x18
Index: ld/testsuite/ld-powerpc/aix-weak-1a.s
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-weak-1a.s	2009-03-10 13:51:47.000000000 +0000
@@ -0,0 +1,24 @@
+	.comm	a,4
+	.comm	b,4
+	.globl	c
+	.csect	c[RW],2
+c:
+	.long	0x11111111
+	.weak	d
+	.csect	d[RW],2
+d:
+	.long	0x22222222
+
+	# Same again, with weak common symbols
+	.weak	e
+	.comm	e,4
+	.weak	f
+	.comm	f,4
+	.globl	g
+	.csect	g[RW],2
+g:
+	.long	0x33333333
+	.weak	h
+	.csect	h[RW],2
+h:
+	.long	0x44444444
Index: ld/testsuite/ld-powerpc/aix-weak-1b.s
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-weak-1b.s	2009-03-10 13:51:47.000000000 +0000
@@ -0,0 +1,24 @@
+	.globl	a
+	.csect	a[RW],2
+a:
+	.long	0x55555555
+	.weak	b
+	.csect	b[RW],2
+b:
+	.long	0x66666666
+	.comm	c,4
+	.comm	d,4
+
+	# Same again, with weak common symbols
+	.globl	e
+	.csect	e[RW],2
+e:
+	.long	0x77777777
+	.weak	f
+	.csect	f[RW],2
+f:
+	.long	0x88888888
+	.weak	g
+	.comm	g,4
+	.weak	h
+	.comm	h,4
Index: ld/testsuite/ld-powerpc/aix-weak-1-rel.hd
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-weak-1-rel.hd	2009-03-10 13:51:47.000000000 +0000
@@ -0,0 +1,12 @@
+.*
+
+Sections:
+Idx Name * Size * VMA * LMA * File off *Algn
+ *0 \.text * 0+00 * 0+00 * 0+00 * [^ ]+ * 2\*\*2
+ *ALLOC, LOAD, CODE
+ *1 \.data * 0+20 * 0+00 * 0+00 * [^ ]+ * 2\*\*3
+ *CONTENTS, ALLOC, LOAD, DATA
+# Should only have 3 three common symbols.
+ *2 \.bss  * 0+0c * 0+20 * 0+20 * [^ ]+ * 2\*\*3
+ *ALLOC
+#pass
Index: ld/testsuite/ld-powerpc/aix-weak-1-rel.nd
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-weak-1-rel.nd	2009-03-10 13:51:47.000000000 +0000
@@ -0,0 +1,25 @@
+# Comments are (aix-weak-1a.s type) wins over/loses to (aix-weak-1b.s type)
+# (strong common) loses to (strong data)
+0+10 d a
+0+10 D a
+# (strong common) wins over (weak data)
+0+20 B b
+0+14 d b
+# (strong data) wins over (strong common)
+0+00 d c
+0+00 D c
+# (weak data) loses to (strong common)
+0+04 d d
+0+28 B d
+# (weak common) loses to (strong data)
+0+18 d e
+0+18 D e
+# (weak common) wins over (weak data)
+0+24 W f
+0+1c d f
+# (strong data) wins over (weak common)
+0+08 d g
+0+08 D g
+# (weak data) wins over (weak common)
+0+0c d h
+0+0c W h
Index: ld/testsuite/ld-powerpc/aix-weak-1-dso.hd
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-weak-1-dso.hd	2009-03-10 13:51:47.000000000 +0000
@@ -0,0 +1,12 @@
+.*
+
+Sections:
+Idx Name * Size * VMA * LMA * File off *Algn
+ *0 \.text * 0+00 * 0*10000000 * 0*10000000 * [^ ]+ * 2\*\*2
+ *ALLOC, LOAD, CODE
+ *1 \.data * 0+20 * 0*10000000 * 0*10000000 * [^ ]+ * 2\*\*3
+ *CONTENTS, ALLOC, LOAD, DATA
+# Should only have 3 three common symbols.
+ *2 \.bss  * 0+0c * 0*10000020 * 0*10000020 * [^ ]+ * 2\*\*3
+ *ALLOC
+#pass
Index: ld/testsuite/ld-powerpc/aix-weak-1-dso.nd
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-weak-1-dso.nd	2009-03-10 13:51:47.000000000 +0000
@@ -0,0 +1,25 @@
+# Comments are (aix-weak-1a.s type) wins over/loses to (aix-weak-1b.s type)
+# (strong common) loses to (strong data)
+0*10000010 d a
+0*10000010 D a
+# (strong common) wins over (weak data)
+0*10000020 B b
+0*10000014 d b
+# (strong data) wins over (strong common)
+0*10000000 d c
+0*10000000 D c
+# (weak data) loses to (strong common)
+0*10000004 d d
+0*10000028 B d
+# (weak common) loses to (strong data)
+0*10000018 d e
+0*10000018 D e
+# (weak common) wins over (weak data)
+0*10000024 W f
+0*1000001c d f
+# (strong data) wins over (weak common)
+0*10000008 d g
+0*10000008 D g
+# (weak data) wins over (weak common)
+0*1000000c d h
+0*1000000c W h
Index: ld/testsuite/ld-powerpc/aix-weak-1-dso.dnd
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-weak-1-dso.dnd	2009-03-10 13:51:47.000000000 +0000
@@ -0,0 +1,17 @@
+# Comments are (aix-weak-1a.s type) wins over/loses to (aix-weak-1b.s type)
+# (strong common) loses to (strong data)
+0*10000010 D a
+# (strong common) wins over (weak data)
+0*10000020 B b
+# (strong data) wins over (strong common)
+0*10000000 D c
+# (weak data) loses to (strong common)
+0*10000028 B d
+# (weak common) loses to (strong data)
+0*10000018 D e
+# (weak common) wins over (weak data)
+0*10000024 W f
+# (strong data) wins over (weak common)
+0*10000008 D g
+# (weak data) wins over (weak common)
+0*1000000c W h
Index: ld/testsuite/ld-powerpc/aix-weak-1.ex
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-weak-1.ex	2009-03-10 13:51:47.000000000 +0000
@@ -0,0 +1,8 @@
+a
+b
+c
+d
+e
+f
+g
+h
Index: ld/testsuite/ld-powerpc/aix-weak-2a.s
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-weak-2a.s	2009-03-10 13:51:47.000000000 +0000
@@ -0,0 +1,21 @@
+	.weak	c1
+	c1 = 0xcccc1111
+	.weak	c2
+	c2 = 0xcccc2222
+	.globl	c3
+	c3 = 0xcccc3333
+	.globl	c4
+	c4 = 0xcccc4444
+
+	.weak	d1
+	d1 = 0xffff1111
+	.weak	d2
+	d2 = 0xffff2222
+	.globl	d3
+	.csect	d3[DS]
+d3:
+	.long	0xffff3333
+	.globl	d4
+	.csect	d4[DS]
+d4:
+	.long	0xffff4444
Index: ld/testsuite/ld-powerpc/aix-weak-2a.ex
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-weak-2a.ex	2009-03-10 13:51:47.000000000 +0000
@@ -0,0 +1,8 @@
+c1
+c2
+c3
+c4
+d1
+d2
+d3
+d4
Index: ld/testsuite/ld-powerpc/aix-weak-2a.nd
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-weak-2a.nd	2009-03-10 13:51:47.000000000 +0000
@@ -0,0 +1,8 @@
+0*cccc1111 W c1
+0*cccc2222 W c2
+0*cccc3333 A c3
+0*cccc4444 A c4
+0*ffff1111 W d1
+0*ffff2222 W d2
+0*10000000 D d3
+0*10000004 D d4
Index: ld/testsuite/ld-powerpc/aix-weak-2b.s
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-weak-2b.s	2009-03-10 13:51:47.000000000 +0000
@@ -0,0 +1,21 @@
+	.globl	c1
+	c1 = 0xdddd1111
+	.weak	c2
+	c2 = 0xdddd2222
+	.globl	c3
+	c3 = 0xdddd3333
+	.weak	c4
+	c4 = 0xdddd4444
+
+	.globl	d1
+	.csect	d1[DS]
+d1:
+	.long	0xeeee1111
+	.weak	d2
+	d2 = 0xeeee2222
+	.globl	d3
+	.csect	d3[DS]
+d3:
+	.long	0xeeee3333
+	.weak	d4
+	d4 = 0xeeee4444
Index: ld/testsuite/ld-powerpc/aix-weak-2b.nd
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-weak-2b.nd	2009-03-10 13:51:47.000000000 +0000
@@ -0,0 +1,8 @@
+0*dddd1111 A c1
+0*dddd2222 W c2
+0*dddd3333 A c3
+0*dddd4444 W c4
+0*10000000 D d1
+0*eeee2222 W d2
+0*10000004 D d3
+0*eeee4444 W d4
Index: ld/testsuite/ld-powerpc/aix-weak-2c.s
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-weak-2c.s	2009-03-10 13:51:47.000000000 +0000
@@ -0,0 +1,11 @@
+	.globl	foo
+	.csect	foo[DS]
+foo:
+	.long	c1
+	.long	c2
+	.long	c3
+	.long	c4
+	.long	d1
+	.long	d2
+	.long	d3
+	.long	d4
Index: ld/testsuite/ld-powerpc/aix-weak-2c.ex
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-weak-2c.ex	2009-03-10 13:51:47.000000000 +0000
@@ -0,0 +1,1 @@
+foo
Index: ld/testsuite/ld-powerpc/aix-weak-2c.nd
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-weak-2c.nd	2009-03-10 13:51:47.000000000 +0000
@@ -0,0 +1,10 @@
+0*dddd1111 C c1
+0*cccc2222 C c2
+0*cccc3333 C c3
+0*cccc4444 C c4
+ *         U d1
+0*ffff2222 C d2
+ *         U d3
+ *         U d4
+0*10000000 d foo
+0*10000000 D foo
Index: ld/testsuite/ld-powerpc/aix-weak-2c.od
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-weak-2c.od	2009-03-10 13:51:47.000000000 +0000
@@ -0,0 +1,13 @@
+
+.*
+
+DYNAMIC RELOCATION RECORDS
+OFFSET * TYPE * VALUE 
+0*10000010 R_POS * d1
+0*10000018 R_POS * d3
+0*1000001c R_POS * d4
+
+
+Contents of section \.data:
+ 0*10000000 dddd1111 cccc2222 cccc3333 cccc4444  .*
+ 0*10000010 00000000 ffff2222 00000000 00000000  .*
Index: ld/testsuite/ld-powerpc/aix-weak-3a.s
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-weak-3a.s	2009-03-10 13:51:47.000000000 +0000
@@ -0,0 +1,8 @@
+	.globl	x1
+	x1 = 0x11223344
+	.globl	x2
+	x2 = 0x55667788
+	.globl	x3
+	.csect	x3[RW]
+x3:
+	.long	42
Index: ld/testsuite/ld-powerpc/aix-weak-3a.ex
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-weak-3a.ex	2009-03-10 13:51:47.000000000 +0000
@@ -0,0 +1,3 @@
+x1
+x2
+x3
Index: ld/testsuite/ld-powerpc/aix-weak-3b.s
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-weak-3b.s	2009-03-10 13:51:47.000000000 +0000
@@ -0,0 +1,30 @@
+	.globl	x1
+	.csect	x1[RW]
+x1:
+	.long	0x0102
+
+	.weak	x2
+	.csect	x2[RW]
+x2:
+	.long	0x0304
+
+	.toc
+Tx1:
+	.tc	x1[TC],x1
+Tx2:
+	.tc	x2[TC],x2
+Tx3:
+	.tc	x3[TC],x3
+
+	.globl	.main
+	.csect	.main[PR]
+.main:
+	.if     size == 32
+	lwz     1,Tx1(2)
+	lwz     1,Tx2(2)
+	lwz     1,Tx3(2)
+	.else
+	ld      1,Tx1(2)
+	ld      1,Tx2(2)
+	ld      1,Tx3(2)
+	.endif
Index: ld/testsuite/ld-powerpc/aix-weak-3b.ex
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-weak-3b.ex	2009-03-10 13:51:47.000000000 +0000
@@ -0,0 +1,1 @@
+y
Index: ld/testsuite/ld-powerpc/aix-weak-3-32.d
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-weak-3-32.d	2009-03-10 13:51:47.000000000 +0000
@@ -0,0 +1,5 @@
+#name: Weak test 3 (main, static) (32-bit)
+#source: aix-weak-3b.s
+#as: -a32 --defsym size=32
+#ld: -b32 -e.main -bnoautoimp tmpdir/aix-weak-3a.so
+#error: .*multiple definition of `x1'\n[^\n]*first defined here
Index: ld/testsuite/ld-powerpc/aix-weak-3-32.dd
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-weak-3-32.dd	2009-03-10 13:51:47.000000000 +0000
@@ -0,0 +1,24 @@
+
+.*
+
+
+Disassembly of section \.data:
+
+20000000 <x1>:
+20000000:	00 00 01 02 	.*
+
+20000004 <x2>:
+20000004:	00 00 03 04 	.*
+
+20000008 <TOC>:
+20000008:	20 00 00 00 	.*
+			20000008: R_POS	x1\+.*
+
+2000000c <x2>:
+2000000c:	20 00 00 04 	.*
+			2000000c: R_POS	x2\+.*
+
+20000010 <x3>:
+20000010:	00 00 00 00 	.*
+			20000010: R_POS	x3
+20000014:	00 00 00 00 	.*
Index: ld/testsuite/ld-powerpc/aix-weak-3-64.d
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-weak-3-64.d	2009-03-10 13:51:47.000000000 +0000
@@ -0,0 +1,5 @@
+#name: Weak test 3 (main, static) (64-bit)
+#source: aix-weak-3b.s
+#as: -a64 --defsym size=64
+#ld: -b64 -e.main -bnoautoimp tmpdir/aix64-weak-3a.so
+#error: .*multiple definition of `x1'\n[^\n]*first defined here
Index: ld/testsuite/ld-powerpc/aix-weak-3-64.dd
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-weak-3-64.dd	2009-03-10 13:51:47.000000000 +0000
@@ -0,0 +1,26 @@
+
+.*
+
+
+Disassembly of section \.data:
+
+0000000020000000 <x1>:
+    20000000:	00 00 01 02 	.*
+
+0000000020000004 <x2>:
+    20000004:	00 00 03 04 	.*
+
+0000000020000008 <TOC>:
+    20000008:	00 00 00 00 	.*
+			20000008: R_POS_64	x1\+.*
+    2000000c:	20 00 00 00 	.*
+
+0000000020000010 <x2>:
+    20000010:	00 00 00 00 	.*
+			20000010: R_POS_64	x2\+.*
+    20000014:	20 00 00 04 	.*
+
+0000000020000018 <x3>:
+    20000018:	00 00 00 00 	.*
+			20000018: R_POS_64	x3
+    2000001c:	00 00 00 00 	.*
Index: ld/testsuite/ld-powerpc/aix52.exp
===================================================================
--- ld/testsuite/ld-powerpc/aix52.exp	2009-03-10 13:49:33.000000000 +0000
+++ ld/testsuite/ld-powerpc/aix52.exp	2009-03-10 13:51:47.000000000 +0000
@@ -124,6 +124,64 @@ set aix52tests {
      {{objdump -dS aix-lineno-1b.dd} {nm {} aix-lineno-1b.nd}}
      "aix-lineno-1b.exe"}
 
+    {"Glink test 2 (part a)" "-shared -bE:aix-glink-2a.ex"
+     "" {aix-glink-2a.s}
+     {}
+     "aix-glink-2a.so"}
+
+    {"Glink test 2 (part b)" "-r"
+     "" {aix-glink-2b.s}
+     {}
+     "aix-glink-2b.ro"}
+
+    {"Glink test 2 (part c)" "-shared -bE:aix-glink-2c.ex"
+     "" {aix-glink-2c.s}
+     {}
+     "aix-glink-2c.so"}
+
+    {"Glink test 2"
+     "-e.main tmpdir/aix-glink-2a.so tmpdir/aix-glink-2b.ro tmpdir/aix-glink-2c.so"
+     "" {aix-glink-2d.s}
+     {{objdump -d aix-glink-2-SIZE.dd}}
+     "aix-glink-2"}
+
+    {"Weak test 1 (rel)" "-r"
+     "" {aix-weak-1a.s aix-weak-1b.s}
+     {{nm {} aix-weak-1-rel.nd} {objdump -h aix-weak-1-rel.hd}}
+     "aix-weak-1.o"}
+
+    {"Weak test 1 (shared, nogc)" "-shared -bE:aix-weak-1.ex -bnogc"
+     "" {aix-weak-1a.s aix-weak-1b.s}
+     {{nm {} aix-weak-1-dso.nd} {objdump -h aix-weak-1-dso.hd}
+      {nm -D aix-weak-1-dso.dnd}}
+     "aix-weak-1-nogc.so"}
+
+    {"Weak test 2 (library 1)" "-shared -bE:aix-weak-2a.ex"
+     "" {aix-weak-2a.s}
+     {{nm -D aix-weak-2a.nd}}
+     "aix-weak-2a.so"}
+
+    {"Weak test 2 (library 2)" "-shared -bE:aix-weak-2a.ex"
+     "" {aix-weak-2b.s}
+     {{nm -D aix-weak-2b.nd}}
+     "aix-weak-2b.so"}
+
+    {"Weak test 2 (main library)"
+     "-shared -bE:aix-weak-2c.ex tmpdir/aix-weak-2a.so tmpdir/aix-weak-2b.so"
+     "" {aix-weak-2c.s}
+     {{nm {} aix-weak-2c.nd} {objdump {-sj.data -R} aix-weak-2c.od}}
+     "aix-weak-2c.so"}
+
+    {"Weak test 3 (library)" "-shared -bE:aix-weak-3a.ex"
+     "" {aix-weak-3a.s}
+     {}
+     "aix-weak-3a.so"}
+
+    {"Weak test 3 (main, dynamic)" "-e.main tmpdir/aix-weak-3a.so"
+     "" {aix-weak-3b.s}
+     {{objdump -Dzrj.data aix-weak-3-SIZE.dd}}
+     "aix-weak-3"}
+
     {"TOC test 1" "-shared -bE:aix-toc-1.ex"
      "" {aix-toc-1a.s aix-toc-1b.s}
      {{objdump -dr aix-toc-1-SIZE.dd}}
@@ -136,3 +194,6 @@ foreach test $aix52tests {
 	run_aix_test 64 $name $ldopts $asopts $sources $tools $output
     }
 }
+
+run_dump_test "aix-weak-3-32"
+run_dump_test "aix-weak-3-64"



More information about the Binutils mailing list