public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [0/21] Add support for AIX 6
@ 2009-03-10 13:58 Richard Sandiford
  2009-03-10 14:00 ` [1/21] Fix handling of archive tests Richard Sandiford
                   ` (21 more replies)
  0 siblings, 22 replies; 50+ messages in thread
From: Richard Sandiford @ 2009-03-10 13:58 UTC (permalink / raw)
  To: binutils

This series of patches adds support for AIX 6.  In truth, only one patch
is actually specific to version 6; the rest fix problems with the existing
AIX 4 and AIX 5 code.  The aim of many of the patches is to resolve the
failures mentioned in the following libtool message:

*** Warning: the GNU linker, at least up to release 2.9.1, is reported
*** to be unable to reliably create shared libraries on AIX.
*** Therefore, libtool is disabling shared libraries support.  If you
*** really care for shared libraries, you may want to modify your PATH
*** so that a non-GNU linker is found, and then restart.

With some libtool and gcc patches, a cross toolchain produced good
GCC testresults, and we've been able to use it in-house to build our
applications.  (The build includes both shared libraries and executables.)
I'm sure there are other issues that I haven't fixed here though.

One of the big issues was: how should we handle archives and symbol
resolution?  On AIX, it is possible to link dynamically against both
shared objects _and_ archives that contain shared objects.  The latter
are more commonly used.  For example, whereas GNU systems have a separate
shared C library (libc.so.X) and static-only archive (libc_nonshared.a),
AIX has a single libc.a that contains both the shared object and the
static-only objects.

This causes problems with things like:

   gnu-ld bar.o -lfoo frob.o

in cases where the user is expecting "foo" to be a shared library.
The executable should link dynamically against foo regardless of
whether foo appears to be needed; you would use:

   gnu-ld bar.o --as-needed -lfoo --no-as-needed frob.o

if you wanted "foo" to behave more like an archive.  However, if shared
library "foo" _is_ an archive, the first command behaves like the second.
You would need:

   gnu-ld bar.o --whole-archive -lfoo --no-whole-archive frob.o

to get the normal ELF behaviour.

This means, for example, that:

   gnu-ld ... -lpthread ... objects ...

fails with a shared libpthread.a, but:

   gnu-ld ... objects ... -lpthread ...

works.

Now the AIX linker appears to apply something like --whole-archive
semantics to _all_ archives.  So, for example:

----------------------------------------------------------------------
#!/bin/bash
set -eu
cat <<EOF > a.c
int x = 1;
EOF
cat <<EOF > b.c
int x = 2;
int main (void) { return x; }
EOF
gcc -c a.c -o a.o
rm -f libfoo.a
ar rc libfoo.a a.o
gcc -L. -lfoo b.c
./a.out || echo $?
rm -f a.out a.c a.o b.c libfoo.a
----------------------------------------------------------------------

prints "2" on your typical ELF target, and on AIX when using the
GNU linker.  But when using the native AIX linker it produces:

----------------------------------------------------------------------
ld: 0711-224 WARNING: Duplicate symbol: x
ld: 0711-345 Use the -bloadmap or -bnoquiet option to obtain more information.
1
----------------------------------------------------------------------

This means that "ld -lpthread ..." works as expected when using the
native linker.  However, the knock-on conseequences might surprise some
users if we did the same thing in the GNU linker.

Also, when resolving symbols, the native linker does not care whether
a definition comes from a direct relocatable object, a direct shared
object, or an archive member.  Strong definitions in shared objects
can override weak definitions in the main objects.  If shared object A
comes before relocatable object B, a weak definition in A trumps a weak
definition in B.  A strong definition in A also trumps a strong
definition in B, albeit with a multiple-definition warning.

I couldn't decide whether to make the GNU linker behave like the AIX
linker or not.  In the end, I left things as they are for no other
reason than it's what we've always done.

All patches in the series were tested against the binutils and
gcc testsuites.

As far as copyright goes: I did this work for Transitive after
they were bought by IBM, and my name has been added to the IBM
copyright assignment.  This work is therefore covered by that.

Richard

^ permalink raw reply	[flat|nested] 50+ messages in thread

* [1/21] Fix handling of archive tests
  2009-03-10 13:58 [0/21] Add support for AIX 6 Richard Sandiford
@ 2009-03-10 14:00 ` Richard Sandiford
  2009-03-12 16:15   ` Nick Clifton
  2009-03-10 14:01 ` [2/21] Add support for AIX 6 Richard Sandiford
                   ` (20 subsequent siblings)
  21 siblings, 1 reply; 50+ messages in thread
From: Richard Sandiford @ 2009-03-10 14:00 UTC (permalink / raw)
  To: binutils

I was using run_ld_link_tests to create an archive and noticed that
it ran both ar _and_ ld.  It runs ld first, so everything works out
OK in the end, but it's easy to fix.

I would have applied that bit as obvious.  However, I also wanted
to be able to pass specific flags to "ar".  The "ld_options" field is
currently unused for ar tests, so it seemed natural to overload that.
AFAICT, no existing ar tests currently set this field to a nonempty string.

OK to install?

Richard


ld/testsuite/
	* lib/ld-lib.exp (ar_simple_create): Add an "aropts" parameter.
	(run_ld_link_tests): Treat the second list element as "ar" options
	when creating an archive.  Don't run the linker in this case.
	(run_cc_link_tests): Likewise.

Index: ld/testsuite/lib/ld-lib.exp
===================================================================
--- ld/testsuite/lib/ld-lib.exp	2009-03-10 13:40:02.000000000 +0000
+++ ld/testsuite/lib/ld-lib.exp	2009-03-10 13:42:09.000000000 +0000
@@ -1095,10 +1095,10 @@ proc file_contents { filename } {
 
 # Create an archive using ar
 #
-proc ar_simple_create { ar target objects } {
+proc ar_simple_create { ar aropts target objects } {
     remote_file host delete $target
 
-    set exec_output [run_host_cmd "$ar" "rc $target $objects"]
+    set exec_output [run_host_cmd "$ar" "$aropts rc $target $objects"]
     set exec_output [prune_warnings $exec_output]
 
     if [string match "" $exec_output] then {
@@ -1111,7 +1111,7 @@ proc ar_simple_create { ar target object
 
 # List contains test-items with 3 items followed by 2 lists, one item and
 # one optional item:
-# 0:name 1:ld options 2:assembler options
+# 0:name 1:ld/ar options 2:assembler options
 # 3:filenames of assembler files 4: action and options. 5: name of output file
 # 6:compiler flags (optional)
 #
@@ -1178,14 +1178,14 @@ proc run_ld_link_tests { ldtests } {
 	    continue
 	}
 
-	if [regexp ".*a$" $binfile] then {
-	    if ![ar_simple_create $ar $binfile "$objfiles"] {
+	if { [regexp ".*a$" $binfile] } {
+	    if { ![ar_simple_create $ar $ld_options $binfile "$objfiles"] } {
 		fail $testname
 		set failed 1
 	    } else {
 		set failed 0
 	    }
-	} elseif ![ld_simple_link $ld $binfile "-L$srcdir/$subdir $ld_options $objfiles"] {
+	} elseif { ![ld_simple_link $ld $binfile "-L$srcdir/$subdir $ld_options $objfiles"] } {
 	    fail $testname
 	    set failed 1
 	} else {
@@ -1434,7 +1434,7 @@ proc run_ld_link_exec_tests { targets_to
 # List contains test-items with 3 items followed by 2 lists, one item and
 # one optional item:
 #  0:name
-#  1:link options
+#  1:ld or ar options
 #  2:compile options
 #  3:filenames of source files
 #  4:action and options.
@@ -1495,14 +1495,14 @@ proc run_cc_link_tests { ldtests } {
 	    set cc_cmd $CC
 	}
 
-	if [regexp ".*a$" $binfile] then {
-	    if ![ar_simple_create $ar $binfile "$objfiles"] {
+	if { [regexp ".*a$" $binfile] } {
+	    if { ![ar_simple_create $ar $ldflags $binfile "$objfiles"] } {
 		fail $testname
 		set failed 1
 	    } else {
 		set failed 0
 	    }
-	} elseif ![ld_simple_link $cc_cmd $binfile "-L$srcdir/$subdir $ldflags $objfiles"] {
+	} elseif { ![ld_simple_link $cc_cmd $binfile "-L$srcdir/$subdir $ldflags $objfiles"] } {
 	    fail $testname
 	    set failed 1
 	} else {

^ permalink raw reply	[flat|nested] 50+ messages in thread

* [2/21] Add support for AIX 6
  2009-03-10 13:58 [0/21] Add support for AIX 6 Richard Sandiford
  2009-03-10 14:00 ` [1/21] Fix handling of archive tests Richard Sandiford
@ 2009-03-10 14:01 ` Richard Sandiford
  2009-03-12 16:17   ` Nick Clifton
  2009-03-10 14:04 ` [3/21] Keep .text, .data and .bss on AIX Richard Sandiford
                   ` (19 subsequent siblings)
  21 siblings, 1 reply; 50+ messages in thread
From: Richard Sandiford @ 2009-03-10 14:01 UTC (permalink / raw)
  To: binutils

This second patch simply treats AIX 6 (and later) like AIX 5 instead
of AIX 4.

OK to install?

Richard


bfd/
	* config.bfd: Treat AIX 6+ in the same way as AIX 5.
	* configure.in: Likewise.
	* configure: Regenerate.

binutils/
	* configure.tgt: Extend AIX 5 behavior to AIX 6 and above.
	* configure.in: Likewise.
	* configure: Regenerate.

gas/
	* configure.tgt: Extend AIX 5 behavior to AIX 6 and above.
	* configure.in: Likewise.
	* configure: Regenerate.

ld/
	* configure.tgt: Extend AIX 5 behavior to AIX 6 and above.

Index: bfd/config.bfd
===================================================================
--- bfd/config.bfd	2009-03-10 13:38:53.000000000 +0000
+++ bfd/config.bfd	2009-03-10 13:42:17.000000000 +0000
@@ -1081,14 +1081,14 @@ case "${targ}" in
     want64=true
     ;;
 #endif
-  powerpc-*-aix5*)
+  powerpc-*-aix[5-9]*)
     targ_cflags=-DAIX_WEAK_SUPPORT
     targ_defvec=rs6000coff_vec
     targ_selvecs="aix5coff64_vec"
     want64=true
     ;;
 #ifdef BFD64
-  powerpc64-*-aix5*)
+  powerpc64-*-aix[5-9]*)
     targ_cflags=-DAIX_WEAK_SUPPORT
     targ_defvec=aix5coff64_vec
     targ_selvecs="rs6000coff_vec"
Index: bfd/configure.in
===================================================================
--- bfd/configure.in	2009-03-10 13:38:53.000000000 +0000
+++ bfd/configure.in	2009-03-10 13:42:17.000000000 +0000
@@ -391,7 +391,9 @@ changequote([,])dnl
   rs6000-*-lynx*)
   	COREFILE=lynx-core.lo
 	;;
-  rs6000-*-aix5.* | powerpc-*-aix5.*)
+changequote(,)dnl
+  rs6000-*-aix[5-9].* | powerpc-*-aix[5-9].*)
+changequote([,])dnl
         COREFILE=rs6000-core.lo
 	COREFLAG="$COREFLAG -DAIX_5_CORE -DAIX_CORE_DUMPX_CORE"
 	;;
Index: binutils/configure.tgt
===================================================================
--- binutils/configure.tgt	2009-03-10 13:38:53.000000000 +0000
+++ binutils/configure.tgt	2009-03-10 13:42:17.000000000 +0000
@@ -9,7 +9,7 @@
 # targ_emul_vector	name of vector to use
 
 case "${targ}" in
-    powerpc-*-aix5* | rs6000-*-aix5*)
+    powerpc-*-aix[5-9]* | rs6000-*-aix[5-9]*)
 	targ_emul=aix 
 	targ_emul_vector=bin_aix5_emulation 
         ;;
Index: binutils/configure.in
===================================================================
--- binutils/configure.in	2009-03-10 13:38:53.000000000 +0000
+++ binutils/configure.in	2009-03-10 13:42:17.000000000 +0000
@@ -330,7 +330,9 @@ changequote(,)dnl
 	powerpc*-aix5.[01])
 changequote([,])dnl
 	  ;;
-	powerpc*-aix5.*)
+changequote(,)dnl
+	powerpc*-aix[5-9].*)
+changequote([,])dnl
 	  OBJDUMP_DEFS="-DAIX_WEAK_SUPPORT"
 	  ;;
 	powerpc*-*-pe* | powerpc*-*-cygwin*)
Index: gas/configure.tgt
===================================================================
--- gas/configure.tgt	2009-03-10 13:38:53.000000000 +0000
+++ gas/configure.tgt	2009-03-10 13:42:17.000000000 +0000
@@ -320,7 +320,7 @@ case ${generic_target} in
   ppc-*-pe | ppc-*-cygwin*)		fmt=coff em=pe ;;
   ppc-*-winnt*)				fmt=coff em=pe ;;
   ppc-*-aix5.[01])			fmt=coff em=aix5 ;;
-  ppc-*-aix5.*)				fmt=coff em=aix5 ;;
+  ppc-*-aix[5-9].*)			fmt=coff em=aix5 ;;
   ppc-*-aix*)				fmt=coff ;;
   ppc-*-beos*)				fmt=coff ;;
   ppc-*-*n*bsd* | ppc-*-elf*)		fmt=elf ;;
Index: gas/configure.in
===================================================================
--- gas/configure.in	2009-03-10 13:38:53.000000000 +0000
+++ gas/configure.in	2009-03-10 13:42:17.000000000 +0000
@@ -143,7 +143,9 @@ for this_target in $target $canon_target
 	AC_MSG_ERROR(Unknown vendor for mips-bsd configuration.)
 	;;
 
-      ppc-*-aix5.*)
+changequote(,)dnl
+      ppc-*-aix[5-9].*)
+changequote([,])dnl
 	AC_DEFINE(AIX_WEAK_SUPPORT, 1,
 		  [Define if using AIX 5.2 value for C_WEAKEXT.])
 	;;
Index: ld/configure.tgt
===================================================================
--- ld/configure.tgt	2009-03-10 13:38:53.000000000 +0000
+++ ld/configure.tgt	2009-03-10 13:42:17.000000000 +0000
@@ -487,12 +487,12 @@ powerpc-*-netware*)	targ_emul=ppcnw ;;
 powerpcle-*-pe)         targ_emul=ppcpe ;;
 powerpcle-*-winnt*)     targ_emul=ppcpe ;;
 powerpcle-*-cygwin*)    targ_emul=ppcpe ;;
-powerpc-*-aix5*)	targ_emul=aix5ppc ;;
+powerpc-*-aix[5-9]*)	targ_emul=aix5ppc ;;
 powerpc-*-aix*)		targ_emul=aixppc ;;
 powerpc-*-beos*)	targ_emul=aixppc ;;
 powerpc-*-windiss*)	targ_emul=elf32ppcwindiss ;;
 powerpc-*-lynxos*)	targ_emul=ppclynx ;;
-rs6000-*-aix5*)		targ_emul=aix5rs6 ;;
+rs6000-*-aix[5-9]*)	targ_emul=aix5rs6 ;;
 rs6000-*-aix*)		targ_emul=aixrs6
 			;;
 s390x-*-linux*)         targ_emul=elf64_s390

^ permalink raw reply	[flat|nested] 50+ messages in thread

* [3/21] Keep .text, .data and .bss on AIX
  2009-03-10 13:58 [0/21] Add support for AIX 6 Richard Sandiford
  2009-03-10 14:00 ` [1/21] Fix handling of archive tests Richard Sandiford
  2009-03-10 14:01 ` [2/21] Add support for AIX 6 Richard Sandiford
@ 2009-03-10 14:04 ` Richard Sandiford
  2009-03-12 16:36   ` Nick Clifton
  2009-03-10 14:05 ` [4/21] Fix o_cputype for 64-bit XCOFF objects Richard Sandiford
                   ` (18 subsequent siblings)
  21 siblings, 1 reply; 50+ messages in thread
From: Richard Sandiford @ 2009-03-10 14:04 UTC (permalink / raw)
  To: binutils

We currently strip empty output sections on AIX, just like we do on ELF.
However, the AIX loader complains if a shared library contains no .text,
.data or .bss section (that is, if the SNtext, SNdata and SNbss fields
are 0 rather than valid section indices).

This patch makes sure we keep these three sections.  OK to install?

Richard


ld/
	* emultempl/aix.em (gld${EMULATION_NAME}_before_allocation): Mark
	.text, .data and .bss output sections as SEC_KEEP.

ld/testsuite/
	* ld-powerpc/aix-core-sec-1.s, ld-powerpc/aix-core-sec-1.ex,
	ld-powerpc/aix-core-sec-1.hd, ld-powerpc/aix-core-sec-2.s,
	ld-powerpc/aix-core-sec-2.ex, ld-powerpc/aix-core-sec-2.hd,
	ld-powerpc/aix-core-sec-3.s, ld-powerpc/aix-core-sec-3.ex,
	ld-powerpc/aix-core-sec-3.hd: New tests.
	* ld-powerpc/aix52.exp: New harness.

Index: ld/emultempl/aix.em
===================================================================
--- ld/emultempl/aix.em	2009-03-10 13:38:53.000000000 +0000
+++ ld/emultempl/aix.em	2009-03-10 13:43:04.000000000 +0000
@@ -616,7 +616,12 @@ gld${EMULATION_NAME}_before_allocation (
   struct export_symbol_list *el;
   char *libpath;
   asection *special_sections[XCOFF_NUMBER_OF_SPECIAL_SECTIONS];
-  int i;
+  static const char *const must_keep_sections[] = {
+    ".text",
+    ".data",
+    ".bss"
+  };
+  unsigned int i;
 
   /* Handle the import and export files, if any.  */
   for (fl = import_files; fl != NULL; fl = fl->next)
@@ -824,6 +829,19 @@ gld${EMULATION_NAME}_before_allocation (
 	}
     }
 
+  /* We must always have .text, .data and .bss output sections, so that
+     the header can refer to them.  The kernel refuses to load shared
+     objects that have missing sections.  */
+  for (i = 0; i < ARRAY_SIZE (must_keep_sections); i++)
+    {
+      asection *sec;
+
+      sec = bfd_get_section_by_name (link_info.output_bfd,
+				     must_keep_sections[i]);
+      if (sec)
+	sec->flags |= SEC_KEEP;
+    }
+
   before_allocation_default ();
 }
 
Index: ld/testsuite/ld-powerpc/aix-core-sec-1.s
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-core-sec-1.s	2009-03-10 13:43:04.000000000 +0000
@@ -0,0 +1,5 @@
+	.globl	foo
+	.csect	foo[RO]
+foo:
+	.long	0x12345678
+	.long	0xdeadbeef
Index: ld/testsuite/ld-powerpc/aix-core-sec-1.ex
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-core-sec-1.ex	2009-03-10 13:43:04.000000000 +0000
@@ -0,0 +1,1 @@
+foo
Index: ld/testsuite/ld-powerpc/aix-core-sec-1.hd
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-core-sec-1.hd	2009-03-10 13:43:04.000000000 +0000
@@ -0,0 +1,11 @@
+#...
+Sections:
+.*
+ * 0 * \.text * 0+8 .*
+ * CONTENTS, ALLOC, LOAD, CODE
+ * 1 * \.data * 0+0 .*
+ * ALLOC, LOAD, DATA
+ * 2 * \.bss * 0+0 .*
+ * ALLOC
+ * 3 * \.loader .*
+ * CONTENTS, ALLOC, LOAD
Index: ld/testsuite/ld-powerpc/aix-core-sec-2.s
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-core-sec-2.s	2009-03-10 13:43:04.000000000 +0000
@@ -0,0 +1,5 @@
+	.globl	foo
+	.csect	foo[RW]
+foo:
+	.long	0x12345678
+	.long	0xdeadbeef
Index: ld/testsuite/ld-powerpc/aix-core-sec-2.ex
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-core-sec-2.ex	2009-03-10 13:43:04.000000000 +0000
@@ -0,0 +1,1 @@
+foo
Index: ld/testsuite/ld-powerpc/aix-core-sec-2.hd
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-core-sec-2.hd	2009-03-10 13:43:04.000000000 +0000
@@ -0,0 +1,11 @@
+#...
+Sections:
+.*
+ * 0 * \.text * 0+0 .*
+ * ALLOC, LOAD, CODE
+ * 1 * \.data * 0+8 .*
+ * CONTENTS, ALLOC, LOAD, DATA
+ * 2 * \.bss * 0+0 .*
+ * ALLOC
+ * 3 * \.loader .*
+ * CONTENTS, ALLOC, LOAD
Index: ld/testsuite/ld-powerpc/aix-core-sec-3.s
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-core-sec-3.s	2009-03-10 13:43:04.000000000 +0000
@@ -0,0 +1,1 @@
+	.comm	foo,8
Index: ld/testsuite/ld-powerpc/aix-core-sec-3.ex
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-core-sec-3.ex	2009-03-10 13:43:04.000000000 +0000
@@ -0,0 +1,1 @@
+foo
Index: ld/testsuite/ld-powerpc/aix-core-sec-3.hd
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-core-sec-3.hd	2009-03-10 13:43:04.000000000 +0000
@@ -0,0 +1,11 @@
+#...
+Sections:
+.*
+ * 0 * \.text * 0+0 .*
+ * ALLOC, LOAD, CODE
+ * 1 * \.data * 0+0 .*
+ * ALLOC, LOAD, DATA
+ * 2 * \.bss * 0+8 .*
+ * ALLOC
+ * 3 * \.loader .*
+ * CONTENTS, ALLOC, LOAD
Index: ld/testsuite/ld-powerpc/aix52.exp
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix52.exp	2009-03-10 13:43:04.000000000 +0000
@@ -0,0 +1,89 @@
+# Expect script for AIX 5.2+ tests
+#   Copyright 2009 Free Software Foundation
+#
+# This file is part of the GNU Binutils.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+#
+
+if { ![istarget "powerpc*-*-aix\[5-9\]*"]
+     || [istarget "powerpc*-*-aix5.\[01\]*"] } {
+    return
+}
+
+# Run a run_link_tests-style test for AIX.  SIZE selects the target size
+# (32 or 64).  The other arguments are elements of a run_link_tests test.
+#
+# Make the following changes before running the test:
+#
+#    - Mention SIZE in the test name.
+#    - Add "-aSIZE --defsym size=SIZE" to the assembler options.
+#    - Add the source directory to any "-bI:" and "-bE:" linker options.
+#    - Add "-bSIZE" to the linker options.
+#    - Add "-XSIZE" to the archiver options.
+#    - Replace "SIZE" with SIZE in TOOLS.
+#    - When testing 64-bit targets:
+#      - Turn tmpdir/aix-* into tmpdir/aix64-*.
+#      - Turn tmpdir/libaix-* into tmpdir/libaix64-*.
+#      - Turn -laix* into -laix64*, to compensate for the above.
+proc run_aix_test { size name ldopts asopts sources tools output } {
+    global srcdir subdir
+
+    if { $size == 64 } {
+	regsub -all {tmpdir/aix-} $ldopts {tmpdir/aix64-} ldopts
+	regsub {^aix} $output {aix64} output
+
+	regsub -all -- {-laix-} $ldopts {-laix64-} ldopts
+	regsub {^libaix} $output {libaix64} output
+    }
+    if { [regexp {.a$} $output] } {
+	append ldopts " -X$size"
+    } else {
+	regsub -all {(-b[IE]):} $ldopts "\\1:$srcdir/$subdir/" ldopts
+	append ldopts " -b$size"
+    }
+    regsub -all {SIZE} $tools $size tools
+    run_ld_link_tests [list [list "$name ($size-bit)" \
+				 $ldopts \
+				 "$asopts -a$size --defsym size=$size" \
+				 $sources \
+				 $tools \
+				 $output]]
+}
+
+set aix52tests {
+    {"Core sections test 1" "-shared -bE:aix-core-sec-1.ex"
+     "" {aix-core-sec-1.s}
+     {{objdump -h aix-core-sec-1.hd}}
+     "aix-core-sec-1.so"}
+
+    {"Core sections test 2" "-shared -bE:aix-core-sec-2.ex"
+     "" {aix-core-sec-2.s}
+     {{objdump -h aix-core-sec-2.hd}}
+     "aix-core-sec-2.so"}
+
+    {"Core sections test 3" "-shared -bE:aix-core-sec-3.ex"
+     "" {aix-core-sec-3.s}
+     {{objdump -h aix-core-sec-3.hd}}
+     "aix-core-sec-3.so"}
+}
+
+foreach test $aix52tests {
+    foreach { name ldopts asopts sources tools output } $test {
+	run_aix_test 32 $name $ldopts $asopts $sources $tools $output
+	run_aix_test 64 $name $ldopts $asopts $sources $tools $output
+    }
+}

^ permalink raw reply	[flat|nested] 50+ messages in thread

* [4/21] Fix o_cputype for 64-bit XCOFF objects
  2009-03-10 13:58 [0/21] Add support for AIX 6 Richard Sandiford
                   ` (2 preceding siblings ...)
  2009-03-10 14:04 ` [3/21] Keep .text, .data and .bss on AIX Richard Sandiford
@ 2009-03-10 14:05 ` Richard Sandiford
  2009-03-12 16:38   ` Nick Clifton
  2009-03-10 14:07 ` [5/21] Set config.dynamic_link for AIX Richard Sandiford
                   ` (17 subsequent siblings)
  21 siblings, 1 reply; 50+ messages in thread
From: Richard Sandiford @ 2009-03-10 14:05 UTC (permalink / raw)
  To: binutils

coff_set_arch_mach_hook associates an o_cputype of 2 (TCPU_PP64)
with bfd_mach_ppc_620, but there is no corresponding case in
xcoff64_write_object_contents.  This means that bfd_mach_ppc_620
objects are incorrectly marked with cputype 1 (TCPU_PPC) instead.

According to:

http://publib.boulder.ibm.com/infocenter/pseries/v5r3/index.jsp?topic=/com.ibm.aix.files/doc/aixfiles/XCOFF.htm

the o_cputype field is still "reserved, set to 0", and the native
AIX tools do seem to set it to 0.  However, the native aouthdr.h file
nevertheless defines various TCPU_* values, and:

http://sourceware.org/ml/binutils/2000-05/msg00228.html

implies that GDB _does_ indirectly care about the cputype,
because it can be used to set the bfd_arch when reading the
object back in.  Even if that's no longer true of modern GDBs,
I'm a bit reluctant to break older, working things.  I've therefore
just added the missing case instead.

AIX seems happy with this.  It understandably refuses to load our
pre-patch 64-bit objects (marked as TCPU_PPC), but it seems just
as happy with TCPU_PPC64 as it is with 0.

OK to install?

Richard


bfd/
	* coff64-rs6000.c (xcoff64_write_object_contents): Set the cputype
	to 2 for bfd_mach_ppc_620.

Index: bfd/coff64-rs6000.c
===================================================================
--- bfd/coff64-rs6000.c	2009-03-10 13:38:53.000000000 +0000
+++ bfd/coff64-rs6000.c	2009-03-10 13:43:22.000000000 +0000
@@ -1048,6 +1048,8 @@ xcoff64_write_object_contents (abfd)
 	    case bfd_arch_powerpc:
 	      if (bfd_get_mach (abfd) == bfd_mach_ppc)
 		internal_a.o_cputype = 3;
+	      else if (bfd_get_mach (abfd) == bfd_mach_ppc_620)
+		internal_a.o_cputype = 2;
 	      else
 		internal_a.o_cputype = 1;
 	      break;

^ permalink raw reply	[flat|nested] 50+ messages in thread

* [5/21] Set config.dynamic_link for AIX
  2009-03-10 13:58 [0/21] Add support for AIX 6 Richard Sandiford
                   ` (3 preceding siblings ...)
  2009-03-10 14:05 ` [4/21] Fix o_cputype for 64-bit XCOFF objects Richard Sandiford
@ 2009-03-10 14:07 ` Richard Sandiford
  2009-03-12 16:39   ` Nick Clifton
  2009-03-10 14:08 ` [6/21] XCOFF R_POS and R_NEG relocations against absolute symbols Richard Sandiford
                   ` (16 subsequent siblings)
  21 siblings, 1 reply; 50+ messages in thread
From: Richard Sandiford @ 2009-03-10 14:07 UTC (permalink / raw)
  To: binutils

Like many ELF targets, the AIX port generates dynamic objects by default.
However, config.dynamic_link is FALSE by default, so any attempt to link
directly against a shared object (as opposed to an archive that contains
a shared object) results in an "attempted static link of dynamic object FOO"
error.

Fixed by setting config.dynamic_link to true by default, just as we do
for GNU/Linux.  Test coverage is provided by later patches.

OK to install?

Richard


ld/
	* emultempl/aix.em (gld${EMULATION_NAME}_before_parse): Set
	config.dynamic_link to TRUE.

Index: ld/emultempl/aix.em
===================================================================
--- ld/emultempl/aix.em	2009-03-10 13:43:04.000000000 +0000
+++ ld/emultempl/aix.em	2009-03-10 13:43:34.000000000 +0000
@@ -137,6 +137,7 @@ gld${EMULATION_NAME}_before_parse (void)
 {
   ldfile_set_output_arch ("${OUTPUT_ARCH}", bfd_arch_`echo ${ARCH} | sed -e 's/:.*//'`);
 
+  config.dynamic_link = TRUE;
   config.has_shared = TRUE;
 
   /* The link_info.[init|fini]_functions are initialized in ld/lexsup.c.

^ permalink raw reply	[flat|nested] 50+ messages in thread

* [6/21] XCOFF R_POS and R_NEG relocations against absolute symbols
  2009-03-10 13:58 [0/21] Add support for AIX 6 Richard Sandiford
                   ` (4 preceding siblings ...)
  2009-03-10 14:07 ` [5/21] Set config.dynamic_link for AIX Richard Sandiford
@ 2009-03-10 14:08 ` Richard Sandiford
  2009-03-13 14:33   ` Nick Clifton
  2009-03-10 14:13 ` [0/21] Add support for AIX 6 Ian Lance Taylor
                   ` (15 subsequent siblings)
  21 siblings, 1 reply; 50+ messages in thread
From: Richard Sandiford @ 2009-03-10 14:08 UTC (permalink / raw)
  To: binutils

The linker currently tries to copy R_POS and R_NEG relocations against
absolute symbols to the .loader section (that is, it tries to make the
relocations dynamic).  This causes the error:

  loader reloc in unrecognized section `*ABS*'

R_POS and R_NEG are simple absolute relocations, so if the symbol is
also absolute, no runtime relocation is needed.  The same is true for
R_RL and R_RLA, which we treat as synonyms for R_POS and R_NEG.

OK to install?

Richard


bfd/
	* xcofflink.c (xcoff_mark, xcoff_link_input_bfd): Don't copy
	R_POS and R_NEG relocations against absolute symbols to the
	.loader section.

ld/testsuite/
	* ld-powerpc/aix-abs-reloc-1.ex, ld-powerpc/aix-abs-reloc-1.im,
	ld-powerpc/aix-abs-reloc-1.od, ld-powerpc/aix-abs-reloc-1.s: New test.
	* ld-powerpc/aix52.exp: Run it.

Index: bfd/xcofflink.c
===================================================================
--- bfd/xcofflink.c	2009-03-10 13:38:53.000000000 +0000
+++ bfd/xcofflink.c	2009-03-10 13:43:53.000000000 +0000
@@ -2335,6 +2335,11 @@ xcoff_mark (struct bfd_link_info *info, 
 		case R_NEG:
 		case R_RL:
 		case R_RLA:
+		  if (h != NULL
+		      && (h->root.type == bfd_link_hash_defined
+			  || h->root.type == bfd_link_hash_defweak)
+		      && bfd_is_abs_section (h->root.u.def.section))
+		    break;
 		  ++xcoff_hash_table (info)->ldrel_count;
 		  if (h != NULL)
 		    h->flags |= XCOFF_LDREL;
@@ -4460,6 +4465,11 @@ #define N_BTSHFT n_btshft
 		case R_NEG:
 		case R_RL:
 		case R_RLA:
+		  if (h != NULL
+		      && (h->root.type == bfd_link_hash_defined
+			  || h->root.type == bfd_link_hash_defweak)
+		      && bfd_is_abs_section (h->root.u.def.section))
+		    break;
 		  /* This reloc needs to be copied into the .loader
 		     section.  */
 		  ldrel.l_vaddr = irel->r_vaddr;
Index: ld/testsuite/ld-powerpc/aix-abs-reloc-1.ex
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-abs-reloc-1.ex	2009-03-10 13:43:53.000000000 +0000
@@ -0,0 +1,1 @@
+foo
Index: ld/testsuite/ld-powerpc/aix-abs-reloc-1.im
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-abs-reloc-1.im	2009-03-10 13:43:53.000000000 +0000
@@ -0,0 +1,1 @@
+bar	0xdeadbeef
Index: ld/testsuite/ld-powerpc/aix-abs-reloc-1.od
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-abs-reloc-1.od	2009-03-10 13:43:53.000000000 +0000
@@ -0,0 +1,7 @@
+
+.*
+
+DYNAMIC RELOCATION RECORDS \(none\)
+
+Contents of section \.data:
+ 10000000 deadbeef .*
Index: ld/testsuite/ld-powerpc/aix-abs-reloc-1.s
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-abs-reloc-1.s	2009-03-10 13:43:53.000000000 +0000
@@ -0,0 +1,4 @@
+	.globl	foo
+	.csect	foo[RW]
+foo:
+	.long	bar
Index: ld/testsuite/ld-powerpc/aix52.exp
===================================================================
--- ld/testsuite/ld-powerpc/aix52.exp	2009-03-10 13:43:04.000000000 +0000
+++ ld/testsuite/ld-powerpc/aix52.exp	2009-03-10 13:43:53.000000000 +0000
@@ -65,6 +65,12 @@ proc run_aix_test { size name ldopts aso
 }
 
 set aix52tests {
+    {"Relocations against absolute symbols 1"
+     "-shared -bI:aix-abs-reloc-1.im -bE:aix-abs-reloc-1.ex"
+     {} {aix-abs-reloc-1.s}
+     {{objdump -sRj.data aix-abs-reloc-1.od}}
+     "aix-abs-reloc-1.so"}
+
     {"Core sections test 1" "-shared -bE:aix-core-sec-1.ex"
      "" {aix-core-sec-1.s}
      {{objdump -h aix-core-sec-1.hd}}

^ permalink raw reply	[flat|nested] 50+ messages in thread

* [7/21] Handle relative branches to absolute addresses
  2009-03-10 13:58 [0/21] Add support for AIX 6 Richard Sandiford
                   ` (6 preceding siblings ...)
  2009-03-10 14:13 ` [0/21] Add support for AIX 6 Ian Lance Taylor
@ 2009-03-10 14:13 ` Richard Sandiford
  2009-03-13 14:37   ` Nick Clifton
  2009-03-10 14:15 ` [8/21] bfd_install_relocation strikes again Richard Sandiford
                   ` (13 subsequent siblings)
  21 siblings, 1 reply; 50+ messages in thread
From: Richard Sandiford @ 2009-03-10 14:13 UTC (permalink / raw)
  To: binutils

This patch fixes:

   R_RBR:
   A relative branch which may be modified to become an
   absolute branch.  FIXME: We don't implement this,
   although we should for symbols of storage mapping class
   XMC_XO.

This is fairly important when linking against libc.a without garbage
collection; the libc.a object that defines setjmp and longjmp also defines
a function called ukey_setjmp, which in turn has a branch relocation against
an absolute symbol called ukeyset_activate.  With our default text start
address of 0x10000000, ukeyset_activate is out of range of a relative
branch, and we get a relocation-overflow error.

(You'd normally want to use garbage collection on AIX, but we currently
don't allow that for shared libraries.  Later patches fix this.)

I stuck to bfd_link_hash_defined because that's what the current code
uses elsewhere.  A later patch will add weak support.

OK to install?

Richard


bfd/
	* coff-rs6000.c (xcoff_reloc_type_br): Make the branch absolute
	if the target is absolute.  Fix comment typo.
	(xcoff_ppc_relocate_section): Remove FIXME.
	* coff64-rs6000.c (xcoff64_reloc_type_br): Make the branch absolute
	if the target is absolute.

ld/testsuite/
	* ld-powerpc/aix-abs-branch-1.im, ld-powerpc/aix-abs-branch-1.ex,
	ld-powerpc/aix-abs-branch-1.s,
	ld-powerpc/aix-abs-branch-1.dd: New test.
	* ld-powerpc/aix52.exp: Run it.

Index: bfd/coff-rs6000.c
===================================================================
--- bfd/coff-rs6000.c	2009-03-10 13:38:53.000000000 +0000
+++ bfd/coff-rs6000.c	2009-03-10 13:46:00.000000000 +0000
@@ -2947,11 +2947,13 @@ xcoff_reloc_type_br (input_bfd, input_se
      bfd_byte *contents;
 {
   struct xcoff_link_hash_entry *h;
+  bfd_vma section_offset;
 
   if (0 > rel->r_symndx)
     return FALSE;
 
   h = obj_xcoff_sym_hashes (input_bfd)[rel->r_symndx];
+  section_offset = rel->r_vaddr - input_section->vma;
 
   /* If we see an R_BR or R_RBR reloc which is jumping to global
      linkage code, and it is followed by an appropriate cror nop
@@ -2962,12 +2964,12 @@ xcoff_reloc_type_br (input_bfd, input_se
      cror.  */
   if (NULL != h
       && bfd_link_hash_defined == h->root.type
-      && rel->r_vaddr - input_section->vma + 8 <= input_section->size)
+      && section_offset + 8 <= input_section->size)
     {
       bfd_byte *pnext;
       unsigned long next;
 
-      pnext = contents + (rel->r_vaddr - input_section->vma) + 4;
+      pnext = contents + section_offset + 4;
       next = bfd_get_32 (input_bfd, pnext);
 
       /* The _ptrgl function is magic.  It is used by the AIX
@@ -2977,12 +2979,12 @@ xcoff_reloc_type_br (input_bfd, input_se
 	  if (next == 0x4def7b82			/* cror 15,15,15 */
 	      || next == 0x4ffffb82			/* cror 31,31,31 */
 	      || next == 0x60000000)			/* ori r0,r0,0 */
-	    bfd_put_32 (input_bfd, 0x80410014, pnext);	/* lwz r1,20(r1) */
+	    bfd_put_32 (input_bfd, 0x80410014, pnext);	/* lwz r2,20(r1) */
 
 	}
       else
 	{
-	  if (next == 0x80410014)			/* lwz r1,20(r1) */
+	  if (next == 0x80410014)			/* lwz r2,20(r1) */
 	    bfd_put_32 (input_bfd, 0x60000000, pnext);	/* ori r0,r0,0 */
 	}
     }
@@ -2998,16 +3000,41 @@ xcoff_reloc_type_br (input_bfd, input_se
       howto->complain_on_overflow = complain_overflow_dont;
     }
 
-  howto->pc_relative = TRUE;
+  /* The original PC-relative relocation is biased by -r_vaddr, so adding
+     the value below will give the absolute target address.  */
+  *relocation = val + addend + rel->r_vaddr;
+
   howto->src_mask &= ~3;
   howto->dst_mask = howto->src_mask;
 
-  /* A PC relative reloc includes the section address.  */
-  addend += input_section->vma;
+  if (h != NULL
+      && h->root.type == bfd_link_hash_defined
+      && bfd_is_abs_section (h->root.u.def.section)
+      && section_offset + 4 <= input_section->size)
+    {
+      bfd_byte *ptr;
+      bfd_vma insn;
 
-  *relocation = val + addend;
-  *relocation -= (input_section->output_section->vma
-		  + input_section->output_offset);
+      /* Turn the relative branch into an absolute one by setting the
+	 AA bit.  */
+      ptr = contents + section_offset;
+      insn = bfd_get_32 (input_bfd, ptr);
+      insn |= 2;
+      bfd_put_32 (input_bfd, insn, ptr);
+
+      /* Make the howto absolute too.  */
+      howto->pc_relative = FALSE;
+      howto->complain_on_overflow = complain_overflow_bitfield;
+    }
+  else
+    {
+      /* Use a PC-relative howto and subtract the instruction's address
+	 from the target address we calculated above.  */
+      howto->pc_relative = TRUE;
+      *relocation -= (input_section->output_section->vma
+		      + input_section->output_offset
+		      + section_offset);
+    }
   return TRUE;
 }
 
@@ -3323,9 +3350,7 @@ xcoff_complain_overflow_unsigned_func (i
 
    R_RBR:
    A relative branch which may be modified to become an
-   absolute branch.  FIXME: We don't implement this,
-   although we should for symbols of storage mapping class
-   XMC_XO.
+   absolute branch.
 
    R_RL:
    The PowerPC AIX ABI describes this as a load which may be
Index: bfd/coff64-rs6000.c
===================================================================
--- bfd/coff64-rs6000.c	2009-03-10 13:43:22.000000000 +0000
+++ bfd/coff64-rs6000.c	2009-03-10 13:46:00.000000000 +0000
@@ -1117,11 +1117,13 @@ xcoff64_reloc_type_br (input_bfd, input_
      bfd_byte *contents;
 {
   struct xcoff_link_hash_entry *h;
+  bfd_vma section_offset;
 
   if (0 > rel->r_symndx)
     return FALSE;
 
   h = obj_xcoff_sym_hashes (input_bfd)[rel->r_symndx];
+  section_offset = rel->r_vaddr - input_section->vma;
 
   /* If we see an R_BR or R_RBR reloc which is jumping to global
      linkage code, and it is followed by an appropriate cror nop
@@ -1132,12 +1134,12 @@ xcoff64_reloc_type_br (input_bfd, input_
      cror.  */
   if (NULL != h
       && bfd_link_hash_defined == h->root.type
-      && rel->r_vaddr - input_section->vma + 8 <= input_section->size)
+      && section_offset + 8 <= input_section->size)
     {
       bfd_byte *pnext;
       unsigned long next;
 
-      pnext = contents + (rel->r_vaddr - input_section->vma) + 4;
+      pnext = contents + section_offset + 4;
       next = bfd_get_32 (input_bfd, pnext);
 
       /* The _ptrgl function is magic.  It is used by the AIX compiler to call
@@ -1166,16 +1168,41 @@ xcoff64_reloc_type_br (input_bfd, input_
       howto->complain_on_overflow = complain_overflow_dont;
     }
 
-  howto->pc_relative = TRUE;
+  /* The original PC-relative relocation is biased by -r_vaddr, so adding
+     the value below will give the absolute target address.  */
+  *relocation = val + addend + rel->r_vaddr;
+
   howto->src_mask &= ~3;
   howto->dst_mask = howto->src_mask;
 
-  /* A PC relative reloc includes the section address.  */
-  addend += input_section->vma;
-
-  *relocation = val + addend;
-  *relocation -= (input_section->output_section->vma
-		  + input_section->output_offset);
+  if (h != NULL
+      && h->root.type == bfd_link_hash_defined
+      && bfd_is_abs_section (h->root.u.def.section)
+      && section_offset + 4 <= input_section->size)
+    {
+      bfd_byte *ptr;
+      bfd_vma insn;
+
+      /* Turn the relative branch into an absolute one by setting the
+	 AA bit.  */
+      ptr = contents + section_offset;
+      insn = bfd_get_32 (input_bfd, ptr);
+      insn |= 2;
+      bfd_put_32 (input_bfd, insn, ptr);
+
+      /* Make the howto absolute too.  */
+      howto->pc_relative = FALSE;
+      howto->complain_on_overflow = complain_overflow_bitfield;
+    }
+  else
+    {
+      /* Use a PC-relative howto and subtract the instruction's address
+	 from the target address we calculated above.  */
+      howto->pc_relative = TRUE;
+      *relocation -= (input_section->output_section->vma
+		      + input_section->output_offset
+		      + section_offset);
+    }
   return TRUE;
 }
 
Index: ld/testsuite/ld-powerpc/aix-abs-branch-1.im
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-abs-branch-1.im	2009-03-10 13:46:00.000000000 +0000
@@ -0,0 +1,1 @@
+bar	0x1450000
Index: ld/testsuite/ld-powerpc/aix-abs-branch-1.ex
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-abs-branch-1.ex	2009-03-10 13:46:00.000000000 +0000
@@ -0,0 +1,1 @@
+foo
Index: ld/testsuite/ld-powerpc/aix-abs-branch-1.s
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-abs-branch-1.s	2009-03-10 13:46:00.000000000 +0000
@@ -0,0 +1,14 @@
+	.globl	foo
+	.csect	foo[PR]
+foo:
+	bl	bar - 0x3000
+	lwz	1,80(1)
+	bl	bar + 0x1000
+	.ifeq	size - 32
+	lwz	2,20(1)
+	.else
+	ld	2,40(1)
+	.endif
+	bl	bar + 0x2800
+	nop
+	bl	bar
Index: ld/testsuite/ld-powerpc/aix-abs-branch-1.dd
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-abs-branch-1.dd	2009-03-10 13:46:00.000000000 +0000
@@ -0,0 +1,14 @@
+
+.*
+
+
+Disassembly of section \.text:
+
+0*10000000 <foo>:
+ *10000000:.*	bla * 144d000 <.*>
+ *10000004:.*	l(wz|) * r1,80\(r1\)
+ *10000008:.*	bla * 1451000 <.*>
+ *1000000c:.*	(oril * r0,r0,0|nop)
+ *10000010:.*	bla * 1452800 <.*>
+ *10000014:.*	(oril * r0,r0,0|nop)
+ *10000018:.*	bla * 1450000 <.*>
Index: ld/testsuite/ld-powerpc/aix52.exp
===================================================================
--- ld/testsuite/ld-powerpc/aix52.exp	2009-03-10 13:43:53.000000000 +0000
+++ ld/testsuite/ld-powerpc/aix52.exp	2009-03-10 13:46:00.000000000 +0000
@@ -65,6 +65,12 @@ proc run_aix_test { size name ldopts aso
 }
 
 set aix52tests {
+    {"Absolute branch test 1"
+     "-shared -bI:aix-abs-branch-1.im -bE:aix-abs-branch-1.ex"
+     "" {aix-abs-branch-1.s}
+     {{objdump {-dR} aix-abs-branch-1.dd}}
+     "aix-abs-branch-1.so"}
+
     {"Relocations against absolute symbols 1"
      "-shared -bI:aix-abs-reloc-1.im -bE:aix-abs-reloc-1.ex"
      {} {aix-abs-reloc-1.s}

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [0/21] Add support for AIX 6
  2009-03-10 13:58 [0/21] Add support for AIX 6 Richard Sandiford
                   ` (5 preceding siblings ...)
  2009-03-10 14:08 ` [6/21] XCOFF R_POS and R_NEG relocations against absolute symbols Richard Sandiford
@ 2009-03-10 14:13 ` Ian Lance Taylor
  2009-03-10 15:22   ` Richard Sandiford
  2009-03-10 15:45   ` Michael Haubenwallner
  2009-03-10 14:13 ` [7/21] Handle relative branches to absolute addresses Richard Sandiford
                   ` (14 subsequent siblings)
  21 siblings, 2 replies; 50+ messages in thread
From: Ian Lance Taylor @ 2009-03-10 14:13 UTC (permalink / raw)
  To: binutils; +Cc: richards

Richard Sandiford <richards@transitive.com> writes:

> Now the AIX linker appears to apply something like --whole-archive
> semantics to _all_ archives.

That is correct.  The AIX linker uses the equivalent of --whole-archive,
and then uses garbage collection to discarded unreferenced csects.

My attitude when I did the original GNU ld port to AIX was that GNU ld
should, as much as possible, present the same interface on every host.
I figured that the main reason that people would use GNU ld for AIX
would be because they were cross-compiling to AIX, and that the most
likely scenario there was a program which ran on many different hosts.
I felt that it would be more convenient in that scenario if they did not
have to invoke the linker differently on different hosts.  This shows up
most drastically on AIX, but we also see it in, e.g., the default for
--export-dynamic, which is different in the native linkers on Solaris
and System V, but which is always the same for GNU ld.

I don't feel all that strongly about this then or now, but that was my
reasoning and it still seems valid to me.

Ian

^ permalink raw reply	[flat|nested] 50+ messages in thread

* [8/21] bfd_install_relocation strikes again
  2009-03-10 13:58 [0/21] Add support for AIX 6 Richard Sandiford
                   ` (7 preceding siblings ...)
  2009-03-10 14:13 ` [7/21] Handle relative branches to absolute addresses Richard Sandiford
@ 2009-03-10 14:15 ` Richard Sandiford
  2009-03-13 14:48   ` Nick Clifton
  2009-03-10 14:22 ` [9/21] Implicitly import undefined symbols Richard Sandiford
                   ` (12 subsequent siblings)
  21 siblings, 1 reply; 50+ messages in thread
From: Richard Sandiford @ 2009-03-10 14:15 UTC (permalink / raw)
  To: binutils

The !OBJ_ELF part of tc-ppc.c:md_apply_fix says:

  /* FIXME FIXME FIXME: The value we are passed in *valP includes
     the symbol values.  If we are doing this relocation the code in
     write.c is going to call bfd_install_relocation, which is also
     going to use the symbol value.  That means that if the reloc is
     fully resolved we want to use *valP since bfd_install_relocation is
     not being used.
     However, if the reloc is not fully resolved we do not want to use
     *valP, and must use fx_offset instead.  However, if the reloc
     is PC relative, we do want to use *valP since it includes the
     result of md_pcrel_from.  This is confusing.  */
  if (fixP->fx_addsy == (symbolS *) NULL)
    fixP->fx_done = 1;

  else if (fixP->fx_pcrel)
    ;

  else
    value = fixP->fx_offset;

But the "double symbol" problem described here applies to PC-relative
relocs just as much as it does to other relocs.  E.g. if we have:

bar:    bl foo
	...
foo:

the relocation field is set to:

        (foo - .text) * 2 - (bar - .text)

rather than the intended:

        (foo - .text) - (bar - .text)

So we should still recompute VALUE for PC_relative relocs, but re-apply
md_pcrel_from_section to the result.

OK to install?

Richard


gas/
	* config/tc-ppc.c (md_apply_fix): On COFF targets, always reread
	"value" from fx_offset.  Manually resubtract md_pcrel_from_section
	where necessary.

gas/testsuite/
	* gas/ppc/xcoff-branch-1.s, gas/ppc/xcoff-branch-1-32.d,
	gas/ppc/xcoff-branch-1-64.d: New tests.
	* gas/ppc/aix.exp: Run them.

Index: gas/config/tc-ppc.c
===================================================================
--- gas/config/tc-ppc.c	2009-03-10 13:38:53.000000000 +0000
+++ gas/config/tc-ppc.c	2009-03-10 13:46:12.000000000 +0000
@@ -5617,18 +5617,19 @@ md_apply_fix (fixS *fixP, valueT *valP, 
      going to use the symbol value.  That means that if the reloc is
      fully resolved we want to use *valP since bfd_install_relocation is
      not being used.
-     However, if the reloc is not fully resolved we do not want to use
-     *valP, and must use fx_offset instead.  However, if the reloc
-     is PC relative, we do want to use *valP since it includes the
-     result of md_pcrel_from.  This is confusing.  */
+     However, if the reloc is not fully resolved we do not want to
+     use *valP, and must use fx_offset instead.  If the relocation
+     is PC-relative, we then need to re-apply md_pcrel_from_section
+     to this new relocation value.  */
   if (fixP->fx_addsy == (symbolS *) NULL)
     fixP->fx_done = 1;
 
-  else if (fixP->fx_pcrel)
-    ;
-
   else
-    value = fixP->fx_offset;
+    {
+      value = fixP->fx_offset;
+      if (fixP->fx_pcrel)
+	value -= md_pcrel_from_section (fixP, seg);
+    }
 #endif
 
   if (fixP->fx_subsy != (symbolS *) NULL)
Index: gas/testsuite/gas/ppc/xcoff-branch-1.s
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ gas/testsuite/gas/ppc/xcoff-branch-1.s	2009-03-10 13:46:12.000000000 +0000
@@ -0,0 +1,40 @@
+	.globl	.foo
+	.globl	foo1
+	.globl	foo2
+	.globl	.bar
+	.globl	.frob
+
+	.csect	.foo[PR]
+.foo:
+	bl	foo2 + 0x4
+	bl	foo1 + 0xc
+	bl	foo1
+	bl	foo2
+	bl	.bar
+foo1:
+	bl	.foo
+	bl	.frob
+	bl	.foo + 0x10
+	bl	.bar + 0x8
+foo2:
+	bl	.frob + 0x10
+	blr
+
+	.csect	.bar[PR]
+.bar:	bl	foo1
+	bl	foo2
+	bl	foo1 + 0x8
+	bl	foo2 + 0x4
+	bl	.foo
+	bl	.bar
+	bl	.frob
+	bl	.foo + 0x1c
+	bl	.bar + 0xc
+	bl	.frob + 0x4
+
+	.csect	.frob[PR]
+.frob:	bl	.foo
+	bl	.bar
+	bl	.frob
+	bl	foo1
+	bl	foo2
Index: gas/testsuite/gas/ppc/xcoff-branch-1-32.d
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ gas/testsuite/gas/ppc/xcoff-branch-1-32.d	2009-03-10 13:46:12.000000000 +0000
@@ -0,0 +1,61 @@
+#as: -a32
+#source: xcoff-branch-1.s
+#objdump: -dr
+#name: XCOFF branch test 1 (32-bit)
+
+.*
+
+
+Disassembly of section \.text:
+
+0+00 <\.foo>:
+   0:	48 00 00 29 	bl      28 <foo2\+0x4>
+   4:	48 00 00 1d 	bl      20 <foo1\+0xc>
+   8:	48 00 00 0d 	bl      14 <foo1>
+   c:	48 00 00 19 	bl      24 <foo2>
+  10:	48 00 00 1d 	bl      2c <\.bar>
+			10: R_(RBR_26|BR)	.*
+
+0+14 <foo1>:
+  14:	4b ff ff ed 	bl      0 <\.foo>
+  18:	48 00 00 3d 	bl      54 <\.frob>
+			18: R_(RBR_26|BR)	.*
+  1c:	4b ff ff f5 	bl      10 <\.foo\+0x10>
+  20:	48 00 00 15 	bl      34 <\.bar\+0x8>
+			20: R_(RBR_26|BR)	.*
+
+0+24 <foo2>:
+  24:	48 00 00 41 	bl      64 <\.frob\+0x10>
+			24: R_(RBR_26|BR)	.*
+  28:	4e 80 00 20 	br
+
+0+2c <\.bar>:
+  2c:	4b ff ff e9 	bl      14 <foo1>
+			2c: R_(RBR_26|BR)	.*
+  30:	4b ff ff f5 	bl      24 <foo2>
+			30: R_(RBR_26|BR)	.*
+  34:	4b ff ff e9 	bl      1c <foo1\+0x8>
+			34: R_(RBR_26|BR)	.*
+  38:	4b ff ff f1 	bl      28 <foo2\+0x4>
+			38: R_(RBR_26|BR)	.*
+  3c:	4b ff ff c5 	bl      0 <\.foo>
+			3c: R_(RBR_26|BR)	.*
+  40:	4b ff ff ed 	bl      2c <\.bar>
+  44:	48 00 00 11 	bl      54 <\.frob>
+			44: R_(RBR_26|BR)	.*
+  48:	4b ff ff d5 	bl      1c <foo1\+0x8>
+			48: R_(RBR_26|BR)	.*
+  4c:	4b ff ff ed 	bl      38 <\.bar\+0xc>
+  50:	48 00 00 09 	bl      58 <\.frob\+0x4>
+			50: R_(RBR_26|BR)	.*
+
+0+54 <\.frob>:
+  54:	4b ff ff ad 	bl      0 <\.foo>
+			54: R_(RBR_26|BR)	.*
+  58:	4b ff ff d5 	bl      2c <\.bar>
+			58: R_(RBR_26|BR)	.*
+  5c:	4b ff ff f9 	bl      54 <\.frob>
+  60:	4b ff ff b5 	bl      14 <foo1>
+			60: R_(RBR_26|BR)	.*
+  64:	4b ff ff c1 	bl      24 <foo2>
+			64: R_(RBR_26|BR)	.*
Index: gas/testsuite/gas/ppc/xcoff-branch-1-64.d
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ gas/testsuite/gas/ppc/xcoff-branch-1-64.d	2009-03-10 13:46:12.000000000 +0000
@@ -0,0 +1,61 @@
+#as: -a64
+#source: xcoff-branch-1.s
+#objdump: -dr
+#name: XCOFF branch test 1 (64-bit)
+
+.*
+
+
+Disassembly of section \.text:
+
+0+00 <\.foo>:
+   0:	48 00 00 29 	bl      28 <foo2\+0x4>
+   4:	48 00 00 1d 	bl      20 <foo1\+0xc>
+   8:	48 00 00 0d 	bl      14 <foo1>
+   c:	48 00 00 19 	bl      24 <foo2>
+  10:	48 00 00 1d 	bl      2c <\.bar>
+			10: R_(RBR_26|BR)	.*
+
+0+14 <foo1>:
+  14:	4b ff ff ed 	bl      0 <\.foo>
+  18:	48 00 00 3d 	bl      54 <\.frob>
+			18: R_(RBR_26|BR)	.*
+  1c:	4b ff ff f5 	bl      10 <\.foo\+0x10>
+  20:	48 00 00 15 	bl      34 <\.bar\+0x8>
+			20: R_(RBR_26|BR)	.*
+
+0+24 <foo2>:
+  24:	48 00 00 41 	bl      64 <\.frob\+0x10>
+			24: R_(RBR_26|BR)	.*
+  28:	4e 80 00 20 	blr
+
+0+2c <\.bar>:
+  2c:	4b ff ff e9 	bl      14 <foo1>
+			2c: R_(RBR_26|BR)	.*
+  30:	4b ff ff f5 	bl      24 <foo2>
+			30: R_(RBR_26|BR)	.*
+  34:	4b ff ff e9 	bl      1c <foo1\+0x8>
+			34: R_(RBR_26|BR)	.*
+  38:	4b ff ff f1 	bl      28 <foo2\+0x4>
+			38: R_(RBR_26|BR)	.*
+  3c:	4b ff ff c5 	bl      0 <\.foo>
+			3c: R_(RBR_26|BR)	.*
+  40:	4b ff ff ed 	bl      2c <\.bar>
+  44:	48 00 00 11 	bl      54 <\.frob>
+			44: R_(RBR_26|BR)	.*
+  48:	4b ff ff d5 	bl      1c <foo1\+0x8>
+			48: R_(RBR_26|BR)	.*
+  4c:	4b ff ff ed 	bl      38 <\.bar\+0xc>
+  50:	48 00 00 09 	bl      58 <\.frob\+0x4>
+			50: R_(RBR_26|BR)	.*
+
+0+54 <\.frob>:
+  54:	4b ff ff ad 	bl      0 <\.foo>
+			54: R_(RBR_26|BR)	.*
+  58:	4b ff ff d5 	bl      2c <\.bar>
+			58: R_(RBR_26|BR)	.*
+  5c:	4b ff ff f9 	bl      54 <\.frob>
+  60:	4b ff ff b5 	bl      14 <foo1>
+			60: R_(RBR_26|BR)	.*
+  64:	4b ff ff c1 	bl      24 <foo2>
+			64: R_(RBR_26|BR)	.*
Index: gas/testsuite/gas/ppc/aix.exp
===================================================================
--- gas/testsuite/gas/ppc/aix.exp	2009-03-10 13:38:53.000000000 +0000
+++ gas/testsuite/gas/ppc/aix.exp	2009-03-10 13:46:12.000000000 +0000
@@ -63,4 +63,6 @@ if [istarget powerpc-ibm-aix*] then {
 
     run_dump_test "textalign-xcoff-001"
     run_dump_test "textalign-xcoff-002"
+    run_dump_test "xcoff-branch-1-32"
+    run_dump_test "xcoff-branch-1-64"
 }

^ permalink raw reply	[flat|nested] 50+ messages in thread

* [9/21] Implicitly import undefined symbols
  2009-03-10 13:58 [0/21] Add support for AIX 6 Richard Sandiford
                   ` (8 preceding siblings ...)
  2009-03-10 14:15 ` [8/21] bfd_install_relocation strikes again Richard Sandiford
@ 2009-03-10 14:22 ` Richard Sandiford
  2009-03-13 14:55   ` Nick Clifton
  2009-03-10 14:25 ` [10/21] Fix the csect handling of XTY_ER symbols Richard Sandiford
                   ` (11 subsequent siblings)
  21 siblings, 1 reply; 50+ messages in thread
From: Richard Sandiford @ 2009-03-10 14:22 UTC (permalink / raw)
  To: binutils

This patch fixes three related problems:

  (1) If a function symbol .FOO is defined but its descriptor FOO is not,
      the linker creates an automatic definition itself.  However, it
      currently only does this if FOO is exported, whereas the AIX
      linker does it for internal references too.  That is, if you have:

		.csect .FOO[PR]
	.FOO:
		...
		.long	FOO

      the AIX linker automatically creates FOO if necessary.

      This might well just be cleaning up after forgetful assembler
      programmers, but *shuffle* we did stumble across this the hard way...

  (2) The linker is inconsistent in the way it handles:

		.long	.FOO

      for an external function FOO.  If FOO is also called, such as by:

		bl      .FOO

      the linker creates global linkage code for FOO and redirects
      _both_ relocations to it.  However, if FOO isn't called, the
      linker generates a dynamic relocation against .FOO itself.

      Again, I'm not sure if these sorts of .longs are really suppoesed
      to exist.  Certainly normal function pointers should use the
      function descriptor instead, and I only came across this case
      by inspection, not in real code.  However, the AIX linker redirects
      ".long .FOO" to global linkage code even if there's no "bl .FOO".
      That seems more consistent than our behaviour, and avoids having
      (unresolvable) dynamic relocations against function symbols.

      As an added bonus, it makes the code simpler.

  (3) The most important one.  Let's suppose we have an undefined
      symbol S.  The default -shared behaviour is to allow references
      to S.  However, although we list S in the dynamic (.loader) symbol
      table, we currently don't mark it as imported.  This causes the
      runtime linker to complain that the relocation is against an
      undefined symbol.

      By default, the native AIX linker lists S as an import without
      specifying an import module.  With -brtl, it instead imports S
      with a special filename of "..".  We should do the same.

The patch makes sure that we have a known source for every marked symbol.
If we mark a symbol S that has no current definition, we do one of
three things:

  (a) If S is a function descriptor for a defined function .S, we create
      S automatically.  This is (1) above, and the code is taken from
      xcoff_build_ldsyms.

  (b) If S is a function symbol, we mark its descriptor and create
      global linkage code.  The code for this is taken from
      xcoff_build_ldsyms.

  (c) Otherwise, we implicitly mark the symbol as an import.

(a) is not an error; the AIX linker does not warn about it.  However,
for (c), we need some way of recording that this import was implicit,
so that we still report relocations against it.  The patch adds an
XCOFF_WAS_UNDEFINED flag for this.  It's convenient to set the flag
for (b) too, so that a relocation is against an undefined symbol iff
XCOFF_WAS_UNDEFINED is set.

That deals with (1) and (3) above.  (2) comes into play because of (b).
At the moment, if we see a branch relocation against .S, and if symbol
S does not yet exist, we create an entry for S automatically.  We then
mark S as the descriptor for .S.  However, we don't do this for other
relocations against .S.

So how should we handle .S if it is only referenced by non-branch
relocations?  We could add special code for this case, or we could
treat all relocs in the same way.

The second behaviour is obviously simpler, and is what the native AIX
linker does.  The patch therefore does it too.  XCOFF_CALLED now means
"this is a _function_ symbol that has at least one relocation against it",
rather than its current meaning of "this is a symbol that has at least
one _branch_ relocation against it".  I couldn't think of a better name
for the flag though; the old one still seems appropriate.

Finally, the native AIX linker defines -berok as follows:

    Produces the output object file without errors even if there are
    unresolved external references.

where "without errors" means "silently".  Errors not related to
undefined externs should still be reported.

In contrast, we currently implement -berok as "report errors as normal,
but generate the executable regardless".  The patch makes us follow
the AIX behaviour.

OK to install?

Richard


include/coff/
	* xcoff.h (XCOFF_CALLED, XCOFF_IMPORT): Update comments.
	(XCOFF_WAS_UNDEFINED): New flag.
	(xcoff_link_hash_table): Add an "rtld" field.

bfd/
	* coff-rs6000.c (xcoff_ppc_relocate_section): Report relocations
	against undefined symbols if the symbol's XCOFF_WAS_UNDEFINED
	flag is set.  Assert that all undefined symbols are either
	imported or defined by a dynamic object.
	* coff64-rs6000.c (xcoff64_ppc_relocate_section): Likewise.
	* xcofflink.c (xcoff_link_add_symbols): Extend function-symbol
	handling to all relocations.  Only set XCOFF_CALLED for function
	symbols.
	(xcoff_find_function): New function, split out from...
	(bfd_xcoff_export_symbol) ...here.
	(xcoff_set_import_path): New function, split out from...
	(bfd_xcoff_import_symbol): ...here.  Remove assertion for old
	meaning of XCOFF_CALLED.
	(xcoff_mark_symbol): If we mark an undefined and unimported
	symbol, find some way of defining it.  If the symbol is a function
	descriptor, fill in its definition automatically.  If the symbol
	is a function, mark its descriptor and allocate room for global
	linkage code.  Otherwise mark the symbol as implicitly imported.
	Move the code for creating function descriptors from...
	(xcoff_build_ldsyms): ...here.  Use XCOFF_WAS_UNDEFINED to 
	check for symbols that were implicitly defined.
	(xcoff_mark): Don't count any dynamic relocations against
	function symbols.
	(bfd_xcoff_size_dynamic_sections): Save the rtld parameter
	in the xcoff link info.
	(xcoff_link_input_bfd): Remove handling of undefined and
	unexported symbols.

ld/
	* emultempl/aix.em (gld${EMULATION_NAME}_handle_option): Make
	-berok and -bernotok control link_info.unresolved_syms_in_objects
	and link_info.unresolved_syms_in_shared_libs instead of
	force_make_executable.

ld/testsuite/
	* ld-powerpc/aix-glink-1.ex, ld-powerpc/aix-glink-1.s,
	ld-powerpc/aix-glink-1-32.dd, ld-powerpc/aix-glink-1-64.dd,
	ld-powerpc/aix-glink-1-32.d, ld-powerpc/aix-glink-1-64.d: New tests.
	* ld-powerpc/aix52.exp: Run them.

Index: include/coff/xcoff.h
===================================================================
--- include/coff/xcoff.h	2009-03-10 13:38:53.000000000 +0000
+++ include/coff/xcoff.h	2009-03-10 13:46:23.000000000 +0000
@@ -291,11 +291,12 @@ #define XCOFF_DEF_DYNAMIC      0x0000000
 #define XCOFF_LDREL            0x00000008
 /* Symbol is the entry point.  */
 #define XCOFF_ENTRY            0x00000010
-/* Symbol is called; this is, it appears in a R_BR reloc.  */
+/* Symbol is for a function and is the target of a relocation.
+   The relocation may or may not be a branch-type relocation.  */
 #define XCOFF_CALLED           0x00000020
 /* Symbol needs the TOC entry filled in.  */
 #define XCOFF_SET_TOC          0x00000040
-/* Symbol is explicitly imported.  */
+/* Symbol is implicitly or explicitly imported.  */
 #define XCOFF_IMPORT           0x00000080
 /* Symbol is explicitly exported.  */
 #define XCOFF_EXPORT           0x00000100
@@ -315,6 +316,8 @@ #define XCOFF_RTINIT           0x0000400
 #define XCOFF_SYSCALL32        0x00008000
 /* Symbol is an imported 64 bit syscall.  */
 #define XCOFF_SYSCALL64        0x00010000 
+/* Symbol was not explicitly defined by the time it was marked.  */
+#define XCOFF_WAS_UNDEFINED    0x00020000
 
 /* The XCOFF linker hash table.  */
 
@@ -368,6 +371,9 @@ struct xcoff_link_hash_table
   /* Whether the .text section must be read-only.  */
   bfd_boolean textro;
 
+  /* Whether -brtl was specified.  */
+  bfd_boolean rtld;
+
   /* Whether garbage collection was done.  */
   bfd_boolean gc;
 
Index: bfd/coff-rs6000.c
===================================================================
--- bfd/coff-rs6000.c	2009-03-10 13:46:00.000000000 +0000
+++ bfd/coff-rs6000.c	2009-03-10 13:46:23.000000000 +0000
@@ -3447,6 +3447,17 @@ xcoff_ppc_relocate_section (output_bfd, 
 	    }
 	  else
 	    {
+	      if (info->unresolved_syms_in_objects != RM_IGNORE
+		  && (h->flags & XCOFF_WAS_UNDEFINED) != 0)
+		{
+		  if (! ((*info->callbacks->undefined_symbol)
+			 (info, h->root.root.string,
+			  input_bfd, input_section,
+			  rel->r_vaddr - input_section->vma,
+			  (info->unresolved_syms_in_objects
+			   == RM_GENERATE_ERROR))))
+		    return FALSE;
+		}
 	      if (h->root.type == bfd_link_hash_defined
 		  || h->root.type == bfd_link_hash_defweak)
 		{
@@ -3462,17 +3473,11 @@ xcoff_ppc_relocate_section (output_bfd, 
 			 + sec->output_offset);
 
 		}
-	      else if ((0 == (h->flags & (XCOFF_DEF_DYNAMIC | XCOFF_IMPORT)))
-		       && ! info->relocatable)
+	      else
 		{
-		  if (! ((*info->callbacks->undefined_symbol)
-			 (info, h->root.root.string, input_bfd, input_section,
-			  rel->r_vaddr - input_section->vma, TRUE)))
-		    return FALSE;
-
-		  /* Don't try to process the reloc.  It can't help, and
-		     it may generate another error.  */
-		  continue;
+		  BFD_ASSERT (info->relocatable
+			      || (h->flags & XCOFF_DEF_DYNAMIC) != 0
+			      || (h->flags & XCOFF_IMPORT) != 0);
 		}
 	    }
 	}
Index: bfd/coff64-rs6000.c
===================================================================
--- bfd/coff64-rs6000.c	2009-03-10 13:46:00.000000000 +0000
+++ bfd/coff64-rs6000.c	2009-03-10 13:46:23.000000000 +0000
@@ -1293,6 +1293,17 @@ xcoff64_ppc_relocate_section (output_bfd
 	    }
 	  else
 	    {
+	      if (info->unresolved_syms_in_objects != RM_IGNORE
+		  && (h->flags & XCOFF_WAS_UNDEFINED) != 0)
+		{
+		  if (! ((*info->callbacks->undefined_symbol)
+			 (info, h->root.root.string,
+			  input_bfd, input_section,
+			  rel->r_vaddr - input_section->vma,
+			  (info->unresolved_syms_in_objects
+			   == RM_GENERATE_ERROR))))
+		    return FALSE;
+		}
 	      if (h->root.type == bfd_link_hash_defined
 		  || h->root.type == bfd_link_hash_defweak)
 		{
@@ -1307,17 +1318,11 @@ xcoff64_ppc_relocate_section (output_bfd
 		  val = (sec->output_section->vma
 			 + sec->output_offset);
 		}
-	      else if ((0 == (h->flags & (XCOFF_DEF_DYNAMIC | XCOFF_IMPORT)))
-		       && ! info->relocatable)
+	      else
 		{
-		  if (! ((*info->callbacks->undefined_symbol)
-			 (info, h->root.root.string, input_bfd, input_section,
-			  rel->r_vaddr - input_section->vma, TRUE)))
-		    return FALSE;
-
-		  /* Don't try to process the reloc.  It can't help, and
-		     it may generate another error.  */
-		  continue;
+		  BFD_ASSERT (info->relocatable
+			      || (h->flags & XCOFF_DEF_DYNAMIC) != 0
+			      || (h->flags & XCOFF_IMPORT) != 0);
 		}
 	    }
 	}
Index: bfd/xcofflink.c
===================================================================
--- bfd/xcofflink.c	2009-03-10 13:43:53.000000000 +0000
+++ bfd/xcofflink.c	2009-03-10 13:46:23.000000000 +0000
@@ -1845,19 +1845,16 @@ #define N_BTSHFT n_btshft
 		  goto error_return;
 		}
 
-	      /* We identify all symbols which are called, so that we
-		 can create glue code for calls to functions imported
-		 from dynamic objects.  */
+	      /* We identify all function symbols that are the target
+		 of a relocation, so that we can create glue code for
+		 functions imported from dynamic objects.  */
  	      if (info->output_bfd->xvec == abfd->xvec
 		  && *rel_csect != bfd_und_section_ptr
-		  && (rel->r_type == R_BR
-		      || rel->r_type == R_RBR)
 		  && obj_xcoff_sym_hashes (abfd)[rel->r_symndx] != NULL)
 		{
 		  struct xcoff_link_hash_entry *h;
 
 		  h = obj_xcoff_sym_hashes (abfd)[rel->r_symndx];
-		  h->flags |= XCOFF_CALLED;
 		  /* If the symbol name starts with a period, it is
 		     the code of a function.  If the symbol is
 		     currently undefined, then add an undefined symbol
@@ -1890,11 +1887,12 @@ #define N_BTSHFT n_btshft
 			  hds = (struct xcoff_link_hash_entry *) bh;
 			}
 		      hds->flags |= XCOFF_DESCRIPTOR;
-		      BFD_ASSERT ((hds->flags & XCOFF_CALLED) == 0
-				  && (h->flags & XCOFF_DESCRIPTOR) == 0);
+		      BFD_ASSERT ((h->flags & XCOFF_DESCRIPTOR) == 0);
 		      hds->descriptor = h;
 		      h->descriptor = hds;
 		    }
+		  if (h->root.root.string[0] == '.')
+		    h->flags |= XCOFF_CALLED;
 		}
 	    }
 
@@ -2203,6 +2201,94 @@ _bfd_xcoff_bfd_link_add_symbols (bfd *ab
     }
 }
 \f
+/* If symbol H has not been interpreted as a function descriptor,
+   see whether it should be.  Set up its descriptor information if so.  */
+
+static bfd_boolean
+xcoff_find_function (struct bfd_link_info *info,
+		     struct xcoff_link_hash_entry *h)
+{
+  if ((h->flags & XCOFF_DESCRIPTOR) == 0
+      && h->root.root.string[0] != '.')
+    {
+      char *fnname;
+      struct xcoff_link_hash_entry *hfn;
+      bfd_size_type amt;
+
+      amt = strlen (h->root.root.string) + 2;
+      fnname = bfd_malloc (amt);
+      if (fnname == NULL)
+	return FALSE;
+      fnname[0] = '.';
+      strcpy (fnname + 1, h->root.root.string);
+      hfn = xcoff_link_hash_lookup (xcoff_hash_table (info),
+				    fnname, FALSE, FALSE, TRUE);
+      free (fnname);
+      if (hfn != NULL
+	  && hfn->smclas == XMC_PR
+	  && (hfn->root.type == bfd_link_hash_defined
+	      || hfn->root.type == bfd_link_hash_defweak))
+	{
+	  h->flags |= XCOFF_DESCRIPTOR;
+	  h->descriptor = hfn;
+	  hfn->descriptor = h;
+	}
+    }
+  return TRUE;
+}
+
+/* H is an imported symbol.  Set the import module's path, file and member
+   to IMPATH, IMPFILE and IMPMEMBER respectively.  All three are null if
+   no specific import module is specified.  */
+
+static bfd_boolean
+xcoff_set_import_path (struct bfd_link_info *info,
+		       struct xcoff_link_hash_entry *h,
+		       const char *imppath, const char *impfile,
+		       const char *impmember)
+{
+  unsigned int c;
+  struct xcoff_import_file **pp;
+
+  /* We overload the ldindx field to hold the l_ifile value for this
+     symbol.  */
+  BFD_ASSERT (h->ldsym == NULL);
+  BFD_ASSERT ((h->flags & XCOFF_BUILT_LDSYM) == 0);
+  if (imppath == NULL)
+    h->ldindx = -1;
+  else
+    {
+      /* We start c at 1 because the first entry in the import list is
+	 reserved for the library search path.  */
+      for (pp = &xcoff_hash_table (info)->imports, c = 1;
+	   *pp != NULL;
+	   pp = &(*pp)->next, ++c)
+	{
+	  if (strcmp ((*pp)->path, imppath) == 0
+	      && strcmp ((*pp)->file, impfile) == 0
+	      && strcmp ((*pp)->member, impmember) == 0)
+	    break;
+	}
+
+      if (*pp == NULL)
+	{
+	  struct xcoff_import_file *n;
+	  bfd_size_type amt = sizeof (* n);
+
+	  n = bfd_alloc (info->output_bfd, amt);
+	  if (n == NULL)
+	    return FALSE;
+	  n->next = NULL;
+	  n->path = imppath;
+	  n->file = impfile;
+	  n->member = impmember;
+	  *pp = n;
+	}
+      h->ldindx = c;
+    }
+  return TRUE;
+}
+\f
 /* Mark a symbol as not being garbage, including the section in which
    it is defined.  */
 
@@ -2213,6 +2299,136 @@ xcoff_mark_symbol (struct bfd_link_info 
     return TRUE;
 
   h->flags |= XCOFF_MARK;
+
+  /* If we're marking an undefined symbol, try find some way of
+     defining it.  */
+  if (!info->relocatable
+      && (h->flags & XCOFF_IMPORT) == 0
+      && (h->flags & XCOFF_DEF_REGULAR) == 0
+      && (h->root.type == bfd_link_hash_undefined
+	  || h->root.type == bfd_link_hash_undefweak))
+    {
+      /* First check whether this symbol can be interpreted as an
+	 undefined function descriptor for a defined function symbol.  */
+      if (!xcoff_find_function (info, h))
+	return FALSE;
+
+      if ((h->flags & XCOFF_DESCRIPTOR) != 0
+	  && (h->descriptor->root.type == bfd_link_hash_defined
+	      || h->descriptor->root.type == bfd_link_hash_defweak))
+	{
+	  /* This is a descriptor for a defined symbol, but the input
+	     objects have not defined the descriptor itself.  Fill in
+	     the definition automatically.
+
+	     Note that we do this even if we found a dynamic definition
+	     of H.  The local function definition logically overrides
+	     the dynamic one.  */
+	  asection *sec;
+
+	  sec = xcoff_hash_table (info)->descriptor_section;
+	  h->root.type = bfd_link_hash_defined;
+	  h->root.u.def.section = sec;
+	  h->root.u.def.value = sec->size;
+	  h->smclas = XMC_DS;
+	  h->flags |= XCOFF_DEF_REGULAR;
+
+	  /* The size of the function descriptor depends on whether this
+	     is xcoff32 (12) or xcoff64 (24).  */
+	  sec->size += bfd_xcoff_function_descriptor_size (sec->owner);
+
+	  /* A function descriptor uses two relocs: one for the
+	     associated code, and one for the TOC address.  */
+	  xcoff_hash_table (info)->ldrel_count += 2;
+	  sec->reloc_count += 2;
+
+	  /* Mark the function itself.  */
+	  if (!xcoff_mark_symbol (info, h->descriptor))
+	    return FALSE;
+
+	  /* We handle writing out the contents of the descriptor in
+	     xcoff_write_global_symbol.  */
+	}
+      else if ((h->flags & XCOFF_CALLED) != 0)
+	{
+	  /* This is a function symbol for which we need to create
+	     linkage code.  */
+	  asection *sec;
+	  struct xcoff_link_hash_entry *hds;
+
+	  /* Mark the descriptor (and its TOC section).  */
+	  hds = h->descriptor;
+	  BFD_ASSERT ((hds->root.type == bfd_link_hash_undefined
+		       || hds->root.type == bfd_link_hash_undefweak)
+		      && (hds->flags & XCOFF_DEF_REGULAR) == 0);
+	  if (!xcoff_mark_symbol (info, hds))
+	    return FALSE;
+
+	  /* Treat this symbol as undefined if the descriptor was.  */
+	  if ((hds->flags & XCOFF_WAS_UNDEFINED) != 0)
+	    h->flags |= XCOFF_WAS_UNDEFINED;
+
+	  /* Allocate room for the global linkage code itself.  */
+	  sec = xcoff_hash_table (info)->linkage_section;
+	  h->root.type = bfd_link_hash_defined;
+	  h->root.u.def.section = sec;
+	  h->root.u.def.value = sec->size;
+	  h->smclas = XMC_GL;
+	  h->flags |= XCOFF_DEF_REGULAR;
+	  sec->size += bfd_xcoff_glink_code_size (info->output_bfd);
+
+	  /* The global linkage code requires a TOC entry for the
+	     descriptor.  */
+	  if (hds->toc_section == NULL)
+	    {
+	      int byte_size;
+
+	      /* 32 vs 64
+		 xcoff32 uses 4 bytes in the toc.
+		 xcoff64 uses 8 bytes in the toc.  */
+	      if (bfd_xcoff_is_xcoff64 (info->output_bfd))
+		byte_size = 8;
+	      else if (bfd_xcoff_is_xcoff32 (info->output_bfd))
+		byte_size = 4;
+	      else
+		return FALSE;
+
+	      /* Allocate room in the fallback TOC section.  */
+	      hds->toc_section = xcoff_hash_table (info)->toc_section;
+	      hds->u.toc_offset = hds->toc_section->size;
+	      hds->toc_section->size += byte_size;
+	      if (!xcoff_mark (info, hds->toc_section))
+		return FALSE;
+
+	      /* Allocate room for a static and dynamic R_TOC
+		 relocation.  */
+	      ++xcoff_hash_table (info)->ldrel_count;
+	      ++hds->toc_section->reloc_count;
+
+	      /* Set the index to -2 to force this symbol to
+		 get written out.  */
+	      hds->indx = -2;
+	      hds->flags |= XCOFF_SET_TOC | XCOFF_LDREL;
+	    }
+	}
+      else if ((h->flags & XCOFF_DEF_DYNAMIC) == 0)
+	{
+	  /* Record that the symbol was undefined, then import it.
+	     -brtl links use a special fake import file.  */
+	  h->flags |= XCOFF_WAS_UNDEFINED | XCOFF_IMPORT;
+	  if (xcoff_hash_table (info)->rtld)
+	    {
+	      if (!xcoff_set_import_path (info, h, "", "..", ""))
+		return FALSE;
+	    }
+	  else
+	    {
+	      if (!xcoff_set_import_path (info, h, NULL, NULL, NULL))
+		return FALSE;
+	    }
+	}
+    }
+
   if (h->root.type == bfd_link_hash_defined
       || h->root.type == bfd_link_hash_defweak)
     {
@@ -2320,15 +2536,9 @@ xcoff_mark (struct bfd_link_info *info, 
 		      || h->root.type == bfd_link_hash_defined
 		      || h->root.type == bfd_link_hash_defweak
 		      || h->root.type == bfd_link_hash_common
-		      || ((h->flags & XCOFF_CALLED) != 0
-			  && (h->root.type == bfd_link_hash_undefined
-			      || h->root.type == bfd_link_hash_undefweak)
-			  && h->root.root.string[0] == '.'
-			  && h->descriptor != NULL
-			  && ((h->descriptor->flags & XCOFF_DEF_DYNAMIC) != 0
-			      || ((h->descriptor->flags & XCOFF_IMPORT) != 0
-				  && (h->descriptor->flags
-				      & XCOFF_DEF_REGULAR) == 0))))
+		      /* We will always provide a local definition of
+			 function symbols.  */
+		      || (h->flags & XCOFF_CALLED) != 0)
 		    break;
 		  /* Fall through.  */
 		case R_POS:
@@ -2483,8 +2693,7 @@ bfd_xcoff_import_symbol (bfd *output_bfd
 	      hds->root.u.undef.abfd = h->root.u.undef.abfd;
 	    }
 	  hds->flags |= XCOFF_DESCRIPTOR;
-	  BFD_ASSERT ((hds->flags & XCOFF_CALLED) == 0
-		      && (h->flags & XCOFF_DESCRIPTOR) == 0);
+	  BFD_ASSERT ((h->flags & XCOFF_DESCRIPTOR) == 0);
 	  hds->descriptor = h;
 	  h->descriptor = hds;
 	}
@@ -2516,46 +2725,8 @@ bfd_xcoff_import_symbol (bfd *output_bfd
       h->root.u.def.value = val;
     }
 
-  /* We overload the ldindx field to hold the l_ifile value for this
-     symbol.  */
-  BFD_ASSERT (h->ldsym == NULL);
-  BFD_ASSERT ((h->flags & XCOFF_BUILT_LDSYM) == 0);
-  if (imppath == NULL)
-    h->ldindx = -1;
-  else
-    {
-      unsigned int c;
-      struct xcoff_import_file **pp;
-
-      /* We start c at 1 because the first entry in the import list is
-	 reserved for the library search path.  */
-      for (pp = &xcoff_hash_table (info)->imports, c = 1;
-	   *pp != NULL;
-	   pp = &(*pp)->next, ++c)
-	{
-	  if (strcmp ((*pp)->path, imppath) == 0
-	      && strcmp ((*pp)->file, impfile) == 0
-	      && strcmp ((*pp)->member, impmember) == 0)
-	    break;
-	}
-
-      if (*pp == NULL)
-	{
-	  struct xcoff_import_file *n;
-	  bfd_size_type amt = sizeof (* n);
-
-	  n = bfd_alloc (output_bfd, amt);
-	  if (n == NULL)
-	    return FALSE;
-	  n->next = NULL;
-	  n->path = imppath;
-	  n->file = impfile;
-	  n->member = impmember;
-	  *pp = n;
-	}
-
-      h->ldindx = c;
-    }
+  if (!xcoff_set_import_path (info, h, imppath, impfile, impmember))
+    return FALSE;
 
   return TRUE;
 }
@@ -2577,34 +2748,6 @@ bfd_xcoff_export_symbol (bfd *output_bfd
   /* FIXME: I'm not at all sure what syscall is supposed to mean, so
      I'm just going to ignore it until somebody explains it.  */
 
-  /* See if this is a function descriptor.  It may be one even though
-     it is not so marked.  */
-  if ((h->flags & XCOFF_DESCRIPTOR) == 0
-      && h->root.root.string[0] != '.')
-    {
-      char *fnname;
-      struct xcoff_link_hash_entry *hfn;
-      bfd_size_type amt = strlen (h->root.root.string) + 2;
-
-      fnname = bfd_malloc (amt);
-      if (fnname == NULL)
-	return FALSE;
-      fnname[0] = '.';
-      strcpy (fnname + 1, h->root.root.string);
-      hfn = xcoff_link_hash_lookup (xcoff_hash_table (info),
-				    fnname, FALSE, FALSE, TRUE);
-      free (fnname);
-      if (hfn != NULL
-	  && hfn->smclas == XMC_PR
-	  && (hfn->root.type == bfd_link_hash_defined
-	      || hfn->root.type == bfd_link_hash_defweak))
-	{
-	  h->flags |= XCOFF_DESCRIPTOR;
-	  h->descriptor = hfn;
-	  hfn->descriptor = h;
-	}
-    }
-
   /* Make sure we don't garbage collect this symbol.  */
   if (! xcoff_mark_symbol (info, h))
     return FALSE;
@@ -2767,115 +2910,16 @@ xcoff_build_ldsyms (struct xcoff_link_ha
 	      != ldinfo->info->output_bfd->xvec)))
     h->flags |= XCOFF_MARK;
 
-  /* If this symbol is called and defined in a dynamic object, or it
-     is imported, then we need to set up global linkage code for it.
-     (Unless we did garbage collection and we didn't need this
-     symbol.)  */
-  if ((h->flags & XCOFF_CALLED) != 0
-      && (h->root.type == bfd_link_hash_undefined
-	  || h->root.type == bfd_link_hash_undefweak)
-      && h->root.root.string[0] == '.'
-      && h->descriptor != NULL
-      && ((h->descriptor->flags & XCOFF_DEF_DYNAMIC) != 0
-	  || ((h->descriptor->flags & XCOFF_IMPORT) != 0
-	      && (h->descriptor->flags & XCOFF_DEF_REGULAR) == 0))
-      && (! xcoff_hash_table (ldinfo->info)->gc
-	  || (h->flags & XCOFF_MARK) != 0))
-    {
-      asection *sec;
-      struct xcoff_link_hash_entry *hds;
-
-      sec = xcoff_hash_table (ldinfo->info)->linkage_section;
-      h->root.type = bfd_link_hash_defined;
-      h->root.u.def.section = sec;
-      h->root.u.def.value = sec->size;
-      h->smclas = XMC_GL;
-      h->flags |= XCOFF_DEF_REGULAR;
-      sec->size += bfd_xcoff_glink_code_size(ldinfo->output_bfd);
-
-      /* The global linkage code requires a TOC entry for the
-	 descriptor.  */
-      hds = h->descriptor;
-      BFD_ASSERT ((hds->root.type == bfd_link_hash_undefined
-		   || hds->root.type == bfd_link_hash_undefweak)
-		  && (hds->flags & XCOFF_DEF_REGULAR) == 0);
-      hds->flags |= XCOFF_MARK;
-      if (hds->toc_section == NULL)
-	{
-	  int byte_size;
-
-	  /* 32 vs 64
-	     xcoff32 uses 4 bytes in the toc.
-	     xcoff64 uses 8 bytes in the toc.  */
-	  if (bfd_xcoff_is_xcoff64 (ldinfo->output_bfd))
-	    byte_size = 8;
-	  else if (bfd_xcoff_is_xcoff32 (ldinfo->output_bfd))
-	    byte_size = 4;
-	  else
-	    return FALSE;
-
-	  hds->toc_section = xcoff_hash_table (ldinfo->info)->toc_section;
-	  hds->u.toc_offset = hds->toc_section->size;
-	  hds->toc_section->size += byte_size;
-	  ++xcoff_hash_table (ldinfo->info)->ldrel_count;
-	  ++hds->toc_section->reloc_count;
-	  hds->indx = -2;
-	  hds->flags |= XCOFF_SET_TOC | XCOFF_LDREL;
-
-	  /* We need to call xcoff_build_ldsyms recursively here,
-	     because we may already have passed hds on the traversal.  */
-	  xcoff_build_ldsyms (hds, p);
-	}
-    }
-
   /* If this symbol is exported, but not defined, we need to try to
      define it.  */
   if ((h->flags & XCOFF_EXPORT) != 0
-      && (h->flags & XCOFF_IMPORT) == 0
-      && (h->flags & XCOFF_DEF_REGULAR) == 0
-      && (h->flags & XCOFF_DEF_DYNAMIC) == 0
-      && (h->root.type == bfd_link_hash_undefined
-	  || h->root.type == bfd_link_hash_undefweak))
+      && (h->flags & XCOFF_WAS_UNDEFINED) != 0)
     {
-      if ((h->flags & XCOFF_DESCRIPTOR) != 0
-	  && (h->descriptor->root.type == bfd_link_hash_defined
-	      || h->descriptor->root.type == bfd_link_hash_defweak))
-	{
-	  asection *sec;
-
-	  /* This is an undefined function descriptor associated with
-	     a defined entry point.  We can build up a function
-	     descriptor ourselves.  Believe it or not, the AIX linker
-	     actually does this, and there are cases where we need to
-	     do it as well.  */
-	  sec = xcoff_hash_table (ldinfo->info)->descriptor_section;
-	  h->root.type = bfd_link_hash_defined;
-	  h->root.u.def.section = sec;
-	  h->root.u.def.value = sec->size;
-	  h->smclas = XMC_DS;
-	  h->flags |= XCOFF_DEF_REGULAR;
-
-	  /* The size of the function descriptor depends if this is an
-	     xcoff32 (12) or xcoff64 (24).  */
-	  sec->size +=
-	    bfd_xcoff_function_descriptor_size(ldinfo->output_bfd);
-
-	  /* A function descriptor uses two relocs: one for the
-	     associated code, and one for the TOC address.  */
-	  xcoff_hash_table (ldinfo->info)->ldrel_count += 2;
-	  sec->reloc_count += 2;
-
-	  /* We handle writing out the contents of the descriptor in
-	     xcoff_write_global_symbol.  */
-	}
-      else
-	{
-	  (*_bfd_error_handler)
-	    (_("warning: attempt to export undefined symbol `%s'"),
-	     h->root.root.string);
-	  h->ldsym = NULL;
-	  return TRUE;
-	}
+      (*_bfd_error_handler)
+	(_("warning: attempt to export undefined symbol `%s'"),
+	 h->root.root.string);
+      h->ldsym = NULL;
+      return TRUE;
     }
 
   /* If this is still a common symbol, and it wasn't garbage
@@ -3017,6 +3061,7 @@ bfd_xcoff_size_dynamic_sections (bfd *ou
 
   xcoff_hash_table (info)->file_align = file_align;
   xcoff_hash_table (info)->textro = textro;
+  xcoff_hash_table (info)->rtld = rtld;
 
   hentry = NULL;
   if (entry != NULL)
@@ -4318,7 +4363,6 @@ #define N_BTSHFT n_btshft
 	    {
 	      struct xcoff_link_hash_entry *h = NULL;
 	      struct internal_ldrel ldrel;
-	      bfd_boolean quiet;
 
 	      *rel_hash = NULL;
 
@@ -4451,7 +4495,6 @@ #define N_BTSHFT n_btshft
 		    }
 		}
 
-	      quiet = FALSE;
 	      switch (irel->r_type)
 		{
 		default:
@@ -4507,17 +4550,7 @@ #define N_BTSHFT n_btshft
 		    }
 		  else
 		    {
-		      if (! finfo->info->relocatable
-			  && (h->flags & XCOFF_DEF_DYNAMIC) == 0
-			  && (h->flags & XCOFF_IMPORT) == 0)
-			{
-			  /* We already called the undefined_symbol
-			     callback for this relocation, in
-			     _bfd_ppc_xcoff_relocate_section.  Don't
-			     issue any more warnings.  */
-			  quiet = TRUE;
-			}
-		      if (h->ldindx < 0 && ! quiet)
+		      if (h->ldindx < 0)
 			{
 			  (*_bfd_error_handler)
 			    (_("%B: `%s' in loader reloc but not loader sym"),
@@ -4531,8 +4564,7 @@ #define N_BTSHFT n_btshft
 		  ldrel.l_rtype = (irel->r_size << 8) | irel->r_type;
 		  ldrel.l_rsecnm = o->output_section->target_index;
 		  if (xcoff_hash_table (finfo->info)->textro
-		      && strcmp (o->output_section->name, ".text") == 0
-		      && ! quiet)
+		      && strcmp (o->output_section->name, ".text") == 0)
 		    {
 		      (*_bfd_error_handler)
 			(_("%B: loader reloc in read-only section %A"),
Index: ld/emultempl/aix.em
===================================================================
--- ld/emultempl/aix.em	2009-03-10 13:43:34.000000000 +0000
+++ ld/emultempl/aix.em	2009-03-10 13:46:23.000000000 +0000
@@ -379,11 +379,13 @@ gld${EMULATION_NAME}_handle_option (int 
       break;
 
     case OPTION_ERNOTOK:
-      force_make_executable = FALSE;
+      link_info.unresolved_syms_in_objects = RM_GENERATE_ERROR;
+      link_info.unresolved_syms_in_shared_libs = RM_GENERATE_ERROR;
       break;
 
     case OPTION_EROK:
-      force_make_executable = TRUE;
+      link_info.unresolved_syms_in_objects = RM_IGNORE;
+      link_info.unresolved_syms_in_shared_libs = RM_IGNORE;
       break;
 
     case OPTION_EXPORT:
Index: ld/testsuite/ld-powerpc/aix-glink-1.ex
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-glink-1.ex	2009-03-10 13:46:23.000000000 +0000
@@ -0,0 +1,2 @@
+f2
+foo
Index: ld/testsuite/ld-powerpc/aix-glink-1.s
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-glink-1.s	2009-03-10 13:46:23.000000000 +0000
@@ -0,0 +1,21 @@
+	.toc
+	.globl	.f1
+	.csect	.f1[PR]
+.f1:
+	blr
+
+	.globl	.f2
+	.csect	.f2[PR]
+.f2:
+	bl	.f3
+
+	.globl	.f3
+	.csect	.f3[PR]
+.f3:
+	blr
+
+	.globl	foo
+	.csect	foo[RW]
+foo:
+	.long	f1
+	.long	.ext
Index: ld/testsuite/ld-powerpc/aix-glink-1-32.dd
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-glink-1-32.dd	2009-03-10 13:46:23.000000000 +0000
@@ -0,0 +1,44 @@
+
+.*
+
+
+Disassembly of section \.text:
+
+10000000 <\.f1>:
+10000000:	4e 80 00 20 	br
+
+10000004 <\.f2>:
+10000004:	48 00 00 05 	bl      10000008 <\.f3>
+
+10000008 <\.f3>:
+10000008:	4e 80 00 20 	br
+
+1000000c <\.ext>:
+1000000c:	81 82 00 00 	l       r12,0\(r2\)
+10000010:	90 41 00 14 	st      r2,20\(r1\)
+10000014:	80 0c 00 00 	l       r0,0\(r12\)
+10000018:	80 4c 00 04 	l       r2,4\(r12\)
+1000001c:	7c 09 03 a6 	mtctr   r0
+10000020:	4e 80 04 20 	bctr
+10000024:	00 00 00 00 	\.long 0x0
+10000028:	00 0c 80 00 	\.long 0xc8000
+1000002c:	00 00 00 00 	\.long 0x0
+
+Disassembly of section \.data:
+
+20000000 <foo>:
+20000000:	20 00 00 08 	.*
+20000004:	10 00 00 0c 	.*
+
+20000008 <f1>:
+20000008:	10 00 00 00 	.*
+2000000c:	20 00 00 20 	.*
+20000010:	00 00 00 00 	.*
+
+20000014 <f2>:
+20000014:	10 00 00 04 	.*
+20000018:	20 00 00 20 	.*
+2000001c:	00 00 00 00 	.*
+
+20000020 <TOC>:
+	\.\.\.
Index: ld/testsuite/ld-powerpc/aix-glink-1-64.dd
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-glink-1-64.dd	2009-03-10 13:46:23.000000000 +0000
@@ -0,0 +1,49 @@
+
+.*
+
+
+Disassembly of section \.text:
+
+0000000010000000 <\.f1>:
+    10000000:	4e 80 00 20 	blr
+
+0000000010000004 <\.f2>:
+    10000004:	48 00 00 05 	bl      10000008 <\.f3>
+
+0000000010000008 <\.f3>:
+    10000008:	4e 80 00 20 	blr
+
+000000001000000c <\.ext>:
+    1000000c:	e9 82 00 00 	ld      r12,0\(r2\)
+    10000010:	f8 41 00 28 	std     r2,40\(r1\)
+    10000014:	e8 0c 00 00 	ld      r0,0\(r12\)
+    10000018:	e8 4c 00 08 	ld      r2,8\(r12\)
+    1000001c:	7c 09 03 a6 	mtctr   r0
+    10000020:	4e 80 04 20 	bctr
+    10000024:	00 00 00 00 	\.long 0x0
+    10000028:	00 0c a0 00 	\.long 0xca000
+    1000002c:	00 00 00 00 	\.long 0x0
+    10000030:	00 00 00 18 	\.long 0x18
+
+Disassembly of section \.data:
+
+0000000020000000 <foo>:
+    20000000:	20 00 00 08 	.*
+    20000004:	10 00 00 0c 	.*
+
+0000000020000008 <f1>:
+    20000008:	00 00 00 00 	.*
+    2000000c:	10 00 00 00 	.*
+    20000010:	00 00 00 00 	.*
+    20000014:	20 00 00 38 	.*
+	\.\.\.
+
+0000000020000020 <f2>:
+    20000020:	00 00 00 00 	.*
+    20000024:	10 00 00 04 	.*
+    20000028:	00 00 00 00 	.*
+    2000002c:	20 00 00 38 	.*
+	\.\.\.
+
+0000000020000038 <TOC>:
+	\.\.\.
Index: ld/testsuite/ld-powerpc/aix-glink-1-32.d
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-glink-1-32.d	2009-03-10 13:46:23.000000000 +0000
@@ -0,0 +1,5 @@
+#name: Glink test 1 (error) (32-bit)
+#source: aix-glink-1.s
+#as: -a32
+#ld: -b32 -bM:SRE -bnogc
+#error: undefined reference to `\.ext'
Index: ld/testsuite/ld-powerpc/aix-glink-1-64.d
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-glink-1-64.d	2009-03-10 13:46:23.000000000 +0000
@@ -0,0 +1,5 @@
+#name: Glink test 1 (error) (64-bit)
+#source: aix-glink-1.s
+#as: -a64
+#ld: -b64 -bM:SRE -bnogc
+#error: undefined reference to `\.ext'
Index: ld/testsuite/ld-powerpc/aix52.exp
===================================================================
--- ld/testsuite/ld-powerpc/aix52.exp	2009-03-10 13:46:00.000000000 +0000
+++ ld/testsuite/ld-powerpc/aix52.exp	2009-03-10 13:46:23.000000000 +0000
@@ -91,6 +91,12 @@ set aix52tests {
      "" {aix-core-sec-3.s}
      {{objdump -h aix-core-sec-3.hd}}
      "aix-core-sec-3.so"}
+
+    {"Glink test 1"
+     "-shared -bE:aix-glink-1.ex --unresolved-symbols=ignore-all"
+     "" {aix-glink-1.s}
+     {{objdump {-D -j.text -j.data} aix-glink-1-SIZE.dd}}
+     "aix-glink-1.so"}
 }
 
 foreach test $aix52tests {

^ permalink raw reply	[flat|nested] 50+ messages in thread

* [10/21] Fix the csect handling of XTY_ER symbols
  2009-03-10 13:58 [0/21] Add support for AIX 6 Richard Sandiford
                   ` (9 preceding siblings ...)
  2009-03-10 14:22 ` [9/21] Implicitly import undefined symbols Richard Sandiford
@ 2009-03-10 14:25 ` Richard Sandiford
  2009-03-13 14:57   ` Nick Clifton
  2009-03-10 14:29 ` [11/21] Cope with TOCs bigger than 32k, and other TC0 fixes Richard Sandiford
                   ` (10 subsequent siblings)
  21 siblings, 1 reply; 50+ messages in thread
From: Richard Sandiford @ 2009-03-10 14:25 UTC (permalink / raw)
  To: binutils

xcoff_mark goes through the section's relocations and marks both the
target symbol's link entry _and_ its csect:

	      h = obj_xcoff_sym_hashes (sec->owner)[rel->r_symndx];
	      if (h != NULL
		  && (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
		  && (rsec->flags & SEC_MARK) == 0)
		{
		  if (! xcoff_mark (info, rsec))
		    return FALSE;
		}

This is wrong in some cases, and I'll fix it later in the series.
However, the current code does show up another problem: XTY_ER
(external reference) symbols are given the same csect as the previous
symbol, even though that csect is usually completely unrelated.
For example, suppose we have two functions .f1 and .f2 that both
call .bar.  The symbol table might look like:

   SD PR .f1
   SD PR .f2
   ER PR .bar

At the moment, we'll say that .bar's csect is .f2.  This means that
if we mark .f1, and thus mark its relocation against .bar, we'll wrongly
think that we need to keep .f2 as well.

I think the most natural fix is to set the "csect" of an undefined
external reference to bfd_und_section_ptr and the "csect" of an
absolute external reference to bfd_abs_section_ptr.

We keep track of the first and last symbol index associated with
each csect.  The change above means that we can't always be sure
that every symbol in that range has the same csect, so the mark
routines should check this explicitly.  (I think that's good
practice anyway.)

The code that records the last symbol index is rather convoluted.
We are only interested in indices that have a linker hash entry
associated with them, and only one part of xcoff_link_add_symbols
establishes such a link.

The changes in this patch are covered by tests in later patches.

OK to install?

Richard


bfd/
	* libcoff-in.h (xcoff_section_tdata): Update commentary.
	* libcoff.h: Regenerate.
	* xcofflink.c (xcoff_link_add_symbols): Set the csect of XTY_ER
	symbols to bfd_und_section_ptr or bfd_abs_section_ptr, rather than
	the previous symbol's csect.  Treat last_symndx as an inclusive value
	and simplify its handling.
	(xcoff_mark): Treat last_symndx as an inclusive value.  Only mark
	symbols with the right csect.  Don't mark rsec when processing
	relocations against undefined or absolute sections.  
	(bfd_xcoff_size_dynamic_sections): Don't check the SEC_MARK flag
	of bfd_und_section_ptr.
	(xcoff_link_input_bfd): Likewise.

Index: bfd/libcoff-in.h
===================================================================
--- bfd/libcoff-in.h	2009-03-10 13:38:53.000000000 +0000
+++ bfd/libcoff-in.h	2009-03-10 13:46:38.000000000 +0000
@@ -215,8 +215,7 @@ struct xcoff_section_tdata
   /* The lineno_count field for the enclosing section, because we are
      going to clobber it there.  */
   unsigned int lineno_count;
-  /* The first and one past the last symbol indices for symbols used
-     by this csect.  */
+  /* The first and last symbol indices for symbols used by this csect.  */
   unsigned long first_symndx;
   unsigned long last_symndx;
 };
Index: bfd/libcoff.h
===================================================================
--- bfd/libcoff.h	2009-03-10 13:38:53.000000000 +0000
+++ bfd/libcoff.h	2009-03-10 13:46:38.000000000 +0000
@@ -219,8 +219,7 @@ struct xcoff_section_tdata
   /* The lineno_count field for the enclosing section, because we are
      going to clobber it there.  */
   unsigned int lineno_count;
-  /* The first and one past the last symbol indices for symbols used
-     by this csect.  */
+  /* The first and last symbol indices for symbols used by this csect.  */
   unsigned long first_symndx;
   unsigned long last_symndx;
 };
Index: bfd/xcofflink.c
===================================================================
--- bfd/xcofflink.c	2009-03-10 13:46:23.000000000 +0000
+++ bfd/xcofflink.c	2009-03-10 13:46:38.000000000 +0000
@@ -1092,17 +1092,9 @@ #define N_BTSHFT n_btshft
 	     Normally csect is a .pr, .rw  etc. created in the loop
 	     If C_FILE or first time, handle special
 
-	     Advance esym, sym_hash, csect_hash ptr's
-	     Keep track of the last_symndx for the current file.  */
-	  if (sym.n_sclass == C_FILE && csect != NULL)
-	    {
-	      xcoff_section_data (abfd, csect)->last_symndx =
-		((esym
-		  - (bfd_byte *) obj_coff_external_syms (abfd))
-		 / symesz);
-	      csect = NULL;
-	    }
-
+	     Advance esym, sym_hash, csect_hash ptrs.  */
+	  if (sym.n_sclass == C_FILE)
+	    csect = NULL;
 	  if (csect != NULL)
 	    *csect_cache = csect;
 	  else if (first_csect == NULL || sym.n_sclass == C_FILE)
@@ -1253,13 +1245,6 @@ #define N_BTSHFT n_btshft
 	  break;
 
 	case XTY_SD:
-	  /* This is a csect definition.  */
-	  if (csect != NULL)
-	    {
-	      xcoff_section_data (abfd, csect)->last_symndx =
-		((esym - (bfd_byte *) obj_coff_external_syms (abfd)) / symesz);
-	    }
-
 	  csect = NULL;
 	  csect_index = -(unsigned) 1;
 
@@ -1541,14 +1526,6 @@ #define N_BTSHFT n_btshft
 	     named .tocbss, and rely on the linker script to put that
 	     in the TOC area.  */
 
-	  if (csect != NULL)
-	    {
-	      xcoff_section_data (abfd, csect)->last_symndx =
-		((esym
-		  - (bfd_byte *) obj_coff_external_syms (abfd))
-		 / symesz);
-	    }
-
 	  if (aux.x_csect.x_smclas == XMC_TD)
 	    {
 	      /* The linker script puts the .td section in the data
@@ -1805,7 +1782,15 @@ #define N_BTSHFT n_btshft
 	    }
 	}
 
-      *csect_cache = csect;
+      if (smtyp == XTY_ER)
+	*csect_cache = section;
+      else
+	{
+	  *csect_cache = csect;
+	  if (csect != NULL)
+	    xcoff_section_data (abfd, csect)->last_symndx
+	      = (esym - (bfd_byte *) obj_coff_external_syms (abfd)) / symesz;
+	}
 
       esym += (sym.n_numaux + 1) * symesz;
       sym_hash += sym.n_numaux + 1;
@@ -2472,26 +2457,24 @@ xcoff_mark (struct bfd_link_info *info, 
       && coff_section_data (sec->owner, sec) != NULL
       && xcoff_section_data (sec->owner, sec) != NULL)
     {
-      struct xcoff_link_hash_entry **hp, **hpend;
+      struct xcoff_link_hash_entry **syms;
       struct internal_reloc *rel, *relend;
+      asection **csects;
+      unsigned long i, first, last;
 
       /* Mark all the symbols in this section.  */
-      hp = (obj_xcoff_sym_hashes (sec->owner)
-	    + xcoff_section_data (sec->owner, sec)->first_symndx);
-      hpend = (obj_xcoff_sym_hashes (sec->owner)
-	       + xcoff_section_data (sec->owner, sec)->last_symndx);
-      for (; hp < hpend; hp++)
-	{
-	  struct xcoff_link_hash_entry *h;
-
-	  h = *hp;
-	  if (h != NULL
-	      && (h->flags & XCOFF_MARK) == 0)
-	    {
-	      if (! xcoff_mark_symbol (info, h))
-		return FALSE;
-	    }
-	}
+      syms = obj_xcoff_sym_hashes (sec->owner);
+      csects = xcoff_data (sec->owner)->csects;
+      first = xcoff_section_data (sec->owner, sec)->first_symndx;
+      last = xcoff_section_data (sec->owner, sec)->last_symndx;
+      for (i = first; i <= last; i++)
+	if (csects[i] == sec
+	    && syms[i] != NULL
+	    && (syms[i]->flags & XCOFF_MARK) == 0)
+	  {
+	    if (!xcoff_mark_symbol (info, syms[i]))
+	      return FALSE;
+	  }
 
       /* Look through the section relocs.  */
       if ((sec->flags & SEC_RELOC) != 0
@@ -2521,6 +2504,8 @@ xcoff_mark (struct bfd_link_info *info, 
 
 	      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)
 		{
 		  if (! xcoff_mark (info, rsec))
@@ -3358,8 +3343,9 @@ bfd_xcoff_size_dynamic_sections (bfd *ou
 	      if (sym._n._n_n._n_zeroes == 0
 		  && *csectpp != NULL
 		  && (! gc
-		      || ((*csectpp)->flags & SEC_MARK) != 0
-		      || *csectpp == bfd_abs_section_ptr)
+		      || bfd_is_abs_section (*csectpp)
+		      || bfd_is_und_section (*csectpp)
+		      || ((*csectpp)->flags & SEC_MARK) != 0)
 		  && bfd_coff_symname_in_debug (sub, &sym))
 		{
 		  char *name;
@@ -3648,8 +3634,9 @@ #define N_BTSHFT n_btshft
 	 symbol.  */
       if (! skip
 	  && xcoff_hash_table (finfo->info)->gc
-	  && ((*csectpp)->flags & SEC_MARK) == 0
-	  && *csectpp != bfd_abs_section_ptr)
+	  && !bfd_is_abs_section (*csectpp)
+	  && !bfd_is_und_section (*csectpp)
+	  && ((*csectpp)->flags & SEC_MARK) == 0)
 	skip = TRUE;
 
       /* An XCOFF linker always skips C_STAT symbols.  */

^ permalink raw reply	[flat|nested] 50+ messages in thread

* [11/21] Cope with TOCs bigger than 32k, and other TC0 fixes
  2009-03-10 13:58 [0/21] Add support for AIX 6 Richard Sandiford
                   ` (10 preceding siblings ...)
  2009-03-10 14:25 ` [10/21] Fix the csect handling of XTY_ER symbols Richard Sandiford
@ 2009-03-10 14:29 ` Richard Sandiford
  2009-03-13 14:59   ` Nick Clifton
  2009-03-10 14:34 ` [12/21] Trim XCOFF symbols earlier in the link process Richard Sandiford
                   ` (9 subsequent siblings)
  21 siblings, 1 reply; 50+ messages in thread
From: Richard Sandiford @ 2009-03-10 14:29 UTC (permalink / raw)
  To: binutils

xcoff_link_input_bfd decides on the fly whether to keep each input
XCOFF symbol.  This leads to a serious bug that I'll come to in a
few patches' time.

This patch deals with the handling of XMC_TC0 (TOC anchor) symbols.
At the moment, the output XMC_TC0 symbol is taken from one of the
input XMC_TC0 symbols.  One problem with this is that we can create
TOC entries and TC0 references automatically, so we should be prepared
to create the TC0 symbol automatically too.  More importantly, the current
code tries to cope with TOCs bigger than 32k:

      /* We skip all but the first TOC anchor.  */
      if (! skip
	  && isymp->n_sclass == C_HIDEXT
	  && aux.x_csect.x_smclas == XMC_TC0)
	{
	  if (finfo->toc_symindx != -1)
	    skip = TRUE;
	  else
	    {
	      bfd_vma tocval, tocend;
	      bfd *inp;

	      tocval = ((*csectpp)->output_section->vma
			+ (*csectpp)->output_offset
			+ isym.n_value
			- (*csectpp)->vma);

	      /* We want to find out if tocval is a good value to use
		 as the TOC anchor--that is, whether we can access all
		 of the TOC using a 16 bit offset from tocval.  This
		 test assumes that the TOC comes at the end of the
		 output section, as it does in the default linker
		 script.  */
	      tocend = ((*csectpp)->output_section->vma
			+ (*csectpp)->output_section->size);
	      for (inp = finfo->info->input_bfds;
		   inp != NULL;
		   inp = inp->link_next)
		{

		  for (o = inp->sections; o != NULL; o = o->next)
		    if (strcmp (o->name, ".tocbss") == 0)
		      {
			bfd_vma new_toc_end;
			new_toc_end = (o->output_section->vma
				       + o->output_offset
				       + o->size);
			if (new_toc_end > tocend)
			  tocend = new_toc_end;
		      }

		}

	      if (tocval + 0x10000 < tocend)
		{
		  (*_bfd_error_handler)
		    (_("TOC overflow: 0x%lx > 0x10000; try -mminimal-toc when compiling"),
		     (unsigned long) (tocend - tocval));
		  bfd_set_error (bfd_error_file_too_big);
		  return FALSE;
		}

	      if (tocval + 0x8000 < tocend)
		{
		  bfd_vma tocadd;

		  tocadd = tocend - (tocval + 0x8000);
		  tocval += tocadd;
		  isym.n_value += tocadd;
		}

	      finfo->toc_symindx = output_index;
	      xcoff_data (finfo->output_bfd)->toc = tocval;
	      xcoff_data (finfo->output_bfd)->sntoc =
		(*csectpp)->output_section->target_index;
	      require = TRUE;

	    }
	}

But the default linker script links sections in this order:

    *(.tc0)
    *(.tc)
    *(.td)

so all the XMC_TC0 csects will be linked at the same address, at the
beginning of the TOC.  We therefore fail to link when the TOC is
bigger than 32k.

We could probably improve things by using:

    *(.tc0 .tc)
    *(.td)

or:

    *(.tc0 .tc .td)

instead of the current section list, but in general, the best place
for the anchor might be _between_ the TOC csects of an input object.

This patch uses a separate function to create a TOC anchor from scratch.

OK to install?

Richard


bfd/
	* xcofflink.c: (xcoff_mark_symbol): Mark the TOC section when
	creating a descriptor.
	(xcoff_sweep): Don't mark toc_section unless it's needed.
	(bfd_xcoff_size_dynamic_sections): Skip the toc_section
	when marking every bfd.
	(xcoff_link_input_bfd): Skip all TOC anchors.
	(xcoff_toc_section_p, xcoff_find_tc0): New functions.
	(_bfd_xcoff_bfd_final_link): Don't set the output bfd's TOC anchor
	to -1; call xcoff_find_tc0 instead.

ld/testsuite/
	* ld-powerpc/aix-toc-1.ex, ld-powerpc/aix-toc-1a.s,
	ld-powerpc/aix-toc-1b.s, ld-powerpc/aix-toc-1-32.dd,
	ld-powerpc/aix-toc-1-64.dd: New tests.
	* ld-powerpc/aix52.exp: Run them.

Index: bfd/xcofflink.c
===================================================================
--- bfd/xcofflink.c	2009-03-10 13:46:38.000000000 +0000
+++ bfd/xcofflink.c	2009-03-10 13:46:58.000000000 +0000
@@ -2331,6 +2331,11 @@ xcoff_mark_symbol (struct bfd_link_info 
 	  if (!xcoff_mark_symbol (info, h->descriptor))
 	    return FALSE;
 
+	  /* Mark the TOC section, so that we get an anchor
+	     to relocate against.  */
+	  if (!xcoff_mark (info, xcoff_hash_table (info)->toc_section))
+	    return FALSE;
+
 	  /* We handle writing out the contents of the descriptor in
 	     xcoff_write_global_symbol.  */
 	}
@@ -2590,7 +2595,6 @@ xcoff_sweep (struct bfd_link_info *info)
 		  || o == xcoff_hash_table (info)->debug_section
 		  || o == xcoff_hash_table (info)->loader_section
 		  || o == xcoff_hash_table (info)->linkage_section
-		  || o == xcoff_hash_table (info)->toc_section
 		  || o == xcoff_hash_table (info)->descriptor_section
 		  || strcmp (o->name, ".debug") == 0)
 		o->flags |= SEC_MARK;
@@ -3126,7 +3130,12 @@ bfd_xcoff_size_dynamic_sections (bfd *ou
 
 	  for (o = sub->sections; o != NULL; o = o->next)
 	    {
-	      if ((o->flags & SEC_MARK) == 0)
+	      /* We shouldn't unconditionaly mark the TOC section.
+		 The output file should only have a TOC if either
+		 (a) one of the input files did or (b) we end up
+		 creating TOC references as part of the link process.  */
+	      if (o != xcoff_hash_table (info)->toc_section
+		  && (o->flags & SEC_MARK) == 0)
 		{
 		  if (! xcoff_mark (info, o))
 		    goto error_return;
@@ -3504,7 +3513,6 @@ #define N_BTSHFT n_btshft
       union internal_auxent aux;
       int smtyp = 0;
       bfd_boolean skip;
-      bfd_boolean require;
       int add;
 
       bfd_coff_swap_sym_in (input_bfd, (void *) esym, (void *) isymp);
@@ -3623,7 +3631,6 @@ #define N_BTSHFT n_btshft
       *indexp = -1;
 
       skip = FALSE;
-      require = FALSE;
       add = 1 + isym.n_numaux;
 
       /* If we are skipping this csect, we want to skip this symbol.  */
@@ -3644,75 +3651,11 @@ #define N_BTSHFT n_btshft
 	  && isymp->n_sclass == C_STAT)
 	skip = TRUE;
 
-      /* We skip all but the first TOC anchor.  */
+      /* We generate the TOC anchor separately.  */
       if (! skip
 	  && isymp->n_sclass == C_HIDEXT
 	  && aux.x_csect.x_smclas == XMC_TC0)
-	{
-	  if (finfo->toc_symindx != -1)
-	    skip = TRUE;
-	  else
-	    {
-	      bfd_vma tocval, tocend;
-	      bfd *inp;
-
-	      tocval = ((*csectpp)->output_section->vma
-			+ (*csectpp)->output_offset
-			+ isym.n_value
-			- (*csectpp)->vma);
-
-	      /* We want to find out if tocval is a good value to use
-		 as the TOC anchor--that is, whether we can access all
-		 of the TOC using a 16 bit offset from tocval.  This
-		 test assumes that the TOC comes at the end of the
-		 output section, as it does in the default linker
-		 script.  */
-	      tocend = ((*csectpp)->output_section->vma
-			+ (*csectpp)->output_section->size);
-	      for (inp = finfo->info->input_bfds;
-		   inp != NULL;
-		   inp = inp->link_next)
-		{
-
-		  for (o = inp->sections; o != NULL; o = o->next)
-		    if (strcmp (o->name, ".tocbss") == 0)
-		      {
-			bfd_vma new_toc_end;
-			new_toc_end = (o->output_section->vma
-				       + o->output_offset
-				       + o->size);
-			if (new_toc_end > tocend)
-			  tocend = new_toc_end;
-		      }
-
-		}
-
-	      if (tocval + 0x10000 < tocend)
-		{
-		  (*_bfd_error_handler)
-		    (_("TOC overflow: 0x%lx > 0x10000; try -mminimal-toc when compiling"),
-		     (unsigned long) (tocend - tocval));
-		  bfd_set_error (bfd_error_file_too_big);
-		  return FALSE;
-		}
-
-	      if (tocval + 0x8000 < tocend)
-		{
-		  bfd_vma tocadd;
-
-		  tocadd = tocend - (tocval + 0x8000);
-		  tocval += tocadd;
-		  isym.n_value += tocadd;
-		}
-
-	      finfo->toc_symindx = output_index;
-	      xcoff_data (finfo->output_bfd)->toc = tocval;
-	      xcoff_data (finfo->output_bfd)->sntoc =
-		(*csectpp)->output_section->target_index;
-	      require = TRUE;
-
-	    }
-	}
+	skip = TRUE;
 
       /* If we are stripping all symbols, we want to skip this one.  */
       if (! skip
@@ -3781,12 +3724,6 @@ #define N_BTSHFT n_btshft
 	    skip = TRUE;
 	}
 
-      /* We can not skip the first TOC anchor.  */
-      if (skip
-	  && require
-	  && finfo->info->strip != strip_all)
-	skip = FALSE;
-
       /* We now know whether we are to skip this symbol or not.  */
       if (! skip)
 	{
@@ -4616,6 +4553,144 @@ xcoff_sort_relocs (const void * p1, cons
     return 0;
 }
 
+/* Return true if section SEC is a TOC section.  */
+
+static inline bfd_boolean
+xcoff_toc_section_p (asection *sec)
+{
+  const char *name;
+
+  name = sec->name;
+  if (name[0] == '.' && name[1] == 't')
+    {
+      if (name[2] == 'c')
+	{
+	  if (name[3] == '0' && name[4] == 0)
+	    return TRUE;
+	  if (name[3] == 0)
+	    return TRUE;
+	}
+      if (name[2] == 'd' && name[3] == 0)
+	return TRUE;
+    }
+  return FALSE;
+}
+
+/* See if the link requires a TOC (it usually does!).  If so, find a
+   good place to put the TOC anchor csect, and write out the associated
+   symbol.  */
+
+static bfd_boolean
+xcoff_find_tc0 (bfd *output_bfd, struct xcoff_final_link_info *finfo)
+{
+  bfd_vma toc_start, toc_end, start, end, best_address;
+  asection *sec;
+  bfd *input_bfd;
+  int section_index;
+  struct internal_syment irsym;
+  union internal_auxent iraux;
+  file_ptr pos;
+  size_t size;
+
+  /* Set [TOC_START, TOC_END) to the range of the TOC.  Record the
+     index of a csect at the beginning of the TOC.  */
+  toc_start = ~(bfd_vma) 0;
+  toc_end = 0;
+  section_index = -1;
+  for (input_bfd = finfo->info->input_bfds;
+       input_bfd != NULL;
+       input_bfd = input_bfd->link_next)
+    for (sec = input_bfd->sections; sec != NULL; sec = sec->next)
+      if ((sec->flags & SEC_MARK) != 0 && xcoff_toc_section_p (sec))
+	{
+	  start = sec->output_section->vma + sec->output_offset;
+	  if (toc_start > start)
+	    {
+	      toc_start = start;
+	      section_index = sec->output_section->target_index;
+	    }
+
+	  end = start + sec->size;
+	  if (toc_end < end)
+	    toc_end = end;
+	}
+
+  /* There's no need for a TC0 symbol if we don't have a TOC.  */
+  if (toc_end < toc_start)
+    {
+      xcoff_data (output_bfd)->toc = toc_start;
+      return TRUE;
+    }
+
+  if (toc_end - toc_start < 0x8000)
+    /* Every TOC csect can be accessed from TOC_START.  */
+    best_address = toc_start;
+  else
+    {
+      /* Find the lowest TOC csect that is still within range of TOC_END.  */
+      best_address = toc_end;
+      for (input_bfd = finfo->info->input_bfds;
+	   input_bfd != NULL;
+	   input_bfd = input_bfd->link_next)
+	for (sec = input_bfd->sections; sec != NULL; sec = sec->next)
+	  if ((sec->flags & SEC_MARK) != 0 && xcoff_toc_section_p (sec))
+	    {
+	      start = sec->output_section->vma + sec->output_offset;
+	      if (start < best_address
+		  && start + 0x8000 >= toc_end)
+		{
+		  best_address = start;
+		  section_index = sec->output_section->target_index;
+		}
+	    }
+
+      /* Make sure that the start of the TOC is also within range.  */
+      if (best_address > toc_start + 0x8000)
+	{
+	  (*_bfd_error_handler)
+	    (_("TOC overflow: 0x%lx > 0x10000; try -mminimal-toc "
+	       "when compiling"),
+	     (unsigned long) (toc_end - toc_start));
+	  bfd_set_error (bfd_error_file_too_big);
+	  return FALSE;
+	}
+    }
+
+  /* Record the chosen TOC value.  */
+  finfo->toc_symindx = obj_raw_syment_count (output_bfd);
+  xcoff_data (output_bfd)->toc = best_address;
+  xcoff_data (output_bfd)->sntoc = section_index;
+
+  /* Fill out the TC0 symbol.  */
+  if (!bfd_xcoff_put_symbol_name (output_bfd, finfo->strtab, &irsym, "TOC"))
+    return FALSE;
+  irsym.n_value = best_address;
+  irsym.n_scnum = section_index;
+  irsym.n_sclass = C_HIDEXT;
+  irsym.n_type = T_NULL;
+  irsym.n_numaux = 1;
+  bfd_coff_swap_sym_out (output_bfd, &irsym, finfo->outsyms);
+
+  /* Fill out the auxillary csect information.  */
+  memset (&iraux, 0, sizeof iraux);
+  iraux.x_csect.x_smtyp = XTY_SD;
+  iraux.x_csect.x_smclas = XMC_TC0;
+  iraux.x_csect.x_scnlen.l = 0;
+  bfd_coff_swap_aux_out (output_bfd, &iraux, T_NULL, C_HIDEXT, 0, 1,
+			 finfo->outsyms + bfd_coff_symesz (output_bfd));
+
+  /* Write the contents to the file.  */
+  pos = obj_sym_filepos (output_bfd);
+  pos += obj_raw_syment_count (output_bfd) * bfd_coff_symesz (output_bfd);
+  size = 2 * bfd_coff_symesz (output_bfd);
+  if (bfd_seek (output_bfd, pos, SEEK_SET) != 0
+      || bfd_bwrite (finfo->outsyms, size, output_bfd) != size)
+    return FALSE;
+  obj_raw_syment_count (output_bfd) += 2;
+
+  return TRUE;
+}
+
 /* Write out a non-XCOFF global symbol.  */
 
 static bfd_boolean
@@ -5692,7 +5767,10 @@ _bfd_xcoff_bfd_final_link (bfd *abfd, st
     goto error_return;
 
   obj_raw_syment_count (abfd) = 0;
-  xcoff_data (abfd)->toc = (bfd_vma) -1;
+
+  /* Find a TOC symbol, if we need one.  */
+  if (!xcoff_find_tc0 (abfd, &finfo))
+    goto error_return;
 
   /* We now know the position of everything in the file, except that
      we don't know the size of the symbol table and therefore we don't
Index: ld/testsuite/ld-powerpc/aix-toc-1.ex
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-toc-1.ex	2009-03-10 13:46:58.000000000 +0000
@@ -0,0 +1,2 @@
+f1
+f2
Index: ld/testsuite/ld-powerpc/aix-toc-1a.s
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-toc-1a.s	2009-03-10 13:46:58.000000000 +0000
@@ -0,0 +1,23 @@
+	.macro  loadtoc
+	.toc
+	.tc	sym\@[TC], \@
+
+	.csect	.f1[PR]
+	.if     size == 32
+	lwz     1,sym\@[TC](2)
+	.else
+	ld      1,sym\@[TC](2)
+	.endif
+	.endm
+
+	.globl	.f1
+	.csect	.f1[PR]
+.f1:
+	.rept	0x7ffc * 8 / size
+	loadtoc
+	.endr
+
+	.globl	f1
+	.csect	f1[DS]
+f1:
+	.long	.f1[PR],TOC[TC0],0
Index: ld/testsuite/ld-powerpc/aix-toc-1b.s
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-toc-1b.s	2009-03-10 13:46:58.000000000 +0000
@@ -0,0 +1,23 @@
+	.macro  loadtoc
+	.toc
+	.tc	asym\@[TC], \@ | 0x10000
+
+	.csect	.f2[PR]
+	.if     size == 32
+	lwz     1,asym\@[TC](2)
+	.else
+	ld      1,asym\@[TC](2)
+	.endif
+	.endm
+
+	.globl	.f2
+	.csect	.f2[PR]
+.f2:
+	.rept	0x7ffc * 8 / size
+	loadtoc
+	.endr
+
+	.globl	f2
+	.csect	f2[DS]
+f2:
+	.long	.f2[PR],TOC[TC0],0
Index: ld/testsuite/ld-powerpc/aix-toc-1-32.dd
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-toc-1-32.dd	2009-03-10 13:46:58.000000000 +0000
@@ -0,0 +1,12 @@
+
+.*
+
+
+Disassembly of section \.text:
+
+10000000 <\.f1>:
+10000000:	80 22 80 08 	l       r1,-32760\(r2\)
+			10000002: R_TOC	sym0.*
+#...
+1000fff4:	80 22 7f fc 	l       r1,32764\(r2\)
+			1000fff6: R_TOC	asym8190.*
Index: ld/testsuite/ld-powerpc/aix-toc-1-64.dd
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-toc-1-64.dd	2009-03-10 13:46:58.000000000 +0000
@@ -0,0 +1,12 @@
+
+.*
+
+
+Disassembly of section \.text:
+
+0000000010000000 <.f1>:
+    10000000:	e8 22 80 10 	ld      r1,-32752\(r2\)
+			10000002: R_TOC	sym0.*
+#...
+    10007ff4:	e8 22 7f f8 	ld      r1,32760\(r2\)
+			10007ff6: R_TOC	asym4094.*
Index: ld/testsuite/ld-powerpc/aix52.exp
===================================================================
--- ld/testsuite/ld-powerpc/aix52.exp	2009-03-10 13:46:23.000000000 +0000
+++ ld/testsuite/ld-powerpc/aix52.exp	2009-03-10 13:46:58.000000000 +0000
@@ -97,6 +97,11 @@ set aix52tests {
      "" {aix-glink-1.s}
      {{objdump {-D -j.text -j.data} aix-glink-1-SIZE.dd}}
      "aix-glink-1.so"}
+
+    {"TOC test 1" "-shared -bE:aix-toc-1.ex"
+     "" {aix-toc-1a.s aix-toc-1b.s}
+     {{objdump -dr aix-toc-1-SIZE.dd}}
+     "aix-toc-1.so"}
 }
 
 foreach test $aix52tests {

^ permalink raw reply	[flat|nested] 50+ messages in thread

* [12/21] Trim XCOFF symbols earlier in the link process
  2009-03-10 13:58 [0/21] Add support for AIX 6 Richard Sandiford
                   ` (11 preceding siblings ...)
  2009-03-10 14:29 ` [11/21] Cope with TOCs bigger than 32k, and other TC0 fixes Richard Sandiford
@ 2009-03-10 14:34 ` Richard Sandiford
  2009-03-13 15:01   ` Nick Clifton
  2009-03-10 14:36 ` [13/21] Fix counting of line-number entries Richard Sandiford
                   ` (8 subsequent siblings)
  21 siblings, 1 reply; 50+ messages in thread
From: Richard Sandiford @ 2009-03-10 14:34 UTC (permalink / raw)
  To: binutils

As I mentioned in the last patch, xcoff_link_input_bfd decides on the
fly whether to keep an XCOFF symbol in the static symbol table.
This patch moves the decision to bfd_size_dynamic_sections instead.

The patch is needed by a later bug fix, but it also lifts the
restriction mentioned here:

      /* If some symbols are stripped based on the name, work out the
	 name and decide whether to skip this symbol.  We don't handle
	 this correctly for symbols whose names are in the .debug
	 section; to get it right we would need a new bfd_strtab_hash
	 function to return the string given the index.  */
      if (! skip
	  && (finfo->info->strip == strip_some
	      || finfo->info->discard == discard_l)
	  && (debug_index == NULL || *debug_index == (unsigned long) -1))

That is, xcoff_link_input_bfd cannot easily look up debug names,
and it runs too late to remove stuff from .debug anyway.  I'm not
sure this ever matters in practice, but the "fix" falls out in the wash.

The patch also makes the structure of xcoff_link_input_bfd a bit
clearer IMO.  At the moment, the function makes two passes over
the symbol table and divides the work up as follows:

Pass 1:

  (1) Create dynamic symbol table entries where appropriate.
      (The decision is independent of whether we keep entries
      in the static symbol table.)

  (2) Decide whether to strip the symbol from the static table.
      If not:

      (3) Assign an index to it.

      (4) Adjust the contents of the main symbol entry, and swap it out.

      (5) If the symbol is associated with a linker hash table entry,
	  update the hash entry appropriately.

Pass 2:

  (6) Fix up C_BSTAT symbols.

  (7) Adjust the contents of auxillary entries, and swap them out.

As the comment above the current second pass says:

  /* Fix up the aux entries and the C_BSTAT symbols.  This must be
     done in a separate pass, because we don't know the correct symbol
     indices until we have already decided which symbols we are going
     to keep.  */

But although we _can_ do (4) in the first pass, I don't see any
reason why we need to.  It seems more logical to leave all the
symbol creation to the second pass, and do everything in order.
There's then no need for (6) to fix up the partially-complete
result of (4).

The patch instead does (1), (2), (3) and (5) in the first pass
and (4), (6) and (7) in the second.

The patch uses a new debug_index value of -2 for symbols that we
decide to strip.  This seemed better than adding a dedicated array,
with all the overhead that implies.

debug_index is effectively a signed value already, so the patch changes
its type accordingly.  No new casts are needed but some can be removed.

The logic in xcoff_keep_symbol_p is taken directly from xcoff_link_input_bfd.
Later patches tweak some aspects of it, but I've deliberately kept such
changes separate.  I certainly can't vouch for the accuracy of the rest;
I'm just taking it on faith.

OK to install?

Richard


bfd/
	* libcoff-in.h (xcoff_tdata): Change debug_indices to a signed long.
	* libcoff.h: Regenerate.
	* xcofflink.c (xcoff_keep_symbol_p): New function, using the
	"skip" logic from xcoff_link_input_bfd.
	(bfd_xcoff_size_dynamic_sections): Explicitly skip dynamic
	objects in a dynamic link, rather than checking whether csectpp
	is null.  Always allocate debug_index for other objects,
	and always go through the loop.  Update the type of debug_index
	after the change above.  Read the auxillary csect information
	and use xcoff_keep_symbol_p to decide whether a symbol should
	be kept.  Set its debug_index to -2 if not.
	(xcoff_link_input_bfd): Update the type of debug_index after
	the change above and always expect it to be nonnull.  Use it to
	test whether a symbol should be stripped, rather than making the
	decision here.  Postpone all symbol creation to the second pass.

Index: bfd/libcoff-in.h
===================================================================
--- bfd/libcoff-in.h	2009-03-10 13:46:38.000000000 +0000
+++ bfd/libcoff-in.h	2009-03-10 13:47:43.000000000 +0000
@@ -165,7 +165,7 @@ struct xcoff_tdata
 
   /* Used by the XCOFF backend linker.  */
   asection **csects;
-  unsigned long *debug_indices;
+  long *debug_indices;
   unsigned int import_file_id;
 };
 
Index: bfd/libcoff.h
===================================================================
--- bfd/libcoff.h	2009-03-10 13:46:38.000000000 +0000
+++ bfd/libcoff.h	2009-03-10 13:47:43.000000000 +0000
@@ -169,7 +169,7 @@ struct xcoff_tdata
 
   /* Used by the XCOFF backend linker.  */
   asection **csects;
-  unsigned long *debug_indices;
+  long *debug_indices;
   unsigned int import_file_id;
 };
 
Index: bfd/xcofflink.c
===================================================================
--- bfd/xcofflink.c	2009-03-10 13:46:58.000000000 +0000
+++ bfd/xcofflink.c	2009-03-10 13:47:43.000000000 +0000
@@ -2981,6 +2981,104 @@ xcoff_build_ldsyms (struct xcoff_link_ha
 
   return TRUE;
 }
+
+/* INPUT_BFD includes XCOFF symbol ISYM, which is associated with linker
+   hash table entry H and csect CSECT.  AUX contains ISYM's auxillary
+   csect information, if any.  NAME is the function's name if the name
+   is stored in the .debug section, otherwise it is null.
+
+   Return 1 if we should include an appropriately-adjusted ISYM
+   in the output file, 0 if we should discard ISYM, or -1 if an
+   error occured.  */
+
+static int
+xcoff_keep_symbol_p (struct bfd_link_info *info, bfd *input_bfd,
+		     struct internal_syment *isym,
+		     union internal_auxent *aux,
+		     struct xcoff_link_hash_entry *h,
+		     asection *csect, const char *name)
+{
+  int smtyp;
+
+  /* If we are skipping this csect, we want to strip the symbol too.  */
+  if (csect == NULL)
+    return 0;
+
+  /* Likewise if we garbage-collected the csect.  */
+  if (xcoff_hash_table (info)->gc
+      && !bfd_is_abs_section (csect)
+      && !bfd_is_und_section (csect)
+      && (csect->flags & SEC_MARK) == 0)
+    return 0;
+
+  /* An XCOFF linker always removes C_STAT symbols.  */
+  if (isym->n_sclass == C_STAT)
+    return 0;
+
+  /* We generate the TOC anchor separately.  */
+  if (isym->n_sclass == C_HIDEXT
+      && aux->x_csect.x_smclas == XMC_TC0)
+    return 0;
+
+  /* If we are stripping all symbols, we want to discard this one.  */
+  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;
+
+  /* If we're discarding local symbols, check whether ISYM is local.  */
+  if (info->discard == discard_all
+      && isym->n_sclass != C_EXT
+      && (isym->n_sclass != C_HIDEXT || smtyp != XTY_SD))
+    return 0;
+
+  /* If we're stripping debugging symbols, check whether ISYM is one.  */
+  if (info->strip == strip_debugger
+      && isym->n_scnum == N_DEBUG)
+    return 0;
+
+  /* If we are stripping symbols based on name, check how ISYM's
+     name should be handled.  */
+  if (info->strip == strip_some
+      || info->discard == discard_l)
+    {
+      char buf[SYMNMLEN + 1];
+
+      if (name == NULL)
+	{
+	  name = _bfd_coff_internal_syment_name (input_bfd, isym, buf);
+	  if (name == NULL)
+	    return -1;
+	}
+
+      if (info->strip == strip_some
+	  && bfd_hash_lookup (info->keep_hash, name, FALSE, FALSE) == NULL)
+	return 0;
+
+      if (info->discard == discard_l
+	  && isym->n_sclass != C_EXT
+	  && (isym->n_sclass != C_HIDEXT || smtyp != XTY_SD)
+	  && bfd_is_local_label_name (input_bfd, name))
+	return 0;
+    }
+
+  return 1;
+}
+
 /* Build the .loader section.  This is called by the XCOFF linker
    emulation before_allocation routine.  We must set the size of the
    .loader section before the linker lays out the output file.
@@ -3288,97 +3386,134 @@ bfd_xcoff_size_dynamic_sections (bfd *ou
 	goto error_return;
     }
 
-  /* Now that we've done garbage collection, figure out the contents
-     of the .debug section.  */
+  /* Now that we've done garbage collection, decide which symbols to keep,
+     and figure out the contents of the .debug section.  */
   debug_strtab = xcoff_hash_table (info)->debug_strtab;
 
   for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
     {
       asection *subdeb;
       bfd_size_type symcount;
-      unsigned long *debug_index;
+      long *debug_index;
       asection **csectpp;
+      struct xcoff_link_hash_entry **sym_hash;
       bfd_byte *esym, *esymend;
       bfd_size_type symesz;
 
       if (sub->xvec != info->output_bfd->xvec)
 	continue;
-      subdeb = bfd_get_section_by_name (sub, ".debug");
-      if (subdeb == NULL || subdeb->size == 0)
-	continue;
 
-      if (info->strip == strip_all
-	  || info->strip == strip_debugger
-	  || info->discard == discard_all)
-	{
-	  subdeb->size = 0;
-	  continue;
-	}
+      if ((sub->flags & DYNAMIC) != 0
+	  && !info->static_link)
+	continue;
 
       if (! _bfd_coff_get_external_symbols (sub))
 	goto error_return;
 
       symcount = obj_raw_syment_count (sub);
-      debug_index = bfd_zalloc (sub, symcount * sizeof (unsigned long));
+      debug_index = bfd_zalloc (sub, symcount * sizeof (long));
       if (debug_index == NULL)
 	goto error_return;
       xcoff_data (sub)->debug_indices = debug_index;
 
-      /* Grab the contents of the .debug section.  We use malloc and
-	 copy the names into the debug stringtab, rather than
-	 bfd_alloc, because I expect that, when linking many files
-	 together, many of the strings will be the same.  Storing the
-	 strings in the hash table should save space in this case.  */
-      if (! bfd_malloc_and_get_section (sub, subdeb, &debug_contents))
-	goto error_return;
+      if (info->strip == strip_all
+	  || info->strip == strip_debugger
+	  || info->discard == discard_all)
+	/* We're stripping all debugging information, so there's no need
+	   to read SUB's .debug section.  */
+	subdeb = NULL;
+      else
+	{
+	  /* Grab the contents of SUB's .debug section, if any.  */
+	  subdeb = bfd_get_section_by_name (sub, ".debug");
+	  if (subdeb != NULL && subdeb->size > 0)
+	    {
+	      /* We use malloc and copy the names into the debug
+		 stringtab, rather than bfd_alloc, because I expect
+		 that, when linking many files together, many of the
+		 strings will be the same.  Storing the strings in the
+		 hash table should save space in this case.  */
+	      if (!bfd_malloc_and_get_section (sub, subdeb, &debug_contents))
+		goto error_return;
+	    }
+	}
 
       csectpp = xcoff_data (sub)->csects;
+      sym_hash = obj_xcoff_sym_hashes (sub);
+      symesz = bfd_coff_symesz (sub);
+      esym = (bfd_byte *) obj_coff_external_syms (sub);
+      esymend = esym + symcount * symesz;
 
-      /* Dynamic object do not have csectpp's.  */
-      if (NULL != csectpp)
+      while (esym < esymend)
 	{
-	  symesz = bfd_coff_symesz (sub);
-	  esym = (bfd_byte *) obj_coff_external_syms (sub);
-	  esymend = esym + symcount * symesz;
+	  struct internal_syment sym;
+	  union internal_auxent aux;
+	  const char *name;
+	  int keep_p;
 
-	  while (esym < esymend)
-	    {
-	      struct internal_syment sym;
+	  bfd_coff_swap_sym_in (sub, esym, &sym);
 
-	      bfd_coff_swap_sym_in (sub, (void *) esym, (void *) &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)
+	    {
+	      BFD_ASSERT (sym.n_numaux > 0);
+	      bfd_coff_swap_aux_in (sub, esym + symesz * sym.n_numaux,
+				    sym.n_type, sym.n_sclass,
+				    sym.n_numaux - 1, sym.n_numaux, &aux);
+	    }
+
+	  /* If this symbol's name is stored in the debug section,
+	     get a pointer to it.  */
+	  if (debug_contents != NULL
+	      && sym._n._n_n._n_zeroes == 0
+	      && bfd_coff_symname_in_debug (sub, &sym))
+	    name = (const char *) debug_contents + sym._n._n_n._n_offset;
+	  else
+	    name = NULL;
 
-	      *debug_index = (unsigned long) -1;
+	  /* Decide whether to copy this symbol to the output file.  */
+	  keep_p = xcoff_keep_symbol_p (info, sub, &sym, &aux,
+					*sym_hash, *csectpp, name);
+	  if (keep_p < 0)
+	    return FALSE;
 
-	      if (sym._n._n_n._n_zeroes == 0
-		  && *csectpp != NULL
-		  && (! gc
-		      || bfd_is_abs_section (*csectpp)
-		      || bfd_is_und_section (*csectpp)
-		      || ((*csectpp)->flags & SEC_MARK) != 0)
-		  && bfd_coff_symname_in_debug (sub, &sym))
+	  if (!keep_p)
+	    /* Use a debug_index of -2 to record that a symbol should
+	       be stripped.  */
+	    *debug_index = -2;
+	  else
+	    {
+	      /* See whether we should store the symbol name in the
+		 output .debug section.  */
+	      if (name != NULL)
 		{
-		  char *name;
 		  bfd_size_type indx;
 
-		  name = (char *) debug_contents + sym._n._n_n._n_offset;
 		  indx = _bfd_stringtab_add (debug_strtab, name, TRUE, TRUE);
 		  if (indx == (bfd_size_type) -1)
 		    goto error_return;
 		  *debug_index = indx;
 		}
-
-	      esym += (sym.n_numaux + 1) * symesz;
-	      csectpp += sym.n_numaux + 1;
-	      debug_index += sym.n_numaux + 1;
+	      else
+		*debug_index = -1;
 	    }
+
+	  esym += (sym.n_numaux + 1) * symesz;
+	  csectpp += sym.n_numaux + 1;
+	  sym_hash += sym.n_numaux + 1;
+	  debug_index += sym.n_numaux + 1;
 	}
 
-      free (debug_contents);
-      debug_contents = NULL;
+      if (debug_contents)
+	{
+	  free (debug_contents);
+	  debug_contents = NULL;
 
-      /* Clear the size of subdeb, so that it is not included directly
-	 in the output file.  */
-      subdeb->size = 0;
+	  /* Clear the size of subdeb, so that it is not included directly
+	     in the output file.  */
+	  subdeb->size = 0;
+	}
 
       if (! info->keep_memory)
 	{
@@ -3455,7 +3590,7 @@ xcoff_link_input_bfd (struct xcoff_final
   struct xcoff_link_hash_entry **sym_hash;
   struct internal_syment *isymp;
   asection **csectpp;
-  unsigned long *debug_index;
+  long *debug_index;
   long *indexp;
   unsigned long output_index;
   bfd_byte *outsym;
@@ -3495,6 +3630,9 @@ #define N_BTSHFT n_btshft
   if (! _bfd_coff_get_external_symbols (input_bfd))
     return FALSE;
 
+  /* Make one pass over the symbols and assign indices to symbols that
+     we have decided to keep.  Also use create .loader symbol information
+     and update information in hash table entries.  */
   esym = (bfd_byte *) obj_coff_external_syms (input_bfd);
   esym_end = esym + obj_raw_syment_count (input_bfd) * isymesz;
   sym_hash = obj_xcoff_sym_hashes (input_bfd);
@@ -3503,16 +3641,10 @@ #define N_BTSHFT n_btshft
   isymp = finfo->internal_syms;
   indexp = finfo->sym_indices;
   output_index = syment_base;
-  outsym = finfo->outsyms;
-  incls = 0;
-  oline = NULL;
-
   while (esym < esym_end)
     {
-      struct internal_syment isym;
       union internal_auxent aux;
       int smtyp = 0;
-      bfd_boolean skip;
       int add;
 
       bfd_coff_swap_sym_in (input_bfd, (void *) esym, (void *) isymp);
@@ -3531,17 +3663,11 @@ #define N_BTSHFT n_btshft
 	  smtyp = SMTYP_SMTYP (aux.x_csect.x_smtyp);
 	}
 
-      /* Make a copy of *isymp so that the relocate_section function
-	 always sees the original values.  This is more reliable than
-	 always recomputing the symbol value even if we are stripping
-	 the symbol.  */
-      isym = *isymp;
-
       /* If this symbol is in the .loader section, swap out the
 	 .loader symbol information.  If this is an external symbol
 	 reference to a defined symbol, though, then wait until we get
 	 to the definition.  */
-      if (isym.n_sclass == C_EXT
+      if (isymp->n_sclass == C_EXT
 	  && *sym_hash != NULL
 	  && (*sym_hash)->ldsym != NULL
 	  && (smtyp != XTY_ER
@@ -3552,18 +3678,18 @@ #define N_BTSHFT n_btshft
 
 	  h = *sym_hash;
 	  ldsym = h->ldsym;
-	  if (isym.n_scnum > 0)
+	  if (isymp->n_scnum > 0)
 	    {
 	      ldsym->l_scnum = (*csectpp)->output_section->target_index;
-	      ldsym->l_value = (isym.n_value
+	      ldsym->l_value = (isymp->n_value
 				+ (*csectpp)->output_section->vma
 				+ (*csectpp)->output_offset
 				- (*csectpp)->vma);
 	    }
 	  else
 	    {
-	      ldsym->l_scnum = isym.n_scnum;
-	      ldsym->l_value = isym.n_value;
+	      ldsym->l_scnum = isymp->n_scnum;
+	      ldsym->l_value = isymp->n_value;
 	    }
 
 	  ldsym->l_smtype = smtyp;
@@ -3628,114 +3754,80 @@ #define N_BTSHFT n_btshft
 	    }
 	}
 
-      *indexp = -1;
-
-      skip = FALSE;
-      add = 1 + isym.n_numaux;
+      add = 1 + isymp->n_numaux;
 
-      /* If we are skipping this csect, we want to skip this symbol.  */
-      if (*csectpp == NULL)
-	skip = TRUE;
-
-      /* If we garbage collected this csect, we want to skip this
-	 symbol.  */
-      if (! skip
-	  && xcoff_hash_table (finfo->info)->gc
-	  && !bfd_is_abs_section (*csectpp)
-	  && !bfd_is_und_section (*csectpp)
-	  && ((*csectpp)->flags & SEC_MARK) == 0)
-	skip = TRUE;
-
-      /* An XCOFF linker always skips C_STAT symbols.  */
-      if (! skip
-	  && isymp->n_sclass == C_STAT)
-	skip = TRUE;
-
-      /* We generate the TOC anchor separately.  */
-      if (! skip
-	  && isymp->n_sclass == C_HIDEXT
-	  && aux.x_csect.x_smclas == XMC_TC0)
-	skip = TRUE;
-
-      /* If we are stripping all symbols, we want to skip this one.  */
-      if (! skip
-	  && finfo->info->strip == strip_all)
-	skip = TRUE;
-
-      /* We can skip resolved external references.  */
-      if (! skip
-	  && isym.n_sclass == C_EXT
-	  && smtyp == XTY_ER
-	  && (*sym_hash)->root.type != bfd_link_hash_undefined)
-	skip = TRUE;
-
-      /* We can skip common symbols if they got defined somewhere
-	 else.  */
-      if (! skip
-	  && isym.n_sclass == C_EXT
-	  && smtyp == XTY_CM
-	  && ((*sym_hash)->root.type != bfd_link_hash_common
-	      || (*sym_hash)->root.u.c.p->section != *csectpp)
-	  && ((*sym_hash)->root.type != bfd_link_hash_defined
-	      || (*sym_hash)->root.u.def.section != *csectpp))
-	skip = TRUE;
-
-      /* Skip local symbols if we are discarding them.  */
-      if (! skip
-	  && finfo->info->discard == discard_all
-	  && isym.n_sclass != C_EXT
-	  && (isym.n_sclass != C_HIDEXT
-	      || smtyp != XTY_SD))
-	skip = TRUE;
-
-      /* If we stripping debugging symbols, and this is a debugging
-	 symbol, then skip it.  */
-      if (! skip
-	  && finfo->info->strip == strip_debugger
-	  && isym.n_scnum == N_DEBUG)
-	skip = TRUE;
-
-      /* If some symbols are stripped based on the name, work out the
-	 name and decide whether to skip this symbol.  We don't handle
-	 this correctly for symbols whose names are in the .debug
-	 section; to get it right we would need a new bfd_strtab_hash
-	 function to return the string given the index.  */
-      if (! skip
-	  && (finfo->info->strip == strip_some
-	      || finfo->info->discard == discard_l)
-	  && (debug_index == NULL || *debug_index == (unsigned long) -1))
+      if (*debug_index == -2)
+	/* We've decided to strip this symbol.  */
+	*indexp = -1;
+      else
 	{
-	  const char *name;
-	  char buf[SYMNMLEN + 1];
+	  /* Assign the next unused index to this symbol.  */
+	  *indexp = output_index;
 
-	  name = _bfd_coff_internal_syment_name (input_bfd, &isym, buf);
+	  if (isymp->n_sclass == C_EXT)
+	    {
+	      BFD_ASSERT (*sym_hash != NULL);
+	      (*sym_hash)->indx = output_index;
+	    }
 
-	  if (name == NULL)
-	    return FALSE;
+	  /* If this is a symbol in the TOC which we may have merged
+	     (class XMC_TC), remember the symbol index of the TOC
+	     symbol.  */
+	  if (isymp->n_sclass == C_HIDEXT
+	      && aux.x_csect.x_smclas == XMC_TC
+	      && *sym_hash != NULL)
+	    {
+	      BFD_ASSERT (((*sym_hash)->flags & XCOFF_SET_TOC) == 0);
+	      BFD_ASSERT ((*sym_hash)->toc_section != NULL);
+	      (*sym_hash)->u.toc_indx = output_index;
+	    }
 
-	  if ((finfo->info->strip == strip_some
-	       && (bfd_hash_lookup (finfo->info->keep_hash, name, FALSE,
-				    FALSE) == NULL))
-	      || (finfo->info->discard == discard_l
-		  && (isym.n_sclass != C_EXT
-		      && (isym.n_sclass != C_HIDEXT
-			  || smtyp != XTY_SD))
-		  && bfd_is_local_label_name (input_bfd, name)))
-	    skip = TRUE;
+	  output_index += add;
 	}
 
-      /* We now know whether we are to skip this symbol or not.  */
-      if (! skip)
+      esym += add * isymesz;
+      isymp += add;
+      csectpp += add;
+      sym_hash += add;
+      debug_index += add;
+      ++indexp;
+      for (--add; add > 0; --add)
+	*indexp++ = -1;
+    }
+
+  /* Now write out the symbols that we decided to keep.  */
+
+  esym = (bfd_byte *) obj_coff_external_syms (input_bfd);
+  esym_end = esym + obj_raw_syment_count (input_bfd) * isymesz;
+  isymp = finfo->internal_syms;
+  indexp = finfo->sym_indices;
+  csectpp = xcoff_data (input_bfd)->csects;
+  debug_index = xcoff_data (input_bfd)->debug_indices;
+  outsym = finfo->outsyms;
+  incls = 0;
+  oline = NULL;
+  while (esym < esym_end)
+    {
+      int add;
+
+      add = 1 + isymp->n_numaux;
+
+      if (*indexp < 0)
+	esym += add * isymesz;
+      else
 	{
-	  /* Adjust the symbol in order to output it.  */
+	  struct internal_syment isym;
+	  int i;
 
+	  /* Adjust the symbol in order to output it.  */
+	  isym = *isymp;
 	  if (isym._n._n_n._n_zeroes == 0
 	      && isym._n._n_n._n_offset != 0)
 	    {
 	      /* This symbol has a long name.  Enter it in the string
 		 table we are building.  If *debug_index != -1, the
 		 name has already been entered in the .debug section.  */
-	      if (debug_index != NULL && *debug_index != (unsigned long) -1)
+	      if (*debug_index >= 0)
 		isym._n._n_n._n_offset = *debug_index;
 	      else
 		{
@@ -3753,17 +3845,6 @@ #define N_BTSHFT n_btshft
 		}
 	    }
 
-	  if (isym.n_sclass != C_BSTAT
-	      && isym.n_sclass != C_ESTAT
-	      && isym.n_sclass != C_DECL
-	      && isym.n_scnum > 0)
-	    {
-	      isym.n_scnum = (*csectpp)->output_section->target_index;
-	      isym.n_value += ((*csectpp)->output_section->vma
-			       + (*csectpp)->output_offset
-			       - (*csectpp)->vma);
-	    }
-
 	  /* The value of a C_FILE symbol is the symbol index of the
 	     next C_FILE symbol.  The value of the last C_FILE symbol
 	     is -1.  We try to get this right, below, just before we
@@ -3772,10 +3853,10 @@ #define N_BTSHFT n_btshft
 	  if (isym.n_sclass == C_FILE)
 	    {
 	      if (finfo->last_file_index != -1
-		  && finfo->last_file.n_value != (bfd_vma) output_index)
+		  && finfo->last_file.n_value != (bfd_vma) *indexp)
 		{
 		  /* We must correct the value of the last C_FILE entry.  */
-		  finfo->last_file.n_value = output_index;
+		  finfo->last_file.n_value = *indexp;
 		  if ((bfd_size_type) finfo->last_file_index >= syment_base)
 		    {
 		      /* The last C_FILE symbol is in this input file.  */
@@ -3806,7 +3887,7 @@ #define N_BTSHFT n_btshft
 		    }
 		}
 
-	      finfo->last_file_index = output_index;
+	      finfo->last_file_index = *indexp;
 	      finfo->last_file = isym;
 	    }
 
@@ -3819,84 +3900,12 @@ #define N_BTSHFT n_btshft
 	      isym.n_value = finfo->line_filepos;
 	      ++incls;
 	    }
-
-	  /* Output the symbol.  */
-
-	  bfd_coff_swap_sym_out (output_bfd, (void *) &isym, (void *) outsym);
-
-	  *indexp = output_index;
-
-	  if (isym.n_sclass == C_EXT)
-	    {
-	      long indx;
-	      struct xcoff_link_hash_entry *h;
-
-	      indx = ((esym - (bfd_byte *) obj_coff_external_syms (input_bfd))
-		      / isymesz);
-	      h = obj_xcoff_sym_hashes (input_bfd)[indx];
-	      BFD_ASSERT (h != NULL);
-	      h->indx = output_index;
-	    }
-
-	  /* If this is a symbol in the TOC which we may have merged
-	     (class XMC_TC), remember the symbol index of the TOC
-	     symbol.  */
-	  if (isym.n_sclass == C_HIDEXT
-	      && aux.x_csect.x_smclas == XMC_TC
-	      && *sym_hash != NULL)
+	  /* The value of a C_BSTAT symbol is the symbol table
+	     index of the containing csect.  */
+	  else if (isym.n_sclass == C_BSTAT)
 	    {
-	      BFD_ASSERT (((*sym_hash)->flags & XCOFF_SET_TOC) == 0);
-	      BFD_ASSERT ((*sym_hash)->toc_section != NULL);
-	      (*sym_hash)->u.toc_indx = output_index;
-	    }
-
-	  output_index += add;
-	  outsym += add * osymesz;
-	}
-
-      esym += add * isymesz;
-      isymp += add;
-      csectpp += add;
-      sym_hash += add;
-      if (debug_index != NULL)
-	debug_index += add;
-      ++indexp;
-      for (--add; add > 0; --add)
-	*indexp++ = -1;
-    }
-
-  /* Fix up the aux entries and the C_BSTAT symbols.  This must be
-     done in a separate pass, because we don't know the correct symbol
-     indices until we have already decided which symbols we are going
-     to keep.  */
-
-  esym = (bfd_byte *) obj_coff_external_syms (input_bfd);
-  esym_end = esym + obj_raw_syment_count (input_bfd) * isymesz;
-  isymp = finfo->internal_syms;
-  indexp = finfo->sym_indices;
-  csectpp = xcoff_data (input_bfd)->csects;
-  outsym = finfo->outsyms;
-  while (esym < esym_end)
-    {
-      int add;
-
-      add = 1 + isymp->n_numaux;
-
-      if (*indexp < 0)
-	esym += add * isymesz;
-      else
-	{
-	  int i;
-
-	  if (isymp->n_sclass == C_BSTAT)
-	    {
-	      struct internal_syment isym;
-
 	      bfd_vma indx;
 
-	      /* The value of a C_BSTAT symbol is the symbol table
-		 index of the containing csect.  */
-	      bfd_coff_swap_sym_in (output_bfd, (void *) outsym, (void *) &isym);
 	      indx = isym.n_value;
 	      if (indx < obj_raw_syment_count (input_bfd))
 		{
@@ -3907,10 +3916,20 @@ #define N_BTSHFT n_btshft
 		    isym.n_value = 0;
 		  else
 		    isym.n_value = symindx;
-		  bfd_coff_swap_sym_out (output_bfd, (void *) &isym,
-					 (void *) outsym);
 		}
 	    }
+	  else if (isym.n_sclass != C_ESTAT
+		   && isym.n_sclass != C_DECL
+		   && isym.n_scnum > 0)
+	    {
+	      isym.n_scnum = (*csectpp)->output_section->target_index;
+	      isym.n_value += ((*csectpp)->output_section->vma
+			       + (*csectpp)->output_offset
+			       - (*csectpp)->vma);
+	    }
+
+	  /* Output the symbol.  */
+	  bfd_coff_swap_sym_out (output_bfd, (void *) &isym, (void *) outsym);
 
 	  esym += isymesz;
 	  outsym += osymesz;
@@ -4185,6 +4204,7 @@ #define N_BTSHFT n_btshft
       indexp += add;
       isymp += add;
       csectpp += add;
+      debug_index += add;
     }
 
   /* If we swapped out a C_FILE symbol, guess that the next C_FILE

^ permalink raw reply	[flat|nested] 50+ messages in thread

* [13/21] Fix counting of line-number entries
  2009-03-10 13:58 [0/21] Add support for AIX 6 Richard Sandiford
                   ` (12 preceding siblings ...)
  2009-03-10 14:34 ` [12/21] Trim XCOFF symbols earlier in the link process Richard Sandiford
@ 2009-03-10 14:36 ` Richard Sandiford
  2009-03-13 15:04   ` Nick Clifton
  2009-03-10 14:38 ` [14/21] Treat absolute imports as XTY_ER/XMC_XO Richard Sandiford
                   ` (7 subsequent siblings)
  21 siblings, 1 reply; 50+ messages in thread
From: Richard Sandiford @ 2009-03-10 14:36 UTC (permalink / raw)
  To: binutils

This is the bug fix that the previous two patches were leading up to.

The COFF symbol table comes immediately after the line-number table.
_bfd_xcoff_bfd_final_link works out how many line-number entries
each output section needs, records the offsets, and assumes that
the symbol table will start after the last section's line numbers.
It then writes both the line numbers and symbol table in one pass.
Most of the writing is delegated to xcoff_link_input_bfd.

The problem is that xcoff_link_input_bfd decides on the fly whether
to actually output a line number, so the line number counts that
_bfd_xcoff_bfd_final_link used are only worst-case estimates.
This means that the line number table can be shorter than expected,
causing coff_write_object_contents to assume that the symbol table
starts earlier than _bfd_xcoff_bfd_final_link wrote it.

xcoff_link_add_symbols works out exactly how many line numbers
are attached to each symbol, but it does not record per-symbol
values; it simply adds the count to the csect's lineno_count.
xcoff_link_input_bfd then works this value out again, once it
knows whether we're keeping the symbol at all.

I think the cleanest fix is to add a new array that records
per-symbol line counts.  We can then count the line numbers
in bfd_size_dynamic_sections, at the same time as deciding
whether to keep a symbol.  xcoff_link_input_bfd can then reuse
this information too, rather than having to work it out again.

The obvious disadvantage of this apprach is that it eats more memory,
which is probably why it wasn't taken earlier.  However, the only other
way I can see of getting accurate line counts is:

  (1) Split out the "how many line numbers does this symbol have?"
      logic out of xcoff_link_input_bfd.

  (2) Make _bfd_xcoff_final_link do an extra pass over the input bfds,
      using this function to collect line-number counts.

This is more complicated, and an extra pass over every input symbol table
and line number table could be rather costly.

OK to install?

Richard


bfd/
	* libcoff-in.h (xcoff_tdata): Add a lineno_counts field.
	* libcoff.h: Regenerate.
	* xcofflink.c (xcoff_link_add_symbols): Record per-symbol
	line-number counts in the bfd's lineno_counts field.
	Don't keep per-csect line-number counts.
	(xcoff_sweep): Don't update per-csect line-number counts.
	(bfd_xcoff_size_dynamic_sections): Count the number of line-number
	entries in each output section.
	(xcoff_link_input_bfd): Get the number of line numbers from
	the bfd's lineno_counts field, rather than recalculating it
	from scratch.  Fix the range check when updating C_BINCL and
	C_EINCL symbols.
	(_bfd_xcoff_bfd_final_link): Don't count the output line numbers
	here.  Don't expect csects to have line-number counts.

ld/testsuite/
	* ld-powerpc/aix-lineno-1.s, ld-powerpc/aix-lineno-1.txt,
	ld-powerpc/aix-lineno-1a.dd, ld-powerpc/aix-lineno-1a.nd,
	ld-powerpc/aix-lineno-1b.dd, ld-powerpc/aix-lineno-1b.nd: New tests.
	* ld-powerpc/aix52.exp: Run them.  Copy aix-lineno-1.txt to tmpdir.

Index: bfd/libcoff-in.h
===================================================================
--- bfd/libcoff-in.h	2009-03-10 13:47:43.000000000 +0000
+++ bfd/libcoff-in.h	2009-03-10 13:48:18.000000000 +0000
@@ -166,6 +166,7 @@ struct xcoff_tdata
   /* Used by the XCOFF backend linker.  */
   asection **csects;
   long *debug_indices;
+  unsigned int *lineno_counts;
   unsigned int import_file_id;
 };
 
Index: bfd/libcoff.h
===================================================================
--- bfd/libcoff.h	2009-03-10 13:47:43.000000000 +0000
+++ bfd/libcoff.h	2009-03-10 13:48:18.000000000 +0000
@@ -170,6 +170,7 @@ struct xcoff_tdata
   /* Used by the XCOFF backend linker.  */
   asection **csects;
   long *debug_indices;
+  unsigned int *lineno_counts;
   unsigned int import_file_id;
 };
 
Index: bfd/xcofflink.c
===================================================================
--- bfd/xcofflink.c	2009-03-10 13:47:43.000000000 +0000
+++ bfd/xcofflink.c	2009-03-10 13:48:18.000000000 +0000
@@ -947,6 +947,7 @@ xcoff_link_add_symbols (bfd *abfd, struc
   bfd_size_type symcount;
   struct xcoff_link_hash_entry **sym_hash;
   asection **csect_cache;
+  unsigned int *lineno_counts;
   bfd_size_type linesz;
   asection *o;
   asection *last_real;
@@ -1013,6 +1014,15 @@ #define N_BTSHFT n_btshft
     goto error_return;
   xcoff_data (abfd)->csects = csect_cache;
 
+  /* We garbage-collect line-number information on a symbol-by-symbol
+     basis, so we need to have quick access to the number of entries
+     per symbol.  */
+  amt = symcount * sizeof (unsigned int);
+  lineno_counts = bfd_zalloc (abfd, amt);
+  if (lineno_counts == NULL && symcount != 0)
+    goto error_return;
+  xcoff_data (abfd)->lineno_counts = lineno_counts;
+
   /* While splitting sections into csects, we need to assign the
      relocs correctly.  The relocs and the csects must both be in
      order by VMA within a given section, so we handle this by
@@ -1104,6 +1114,7 @@ #define N_BTSHFT n_btshft
 	  esym += (sym.n_numaux + 1) * symesz;
 	  sym_hash += sym.n_numaux + 1;
 	  csect_cache += sym.n_numaux + 1;
+	  lineno_counts += sym.n_numaux + 1;
 
 	  continue;
 	}
@@ -1174,7 +1185,7 @@ #define N_BTSHFT n_btshft
 			  if (lin.l_lnno == 0)
 			    break;
 			}
-		      csect->lineno_count += (linp - linpstart) / linesz;
+		      *lineno_counts = (linp - linpstart) / linesz;
 		      /* The setting of line_filepos will only be
 			 useful if all the line number entries for a
 			 csect are contiguous; this only matters for
@@ -1795,6 +1806,7 @@ #define N_BTSHFT n_btshft
       esym += (sym.n_numaux + 1) * symesz;
       sym_hash += sym.n_numaux + 1;
       csect_cache += sym.n_numaux + 1;
+      lineno_counts += sym.n_numaux + 1;
     }
 
   BFD_ASSERT (last_real == NULL || last_real->next == first_csect);
@@ -2602,7 +2614,6 @@ xcoff_sweep (struct bfd_link_info *info)
 		{
 		  o->size = 0;
 		  o->reloc_count = 0;
-		  o->lineno_count = 0;
 		}
 	    }
 	}
@@ -3396,6 +3407,7 @@ bfd_xcoff_size_dynamic_sections (bfd *ou
       bfd_size_type symcount;
       long *debug_index;
       asection **csectpp;
+      unsigned int *lineno_counts;
       struct xcoff_link_hash_entry **sym_hash;
       bfd_byte *esym, *esymend;
       bfd_size_type symesz;
@@ -3439,6 +3451,7 @@ bfd_xcoff_size_dynamic_sections (bfd *ou
 	}
 
       csectpp = xcoff_data (sub)->csects;
+      lineno_counts = xcoff_data (sub)->lineno_counts;
       sym_hash = obj_xcoff_sym_hashes (sub);
       symesz = bfd_coff_symesz (sub);
       esym = (bfd_byte *) obj_coff_external_syms (sub);
@@ -3448,6 +3461,7 @@ bfd_xcoff_size_dynamic_sections (bfd *ou
 	{
 	  struct internal_syment sym;
 	  union internal_auxent aux;
+	  asection *csect;
 	  const char *name;
 	  int keep_p;
 
@@ -3473,8 +3487,9 @@ bfd_xcoff_size_dynamic_sections (bfd *ou
 	    name = NULL;
 
 	  /* Decide whether to copy this symbol to the output file.  */
+	  csect = *csectpp;
 	  keep_p = xcoff_keep_symbol_p (info, sub, &sym, &aux,
-					*sym_hash, *csectpp, name);
+					*sym_hash, csect, name);
 	  if (keep_p < 0)
 	    return FALSE;
 
@@ -3497,11 +3512,14 @@ bfd_xcoff_size_dynamic_sections (bfd *ou
 		}
 	      else
 		*debug_index = -1;
+	      if (*lineno_counts > 0)
+		csect->output_section->lineno_count += *lineno_counts;
 	    }
 
 	  esym += (sym.n_numaux + 1) * symesz;
 	  csectpp += sym.n_numaux + 1;
 	  sym_hash += sym.n_numaux + 1;
+	  lineno_counts += sym.n_numaux + 1;
 	  debug_index += sym.n_numaux + 1;
 	}
 
@@ -3590,6 +3608,7 @@ xcoff_link_input_bfd (struct xcoff_final
   struct xcoff_link_hash_entry **sym_hash;
   struct internal_syment *isymp;
   asection **csectpp;
+  unsigned int *lineno_counts;
   long *debug_index;
   long *indexp;
   unsigned long output_index;
@@ -3802,6 +3821,7 @@ #define N_BTSHFT n_btshft
   isymp = finfo->internal_syms;
   indexp = finfo->sym_indices;
   csectpp = xcoff_data (input_bfd)->csects;
+  lineno_counts = xcoff_data (input_bfd)->lineno_counts;
   debug_index = xcoff_data (input_bfd)->debug_indices;
   outsym = finfo->outsyms;
   incls = 0;
@@ -4056,8 +4076,7 @@ #define N_BTSHFT n_btshft
 		  && ISFCN (isymp->n_type)
 		  && aux.x_sym.x_fcnary.x_fcn.x_lnnoptr != 0)
 		{
-		  if (finfo->info->strip != strip_none
-		      && finfo->info->strip != strip_some)
+		  if (*lineno_counts == 0)
 		    aux.x_sym.x_fcnary.x_fcn.x_lnnoptr = 0;
 		  else
 		    {
@@ -4065,14 +4084,21 @@ #define N_BTSHFT n_btshft
 		      unsigned int enc_count;
 		      bfd_signed_vma linoff;
 		      struct internal_lineno lin;
+		      bfd_byte *linp;
+		      bfd_byte *linpend;
+		      bfd_vma offset;
+		      file_ptr pos;
+		      bfd_size_type amt;
 
+		      /* Read in the enclosing section's line-number
+			 information, if we haven't already.  */
 		      o = *csectpp;
 		      enclosing = xcoff_section_data (abfd, o)->enclosing;
 		      enc_count = xcoff_section_data (abfd, o)->lineno_count;
 		      if (oline != enclosing)
 			{
-			  file_ptr pos = enclosing->line_filepos;
-			  bfd_size_type amt = linesz * enc_count;
+			  pos = enclosing->line_filepos;
+			  amt = linesz * enc_count;
 			  if (bfd_seek (input_bfd, pos, SEEK_SET) != 0
 			      || (bfd_bread (finfo->linenos, amt, input_bfd)
 				  != amt))
@@ -4080,114 +4106,83 @@ #define N_BTSHFT n_btshft
 			  oline = enclosing;
 			}
 
+		      /* Copy across the first entry, adjusting its
+			 symbol index.  */
 		      linoff = (aux.x_sym.x_fcnary.x_fcn.x_lnnoptr
 				- enclosing->line_filepos);
-
-		      bfd_coff_swap_lineno_in (input_bfd,
-					       (void *) (finfo->linenos + linoff),
-					       (void *) &lin);
-		      if (lin.l_lnno != 0
-			  || ((bfd_size_type) lin.l_addr.l_symndx
-			      != ((esym
-				   - isymesz
-				   - ((bfd_byte *)
-				      obj_coff_external_syms (input_bfd)))
-				  / isymesz)))
-			aux.x_sym.x_fcnary.x_fcn.x_lnnoptr = 0;
-		      else
+		      linp = finfo->linenos + linoff;
+		      bfd_coff_swap_lineno_in (input_bfd, linp, &lin);
+		      lin.l_addr.l_symndx = *indexp;
+		      bfd_coff_swap_lineno_out (output_bfd, &lin, linp);
+		      linp += linesz;
+
+		      /* Copy the other entries, adjusting their addresses.  */
+		      linpend = linp + *lineno_counts * linesz;
+		      offset = (o->output_section->vma
+				+ o->output_offset
+				- o->vma);
+		      for (; linp < linpend; linp += linesz)
 			{
-			  bfd_byte *linpend, *linp;
-			  bfd_vma offset;
-			  bfd_size_type count;
-
-			  lin.l_addr.l_symndx = *indexp;
-			  bfd_coff_swap_lineno_out (output_bfd, (void *) &lin,
-						    (void *) (finfo->linenos
-							   + linoff));
-
-			  linpend = (finfo->linenos
-				     + enc_count * linesz);
-			  offset = (o->output_section->vma
-				    + o->output_offset
-				    - o->vma);
-			  for (linp = finfo->linenos + linoff + linesz;
-			       linp < linpend;
-			       linp += linesz)
-			    {
-			      bfd_coff_swap_lineno_in (input_bfd, (void *) linp,
-						       (void *) &lin);
-			      if (lin.l_lnno == 0)
-				break;
-			      lin.l_addr.l_paddr += offset;
-			      bfd_coff_swap_lineno_out (output_bfd,
-							(void *) &lin,
-							(void *) linp);
-			    }
-
-			  count = (linp - (finfo->linenos + linoff)) / linesz;
+			  bfd_coff_swap_lineno_in (input_bfd, linp, &lin);
+			  lin.l_addr.l_paddr += offset;
+			  bfd_coff_swap_lineno_out (output_bfd, &lin, linp);
+			}
 
-			  aux.x_sym.x_fcnary.x_fcn.x_lnnoptr =
-			    (o->output_section->line_filepos
+		      /* Write out the entries we've just processed.  */
+		      pos = (o->output_section->line_filepos
 			     + o->output_section->lineno_count * linesz);
+		      amt = linesz * *lineno_counts;
+		      if (bfd_seek (output_bfd, pos, SEEK_SET) != 0
+			  || bfd_bwrite (finfo->linenos + linoff,
+					 amt, output_bfd) != amt)
+			return FALSE;
+		      o->output_section->lineno_count += *lineno_counts;
 
-			  if (bfd_seek (output_bfd,
-					aux.x_sym.x_fcnary.x_fcn.x_lnnoptr,
-					SEEK_SET) != 0
-			      || (bfd_bwrite (finfo->linenos + linoff,
-					     linesz * count, output_bfd)
-				  != linesz * count))
-			    return FALSE;
-
-			  o->output_section->lineno_count += count;
+		      /* Record the offset of the symbol's line numbers
+			 in the output file.  */
+		      aux.x_sym.x_fcnary.x_fcn.x_lnnoptr = pos;
 
-			  if (incls > 0)
+		      if (incls > 0)
+			{
+			  struct internal_syment *iisp, *iispend;
+			  long *iindp;
+			  bfd_byte *oos;
+			  bfd_vma range_start, range_end;
+			  int iiadd;
+
+			  /* Update any C_BINCL or C_EINCL symbols
+			     that refer to a line number in the
+			     range we just output.  */
+			  iisp = finfo->internal_syms;
+			  iispend = iisp + obj_raw_syment_count (input_bfd);
+			  iindp = finfo->sym_indices;
+			  oos = finfo->outsyms;
+			  range_start = enclosing->line_filepos + linoff;
+			  range_end = range_start + *lineno_counts * linesz;
+			  while (iisp < iispend)
 			    {
-			      struct internal_syment *iisp, *iispend;
-			      long *iindp;
-			      bfd_byte *oos;
-			      int iiadd;
-
-			      /* Update any C_BINCL or C_EINCL symbols
-				 that refer to a line number in the
-				 range we just output.  */
-			      iisp = finfo->internal_syms;
-			      iispend = (iisp
-					 + obj_raw_syment_count (input_bfd));
-			      iindp = finfo->sym_indices;
-			      oos = finfo->outsyms;
-			      while (iisp < iispend)
+			      if (*iindp >= 0
+				  && (iisp->n_sclass == C_BINCL
+				      || iisp->n_sclass == C_EINCL)
+				  && iisp->n_value >= range_start
+				  && iisp->n_value < range_end)
 				{
-				  if (*iindp >= 0
-				      && (iisp->n_sclass == C_BINCL
-					  || iisp->n_sclass == C_EINCL)
-				      && ((bfd_size_type) iisp->n_value
-					  >= (bfd_size_type)(enclosing->line_filepos + linoff))
-				      && ((bfd_size_type) iisp->n_value
-					  < (enclosing->line_filepos
-					     + enc_count * linesz)))
-				    {
-				      struct internal_syment iis;
-
-				      bfd_coff_swap_sym_in (output_bfd,
-							    (void *) oos,
-							    (void *) &iis);
-				      iis.n_value =
-					(iisp->n_value
-					 - enclosing->line_filepos
-					 - linoff
-					 + aux.x_sym.x_fcnary.x_fcn.x_lnnoptr);
-				      bfd_coff_swap_sym_out (output_bfd,
-							     (void *) &iis,
-							     (void *) oos);
-				      --incls;
-				    }
-
-				  iiadd = 1 + iisp->n_numaux;
-				  if (*iindp >= 0)
-				    oos += iiadd * osymesz;
-				  iisp += iiadd;
-				  iindp += iiadd;
+				  struct internal_syment iis;
+
+				  bfd_coff_swap_sym_in (output_bfd, oos, &iis);
+				  iis.n_value = (iisp->n_value
+						 - range_start
+						 + pos);
+				  bfd_coff_swap_sym_out (output_bfd,
+							 &iis, oos);
+				  --incls;
 				}
+
+			      iiadd = 1 + iisp->n_numaux;
+			      if (*iindp >= 0)
+				oos += iiadd * osymesz;
+			      iisp += iiadd;
+			      iindp += iiadd;
 			    }
 			}
 		    }
@@ -4204,6 +4199,7 @@ #define N_BTSHFT n_btshft
       indexp += add;
       isymp += add;
       csectpp += add;
+      lineno_counts += add;
       debug_index += add;
     }
 
@@ -5498,15 +5494,15 @@ _bfd_xcoff_bfd_final_link (bfd *abfd, st
   if (finfo.strtab == NULL)
     goto error_return;
 
-  /* Count the line number and relocation entries required for the
-     output file.  Determine a few maximum sizes.  */
+  /* Count the relocation entries required for the output file.
+     (We've already counted the line numbers.)  Determine a few
+     maximum sizes.  */
   max_contents_size = 0;
   max_lineno_count = 0;
   max_reloc_count = 0;
   for (o = abfd->sections; o != NULL; o = o->next)
     {
       o->reloc_count = 0;
-      o->lineno_count = 0;
       for (p = o->map_head.link_order; p != NULL; p = p->next)
 	{
 	  if (p->type == bfd_indirect_link_order)
@@ -5521,18 +5517,12 @@ _bfd_xcoff_bfd_final_link (bfd *abfd, st
 		 the linker has decided to not include.  */
 	      sec->linker_mark = TRUE;
 
-	      if (info->strip == strip_none
-		  || info->strip == strip_some)
-		o->lineno_count += sec->lineno_count;
-
 	      o->reloc_count += sec->reloc_count;
 
 	      if (sec->rawsize > max_contents_size)
 		max_contents_size = sec->rawsize;
 	      if (sec->size > max_contents_size)
 		max_contents_size = sec->size;
-	      if (sec->lineno_count > max_lineno_count)
-		max_lineno_count = sec->lineno_count;
 	      if (coff_section_data (sec->owner, sec) != NULL
 		  && xcoff_section_data (sec->owner, sec) != NULL
 		  && (xcoff_section_data (sec->owner, sec)->lineno_count
Index: ld/testsuite/ld-powerpc/aix-lineno-1.s
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-lineno-1.s	2009-03-10 13:48:18.000000000 +0000
@@ -0,0 +1,25 @@
+	.file	"tmpdir/aix-lineno-1.txt"
+	.csect	.foo[PR]
+	.function .foo,.foo
+.foo:
+	.bf	1
+	nop
+	.line	2
+	nop
+	.line	3
+	nop
+	.line	4
+	nop
+	.line	5
+	nop
+	.ef	1
+
+	.globl	.main
+	.csect	.main[PR]
+	.function .main,.main
+.main:
+	.bf	7
+	bl	.foo
+	.line	2
+	nop
+	.ef	7
Index: ld/testsuite/ld-powerpc/aix-lineno-1.txt
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-lineno-1.txt	2009-03-10 13:48:18.000000000 +0000
@@ -0,0 +1,8 @@
+Four
+and
+twenty
+blackbirds
+baked
+in
+a
+pie
Index: ld/testsuite/ld-powerpc/aix-lineno-1a.dd
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-lineno-1a.dd	2009-03-10 13:48:18.000000000 +0000
@@ -0,0 +1,24 @@
+
+.*
+
+
+Disassembly of section \.text:
+
+0*10000000 <\.foo>:
+Four
+ *10000000:	60 00 00 00 	(oril    r0,r0,0|nop)
+and
+ *10000004:	60 00 00 00 	(oril    r0,r0,0|nop)
+twenty
+ *10000008:	60 00 00 00 	(oril    r0,r0,0|nop)
+blackbirds
+ *1000000c:	60 00 00 00 	(oril    r0,r0,0|nop)
+baked
+ *10000010:	60 00 00 00 	(oril    r0,r0,0|nop)
+
+0*10000014 <\.main>:
+in
+a
+ *10000014:	4b ff ff ed 	bl      10000000 <\.foo>
+pie
+ *10000018:	60 00 00 00 	(oril    r0,r0,0|nop)
Index: ld/testsuite/ld-powerpc/aix-lineno-1a.nd
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-lineno-1a.nd	2009-03-10 13:48:18.000000000 +0000
@@ -0,0 +1,8 @@
+0*10000000 t \.bf
+0*10000014 t \.bf
+0*10000014 t \.ef
+0*1000001c t \.ef
+0*10000000 t \.foo
+0*10000000 t \.foo
+0*10000014 t \.main
+0*10000014 T \.main
Index: ld/testsuite/ld-powerpc/aix-lineno-1b.dd
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-lineno-1b.dd	2009-03-10 13:48:18.000000000 +0000
@@ -0,0 +1,16 @@
+
+.*
+
+
+Disassembly of section \.text:
+
+0*10000000 <\.foo>:
+ *10000000:	60 00 00 00 	(oril    r0,r0,0|nop)
+ *10000004:	60 00 00 00 	(oril    r0,r0,0|nop)
+ *10000008:	60 00 00 00 	(oril    r0,r0,0|nop)
+ *1000000c:	60 00 00 00 	(oril    r0,r0,0|nop)
+ *10000010:	60 00 00 00 	(oril    r0,r0,0|nop)
+
+0*10000014 <\.main>:
+ *10000014:	4b ff ff ed 	bl      10000000 <\.foo>
+ *10000018:	60 00 00 00 	(oril    r0,r0,0|nop)
Index: ld/testsuite/ld-powerpc/aix-lineno-1b.nd
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-lineno-1b.nd	2009-03-10 13:48:18.000000000 +0000
@@ -0,0 +1,3 @@
+0*10000000 t \.foo
+0*10000014 t \.main
+0*10000014 T \.main
Index: ld/testsuite/ld-powerpc/aix52.exp
===================================================================
--- ld/testsuite/ld-powerpc/aix52.exp	2009-03-10 13:46:58.000000000 +0000
+++ ld/testsuite/ld-powerpc/aix52.exp	2009-03-10 13:48:18.000000000 +0000
@@ -64,6 +64,10 @@ proc run_aix_test { size name ldopts aso
 				 $output]]
 }
 
+foreach file { "aix-lineno-1.txt" } {
+    remote_upload host "$srcdir/$subdir/$file" "tmpdir/$file"
+}
+
 set aix52tests {
     {"Absolute branch test 1"
      "-shared -bI:aix-abs-branch-1.im -bE:aix-abs-branch-1.ex"
@@ -98,6 +102,16 @@ set aix52tests {
      {{objdump {-D -j.text -j.data} aix-glink-1-SIZE.dd}}
      "aix-glink-1.so"}
 
+    {"Line number test 1 (no discards)" "-e.main"
+     "" {aix-lineno-1.s}
+     {{objdump -dS aix-lineno-1a.dd} {nm {} aix-lineno-1a.nd}}
+     "aix-lineno-1a.exe"}
+
+    {"Line number test 1 (discard locals)" "-e.main -x"
+     "" {aix-lineno-1.s}
+     {{objdump -dS aix-lineno-1b.dd} {nm {} aix-lineno-1b.nd}}
+     "aix-lineno-1b.exe"}
+
     {"TOC test 1" "-shared -bE:aix-toc-1.ex"
      "" {aix-toc-1a.s aix-toc-1b.s}
      {{objdump -dr aix-toc-1-SIZE.dd}}

^ permalink raw reply	[flat|nested] 50+ messages in thread

* [14/21] Treat absolute imports as XTY_ER/XMC_XO
  2009-03-10 13:58 [0/21] Add support for AIX 6 Richard Sandiford
                   ` (13 preceding siblings ...)
  2009-03-10 14:36 ` [13/21] Fix counting of line-number entries Richard Sandiford
@ 2009-03-10 14:38 ` Richard Sandiford
  2009-03-13 15:11   ` Nick Clifton
  2009-03-10 14:40 ` [15/21] Avoid writing duplicate XCOFF symbols Richard Sandiford
                   ` (6 subsequent siblings)
  21 siblings, 1 reply; 50+ messages in thread
From: Richard Sandiford @ 2009-03-10 14:38 UTC (permalink / raw)
  To: binutils

The native XCOFF linker treats absolute imports as XTY_ER/XMC_XO,
so we ought to do the same.

Note that nm currently mistakes absolute symbols for common symbols.
I'm not intending to fix that.  (Can we say "C" is for constant? ;))

OK to install?

Richard


bfd/
	* xcofflink.c (bfd_xcoff_import_symbol): Treat imported absolute
	symbols as XMC_XO.

ld/testsuite/
	* ld-powerpc/aix-abs-branch-1.nd,
	ld-powerpc/aix-abs-reloc-1.nd: New tests.
	* ld-powerpc/aix52.exp: Run them.

Index: bfd/xcofflink.c
===================================================================
--- bfd/xcofflink.c	2009-03-10 13:48:18.000000000 +0000
+++ bfd/xcofflink.c	2009-03-10 13:48:48.000000000 +0000
@@ -2723,6 +2723,7 @@ bfd_xcoff_import_symbol (bfd *output_bfd
       h->root.type = bfd_link_hash_defined;
       h->root.u.def.section = bfd_abs_section_ptr;
       h->root.u.def.value = val;
+      h->smclas = XMC_XO;
     }
 
   if (!xcoff_set_import_path (info, h, imppath, impfile, impmember))
Index: ld/testsuite/ld-powerpc/aix-abs-branch-1.nd
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-abs-branch-1.nd	2009-03-10 13:48:48.000000000 +0000
@@ -0,0 +1,3 @@
+0*01450000 C bar
+0*10000000 t foo
+0*10000000 T foo
Index: ld/testsuite/ld-powerpc/aix-abs-reloc-1.nd
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-abs-reloc-1.nd	2009-03-10 13:48:48.000000000 +0000
@@ -0,0 +1,3 @@
+0*deadbeef C bar
+0*10000000 d foo
+0*10000000 D foo
Index: ld/testsuite/ld-powerpc/aix52.exp
===================================================================
--- ld/testsuite/ld-powerpc/aix52.exp	2009-03-10 13:48:18.000000000 +0000
+++ ld/testsuite/ld-powerpc/aix52.exp	2009-03-10 13:48:48.000000000 +0000
@@ -72,13 +72,13 @@ set aix52tests {
     {"Absolute branch test 1"
      "-shared -bI:aix-abs-branch-1.im -bE:aix-abs-branch-1.ex"
      "" {aix-abs-branch-1.s}
-     {{objdump {-dR} aix-abs-branch-1.dd}}
+     {{objdump {-dR} aix-abs-branch-1.dd} {nm {} aix-abs-branch-1.nd}}
      "aix-abs-branch-1.so"}
 
     {"Relocations against absolute symbols 1"
      "-shared -bI:aix-abs-reloc-1.im -bE:aix-abs-reloc-1.ex"
      {} {aix-abs-reloc-1.s}
-     {{objdump -sRj.data aix-abs-reloc-1.od}}
+     {{objdump -sRj.data aix-abs-reloc-1.od} {nm {} aix-abs-reloc-1.nd}}
      "aix-abs-reloc-1.so"}
 
     {"Core sections test 1" "-shared -bE:aix-core-sec-1.ex"

^ permalink raw reply	[flat|nested] 50+ messages in thread

* [15/21] Avoid writing duplicate XCOFF symbols
  2009-03-10 13:58 [0/21] Add support for AIX 6 Richard Sandiford
                   ` (14 preceding siblings ...)
  2009-03-10 14:38 ` [14/21] Treat absolute imports as XTY_ER/XMC_XO Richard Sandiford
@ 2009-03-10 14:40 ` Richard Sandiford
  2009-03-13 15:12   ` Nick Clifton
  2009-03-10 14:45 ` [16/21] Add AIX weak support Richard Sandiford
                   ` (5 subsequent siblings)
  21 siblings, 1 reply; 50+ messages in thread
From: Richard Sandiford @ 2009-03-10 14:40 UTC (permalink / raw)
  To: binutils

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}

^ permalink raw reply	[flat|nested] 50+ messages in thread

* [16/21] Add AIX weak support
  2009-03-10 13:58 [0/21] Add support for AIX 6 Richard Sandiford
                   ` (15 preceding siblings ...)
  2009-03-10 14:40 ` [15/21] Avoid writing duplicate XCOFF symbols Richard Sandiford
@ 2009-03-10 14:45 ` Richard Sandiford
  2009-03-13 15:17   ` Nick Clifton
  2009-03-10 14:46 ` [17/21] Suppor garbage collection without an entry point Richard Sandiford
                   ` (4 subsequent siblings)
  21 siblings, 1 reply; 50+ messages in thread
From: Richard Sandiford @ 2009-03-10 14:45 UTC (permalink / raw)
  To: binutils

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);
 }
 \f
+/* 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"

^ permalink raw reply	[flat|nested] 50+ messages in thread

* [17/21] Suppor garbage collection without an entry point
  2009-03-10 13:58 [0/21] Add support for AIX 6 Richard Sandiford
                   ` (16 preceding siblings ...)
  2009-03-10 14:45 ` [16/21] Add AIX weak support Richard Sandiford
@ 2009-03-10 14:46 ` Richard Sandiford
  2009-03-13 15:22   ` Nick Clifton
  2009-03-10 14:49 ` [18/21] Add -bexpall and -bexpfull Richard Sandiford
                   ` (3 subsequent siblings)
  21 siblings, 1 reply; 50+ messages in thread
From: Richard Sandiford @ 2009-03-10 14:46 UTC (permalink / raw)
  To: binutils

Although the AIX linker has a -bnogc option, I don't think it's expected
to be used much.  Garbage collection is the default, and the system
libraries tend to put several independent functions in the same archive
object.  (For example, as mentioned in a previous message, the libc.a
file that defines setjmp also defines a bunch of other less well-used
functions like ukey_setjmp.)

The GNU AIX linker also garbage-collects by default, but only for objects
with a defined entry point.  We ought to do garbage collection for shared
libraries too.

We're actually almost there.  We already mark all exported symbols and
the entry point.  We simply need to mark any init and fini functions too.

OK to install?

Richard


bfd/
	* xcofflink.c (xcoff_mark_symbol_by_name): New function.
	(bfd_xcoff_size_dynamic_sections): Use it to mark the entry,
	init and fini functions.  Do garbage collection for objects
	without an entry point too.

ld/testsuite/
	* ld-powerpc/aix-gc-1.s, ld-powerpc/aix-gc-1.ex,
	ld-powerpc/aix-gc-1-32.dd, ld-powerpc/aix-gc-1-64.dd,
	ld-powerpc/aix-weak-1-gcdso.dnd, ld-powerpc/aix-weak-1-gcdso.hd,
	ld-powerpc/aix-weak-1-gcdso.nd: New tests.
	* ld-powerpc/aix52.exp: Run them.

Index: bfd/xcofflink.c
===================================================================
--- bfd/xcofflink.c	2009-03-10 13:51:47.000000000 +0000
+++ bfd/xcofflink.c	2009-03-10 13:52:29.000000000 +0000
@@ -2482,6 +2482,30 @@ xcoff_mark_symbol (struct bfd_link_info 
   return TRUE;
 }
 
+/* Look for a symbol called NAME.  If the symbol is defined, mark it.
+   If the symbol exists, set FLAGS.  */
+
+static bfd_boolean
+xcoff_mark_symbol_by_name (struct bfd_link_info *info,
+			   const char *name, unsigned int flags)
+{
+  struct xcoff_link_hash_entry *h;
+
+  h = xcoff_link_hash_lookup (xcoff_hash_table (info), name,
+			      FALSE, FALSE, TRUE);
+  if (h != NULL)
+    {
+      h->flags |= flags;
+      if (h->root.type == bfd_link_hash_defined
+	  || h->root.type == bfd_link_hash_defweak)
+	{
+	  if (!xcoff_mark (info, h->root.u.def.section))
+	    return FALSE;
+	}
+    }
+  return TRUE;
+}
+
 /* The mark phase of garbage collection.  For a given section, mark
    it, and all the sections which define symbols to which it refers.
    Because this function needs to look at the relocs, we also count
@@ -3177,7 +3201,6 @@ bfd_xcoff_size_dynamic_sections (bfd *ou
 				 asection **special_sections,
 				 bfd_boolean rtld)
 {
-  struct xcoff_link_hash_entry *hentry;
   asection *lsec;
   struct xcoff_loader_info ldinfo;
   int i;
@@ -3216,15 +3239,6 @@ bfd_xcoff_size_dynamic_sections (bfd *ou
   xcoff_hash_table (info)->textro = textro;
   xcoff_hash_table (info)->rtld = rtld;
 
-  hentry = NULL;
-  if (entry != NULL)
-    {
-      hentry = xcoff_link_hash_lookup (xcoff_hash_table (info), entry,
-				       FALSE, FALSE, TRUE);
-      if (hentry != NULL)
-	hentry->flags |= XCOFF_ENTRY;
-    }
-
   /* __rtinit */
   if (info->init_function || info->fini_function || rtld)
     {
@@ -3277,11 +3291,7 @@ bfd_xcoff_size_dynamic_sections (bfd *ou
     }
 
   /* Garbage collect unused sections.  */
-  if (info->relocatable
-      || ! gc
-      || hentry == NULL
-      || (hentry->root.type != bfd_link_hash_defined
-	  && hentry->root.type != bfd_link_hash_defweak))
+  if (info->relocatable || !gc)
     {
       gc = FALSE;
       xcoff_hash_table (info)->gc = FALSE;
@@ -3309,7 +3319,14 @@ bfd_xcoff_size_dynamic_sections (bfd *ou
     }
   else
     {
-      if (! xcoff_mark (info, hentry->root.u.def.section))
+      if (entry != NULL
+	  && !xcoff_mark_symbol_by_name (info, entry, XCOFF_ENTRY))
+	goto error_return;
+      if (info->init_function != NULL
+	  && !xcoff_mark_symbol_by_name (info, info->init_function, 0))
+	goto error_return;
+      if (info->fini_function != NULL
+	  && !xcoff_mark_symbol_by_name (info, info->fini_function, 0))
 	goto error_return;
       xcoff_sweep (info);
       xcoff_hash_table (info)->gc = TRUE;
Index: ld/testsuite/ld-powerpc/aix-gc-1.s
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-gc-1.s	2009-03-10 13:52:29.000000000 +0000
@@ -0,0 +1,55 @@
+	.macro	loadtoc,sym
+	.if	size == 32
+	lwz	1,\sym(2)
+	.else
+	ld	1,\sym(2)
+	.endif
+	.endm
+
+	.toc
+LC01:	.tc	indirect1[TC],indirect1[RW]
+LC02:	.tc	block[TC],block[RW]
+
+	.csect	.unused_local[PR]
+.unused_local:
+	bl	.unused_global
+
+	.globl	.init_function
+	.csect	.init_function[PR]
+.init_function:
+	loadtoc	LC01
+
+	.globl	.fini_function
+	.csect	.fini_function[PR]
+.fini_function:
+	loadtoc	LC02
+
+	.globl	.unused_global
+	.csect	.unused_global[PR]
+.unused_global:
+	bl	.unused_local
+
+	.globl	.exported_global
+	.csect	.exported_global[PR]
+.exported_global:
+	bl	.indirect2
+
+	.globl	.indirect1
+	.csect	.indirect1[PR]
+.indirect1:
+	lwz	8,4(8)
+
+	.csect	.indirect2[PR]
+.indirect2:
+	lwz	8,8(8)
+
+	.globl	.indirect3
+	.csect	.indirect3[PR]
+.indirect3:
+	lwz	8,12(8)
+
+	.globl	block
+	.csect	block[RW]
+block:
+	.long	indirect3
+	.long	0x11223344
Index: ld/testsuite/ld-powerpc/aix-gc-1.ex
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-gc-1.ex	2009-03-10 13:52:29.000000000 +0000
@@ -0,0 +1,1 @@
+exported_global
Index: ld/testsuite/ld-powerpc/aix-gc-1-32.dd
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-gc-1-32.dd	2009-03-10 13:52:29.000000000 +0000
@@ -0,0 +1,67 @@
+
+.*
+
+
+Disassembly of section \.text:
+
+10000000 <\.init_function>:
+10000000:	80 22 00 00 	l       r1,0\(r2\)
+
+10000004 <\.fini_function>:
+10000004:	80 22 00 04 	l       r1,4\(r2\)
+
+10000008 <\.exported_global>:
+10000008:	48 00 00 09 	bl      10000010 <\.indirect2>
+
+1000000c <\.indirect1>:
+1000000c:	81 08 00 04 	l       r8,4\(r8\)
+
+10000010 <\.indirect2>:
+10000010:	81 08 00 08 	l       r8,8\(r8\)
+
+10000014 <\.indirect3>:
+10000014:	81 08 00 0c 	l       r8,12\(r8\)
+
+Disassembly of section \.data:
+
+20000000 <block>:
+# Pointer to indirect3.
+20000000:	20 00 00 98 	.*
+20000004:	11 22 33 44 	.*
+
+20000008 <__rtinit>:
+#...
+
+20000068 <exported_global>:
+20000068:	10 00 00 08 	.*
+2000006c:	20 00 00 a4 	.*
+20000070:	00 00 00 00 	.*
+
+20000074 <init_function>:
+20000074:	10 00 00 00 	.*
+20000078:	20 00 00 a4 	.*
+2000007c:	00 00 00 00 	.*
+
+20000080 <indirect1>:
+20000080:	10 00 00 0c 	.*
+20000084:	20 00 00 a4 	.*
+20000088:	00 00 00 00 	.*
+
+2000008c <fini_function>:
+2000008c:	10 00 00 04 	.*
+20000090:	20 00 00 a4 	.*
+20000094:	00 00 00 00 	.*
+
+20000098 <indirect3>:
+20000098:	10 00 00 14 	.*
+2000009c:	20 00 00 a4 	.*
+200000a0:	00 00 00 00 	.*
+
+200000a4 <TOC>:
+# TOC entry for indirect1.
+200000a4:	20 00 00 80 	.*
+
+200000a8 <block>:
+# TOC entry for block.
+200000a8:	20 00 00 00 	.*
+200000ac:	00 00 00 00 	.*
Index: ld/testsuite/ld-powerpc/aix-gc-1-64.dd
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-gc-1-64.dd	2009-03-10 13:52:29.000000000 +0000
@@ -0,0 +1,81 @@
+
+.*
+
+
+Disassembly of section \.text:
+
+0000000010000000 <\.init_function>:
+    10000000:	e8 22 00 00 	ld      r1,0\(r2\)
+
+0000000010000004 <\.fini_function>:
+    10000004:	e8 22 00 08 	ld      r1,8\(r2\)
+
+0000000010000008 <\.exported_global>:
+    10000008:	48 00 00 09 	bl      10000010 <\.indirect2>
+
+000000001000000c <\.indirect1>:
+    1000000c:	81 08 00 04 	lwz     r8,4\(r8\)
+
+0000000010000010 <\.indirect2>:
+    10000010:	81 08 00 08 	lwz     r8,8\(r8\)
+
+0000000010000014 <\.indirect3>:
+    10000014:	81 08 00 0c 	lwz     r8,12\(r8\)
+
+Disassembly of section \.data:
+
+0000000020000000 <block>:
+# Pointer to indirect3.
+    20000000:	20 00 00 e0 	.*
+    20000004:	11 22 33 44 	.*
+
+0000000020000008 <__rtinit>:
+#...
+
+0000000020000080 <exported_global>:
+    20000080:	00 00 00 00 	.*
+    20000084:	10 00 00 08 	.*
+    20000088:	00 00 00 00 	.*
+    2000008c:	20 00 00 f8 	.*
+    20000090:	00 00 00 00 	.*
+    20000094:	00 00 00 00 	.*
+
+0000000020000098 <init_function>:
+    20000098:	00 00 00 00 	.*
+    2000009c:	10 00 00 00 	.*
+    200000a0:	00 00 00 00 	.*
+    200000a4:	20 00 00 f8 	.*
+    200000a8:	00 00 00 00 	.*
+    200000ac:	00 00 00 00 	.*
+
+00000000200000b0 <indirect1>:
+    200000b0:	00 00 00 00 	.*
+    200000b4:	10 00 00 0c 	.*
+    200000b8:	00 00 00 00 	.*
+    200000bc:	20 00 00 f8 	.*
+    200000c0:	00 00 00 00 	.*
+    200000c4:	00 00 00 00 	.*
+
+00000000200000c8 <fini_function>:
+    200000c8:	00 00 00 00 	.*
+    200000cc:	10 00 00 04 	.*
+    200000d0:	00 00 00 00 	.*
+    200000d4:	20 00 00 f8 	.*
+    200000d8:	00 00 00 00 	.*
+    200000dc:	00 00 00 00 	.*
+
+00000000200000e0 <indirect3>:
+    200000e0:	00 00 00 00 	.*
+    200000e4:	10 00 00 14 	.*
+    200000e8:	00 00 00 00 	.*
+    200000ec:	20 00 00 f8 	.*
+    200000f0:	00 00 00 00 	.*
+    200000f4:	00 00 00 00 	.*
+
+00000000200000f8 <TOC>:
+    200000f8:	00 00 00 00 	.*
+    200000fc:	20 00 00 b0 	.*
+
+0000000020000100 <block>:
+    20000100:	00 00 00 00 	.*
+    20000104:	20 00 00 00 	.*
Index: ld/testsuite/ld-powerpc/aix-weak-1-gcdso.dnd
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-weak-1-gcdso.dnd	2009-03-10 13:52:29.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*1000000c D a
+# (strong common) wins over (weak data)
+0*10000018 B b
+# (strong data) wins over (strong common)
+0*10000000 D c
+# (weak data) loses to (strong common)
+0*10000020 B d
+# (weak common) loses to (strong data)
+0*10000010 D e
+# (weak common) wins over (weak data)
+0*1000001c W f
+# (strong data) wins over (weak common)
+0*10000004 D g
+# (weak data) wins over (weak common)
+0*10000008 W h
Index: ld/testsuite/ld-powerpc/aix-weak-1-gcdso.hd
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-weak-1-gcdso.hd	2009-03-10 13:52:29.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+18 * 0*10000000 * 0*10000000 * [^ ]+ * 2\*\*3
+ *CONTENTS, ALLOC, LOAD, DATA
+# Should only have 3 three common symbols.
+ *2 \.bss  * 0+0c * 0*10000018 * 0*10000018 * [^ ]+ * 2\*\*3
+ *ALLOC
+#pass
Index: ld/testsuite/ld-powerpc/aix-weak-1-gcdso.nd
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-weak-1-gcdso.nd	2009-03-10 13:52:29.000000000 +0000
@@ -0,0 +1,22 @@
+# Comments are (aix-weak-1a.s type) wins over/loses to (aix-weak-1b.s type)
+# (strong common) loses to (strong data)
+0*1000000c d a
+0*1000000c D a
+# (strong common) wins over (weak data)
+0*10000018 B b
+# (strong data) wins over (strong common)
+0*10000000 d c
+0*10000000 D c
+# (weak data) loses to (strong common)
+0*10000020 B d
+# (weak common) loses to (strong data)
+0*10000010 d e
+0*10000010 D e
+# (weak common) wins over (weak data)
+0*1000001c W f
+# (strong data) wins over (weak common)
+0*10000004 d g
+0*10000004 D g
+# (weak data) wins over (weak common)
+0*10000008 d h
+0*10000008 W h
Index: ld/testsuite/ld-powerpc/aix52.exp
===================================================================
--- ld/testsuite/ld-powerpc/aix52.exp	2009-03-10 13:51:47.000000000 +0000
+++ ld/testsuite/ld-powerpc/aix52.exp	2009-03-10 13:52:29.000000000 +0000
@@ -108,6 +108,12 @@ set aix52tests {
       {nm -D aix-no-dup-syms-1-dso.dnd} {objdump -R aix-no-dup-syms-1-dso.drd}}
      "aix-no-dup-syms-1.so"}
 
+    {"Garbage collection test 1"
+     "-shared -binitfini:init_function:fini_function -bE:aix-gc-1.ex"
+     "" {aix-gc-1.s}
+     {{objdump {-dz -j.text -j.data} aix-gc-1-SIZE.dd}}
+     "aix-gc-1.so"}
+
     {"Glink test 1"
      "-shared -bE:aix-glink-1.ex --unresolved-symbols=ignore-all"
      "" {aix-glink-1.s}
@@ -156,6 +162,12 @@ set aix52tests {
       {nm -D aix-weak-1-dso.dnd}}
      "aix-weak-1-nogc.so"}
 
+    {"Weak test 1 (shared, gc)" "-shared -bE:aix-weak-1.ex"
+     "" {aix-weak-1a.s aix-weak-1b.s}
+     {{nm {} aix-weak-1-gcdso.nd} {objdump -h aix-weak-1-gcdso.hd}
+      {nm -D aix-weak-1-gcdso.dnd}}
+     "aix-weak-1-gc.so"}
+
     {"Weak test 2 (library 1)" "-shared -bE:aix-weak-2a.ex"
      "" {aix-weak-2a.s}
      {{nm -D aix-weak-2a.nd}}

^ permalink raw reply	[flat|nested] 50+ messages in thread

* [18/21] Add -bexpall and -bexpfull
  2009-03-10 13:58 [0/21] Add support for AIX 6 Richard Sandiford
                   ` (17 preceding siblings ...)
  2009-03-10 14:46 ` [17/21] Suppor garbage collection without an entry point Richard Sandiford
@ 2009-03-10 14:49 ` Richard Sandiford
  2009-03-13 15:21   ` Nick Clifton
  2009-03-10 14:50 ` [19/21] Give imported function descriptors class XMC_DS Richard Sandiford
                   ` (2 subsequent siblings)
  21 siblings, 1 reply; 50+ messages in thread
From: Richard Sandiford @ 2009-03-10 14:49 UTC (permalink / raw)
  To: binutils

The native AIX linker has two options called -bexpall and -bexpfull.
This patch adds support to the GNU linker.

Support for -bexpfull-like behaviour is already there for non-gc links,
in the form of -unix.  We simply need to extend it to gc links by
marking all symbols that need to be exported.  Support for -bexpall is a
simple extension of this.

The current code doesn't export symbols from archives that contain
shared objects:

  /* We don't export a symbol which is being defined by an object
     included from an archive which contains a shared object.  The
     rationale is that if an archive contains both an unshared and
     a shared object, then there must be some reason that the
     unshared object is unshared, and we don't want to start
     providing a shared version of it.  In particular, this solves
     a bug involving the _savefNN set of functions.  gcc will call
     those functions without providing a slot to restore the TOC,
     so it is essential that these functions be linked in directly
     and not from a shared object, which means that a shared
     object which also happens to link them in must not export
     them.  This is confusing, but I haven't been able to think of
     a different approach.  Note that the symbols can, of course,
     be exported explicitly.  */

I think this diverges from the native linker, but the reason is
explained fairly well, so I kept it.

The existing code actually walks the archive for every symbol it
is given, which seems rather inefficient, but I kept that too.
Adding some sort of cache is a possible future refinement.

There's no documentation or help output for the new options because
I couldn't find any for the existing ones.  I'm afraid fixing that
is beyond what I have time for right now.

OK to install?

Richard


include/coff/
	* xcoff.h (XCOFF_EXPALL, XCOFF_EXPFULL): New flags.
	(xcoff_loader_info): Add auto_export_flags.

bfd/
	* bfd-in.h (bfd_xcoff_size_dynamic_sections): Replace the
	bfd_boolean export_defineds parameter with an unsigned int
	auto_export_flags parameter.
	* bfd-in2.h: Regenerate.
	* xcofflink.c (xcoff_archive_contains_shared_object_p): New function,
	split out from xcoff_build_ldsyms.
	(xcoff_covered_by_expall_p): New function.
	(xcoff_auto_export_p): New function, split out from xcoff_build_ldsyms
	but with extra code to handle -bexpfull and -bexpall.
	(xcoff_mark_auto_exports): New function.
	(xcoff_build_ldsyms): Use xcoff_auto_export_p to decide whether
	a function should be automatically exported.
	(bfd_xcoff_size_dynamic_sections): Replace the export_defineds
	parameter with an auto_export_flags parameter.  Update ldinfo
	accordingly.  Use xcoff_mark_auto_exports to mark all automatically-
	exported symbols.

ld/
	* emultempl/aix.em (auto_export_flags): New variable.
	(explicit_auto_export_flags): Likewise.
	(OPTION_EXPALL, OPTION_EXPFULL): New enum values.
	(OPTION_NOEXPALL, OPTION_NOEXPFULL): Likewise.
	(gld${EMULATION_NAME}_add_options): Add -bexpall, -bexpfull,
	-bnoexpall and -bnoexpfull.
	(gld${EMULATION_NAME}_handle_option): Handle them.
	(gld${EMULATION_NAME}_before_allocation): Update the call to
	bfd_size_dynamic_sections.

ld/testsuite/
	* ld-powerpc/aix-export-1-all.dd, ld-powerpc/aix-export-1-full.dd,
	ld-powerpc/aix-export-1a.s, ld-powerpc/aix-export-1b.s: New tests.
	* ld-powerpc/aix52.exp: Run them.

Index: include/coff/xcoff.h
===================================================================
--- include/coff/xcoff.h	2009-03-10 13:51:47.000000000 +0000
+++ include/coff/xcoff.h	2009-03-10 13:52:51.000000000 +0000
@@ -394,6 +394,9 @@ struct xcoff_link_hash_table
   asection *special_sections[XCOFF_NUMBER_OF_SPECIAL_SECTIONS];
 };
 
+/* These flags indicate which of -bexpall and -bexpfull are in effect.  */
+#define XCOFF_EXPALL 1
+#define XCOFF_EXPFULL 2
 
 /* This structure is used to pass information through
    xcoff_link_hash_traverse.  */
@@ -409,8 +412,8 @@ struct xcoff_loader_info
   /* Link information structure.  */
   struct bfd_link_info *info;
 
-  /* Whether all defined symbols should be exported.  */
-  bfd_boolean export_defineds;
+  /* A mask of XCOFF_EXPALL and XCOFF_EXPFULL flags.  */
+  unsigned int auto_export_flags;
 
   /* Number of ldsym structures.  */
   size_t ldsym_count;
Index: bfd/bfd-in.h
===================================================================
--- bfd/bfd-in.h	2009-03-10 13:38:52.000000000 +0000
+++ bfd/bfd-in.h	2009-03-10 13:52:51.000000000 +0000
@@ -779,7 +779,7 @@ typedef struct _bfd_window
 extern bfd_boolean bfd_xcoff_size_dynamic_sections
   (bfd *, struct bfd_link_info *, const char *, const char *,
    unsigned long, unsigned long, unsigned long, bfd_boolean,
-   int, bfd_boolean, bfd_boolean, struct bfd_section **, bfd_boolean);
+   int, bfd_boolean, unsigned int, struct bfd_section **, bfd_boolean);
 extern bfd_boolean bfd_xcoff_link_generate_rtinit
   (bfd *, const char *, const char *, bfd_boolean);
 
Index: bfd/bfd-in2.h
===================================================================
--- bfd/bfd-in2.h	2009-03-10 13:38:52.000000000 +0000
+++ bfd/bfd-in2.h	2009-03-10 13:52:51.000000000 +0000
@@ -786,7 +786,7 @@ typedef struct _bfd_window
 extern bfd_boolean bfd_xcoff_size_dynamic_sections
   (bfd *, struct bfd_link_info *, const char *, const char *,
    unsigned long, unsigned long, unsigned long, bfd_boolean,
-   int, bfd_boolean, bfd_boolean, struct bfd_section **, bfd_boolean);
+   int, bfd_boolean, unsigned int, struct bfd_section **, bfd_boolean);
 extern bfd_boolean bfd_xcoff_link_generate_rtinit
   (bfd *, const char *, const char *, bfd_boolean);
 
Index: bfd/xcofflink.c
===================================================================
--- bfd/xcofflink.c	2009-03-10 13:52:29.000000000 +0000
+++ bfd/xcofflink.c	2009-03-10 13:52:51.000000000 +0000
@@ -2313,6 +2313,97 @@ xcoff_set_import_path (struct bfd_link_i
   return TRUE;
 }
 \f
+/* Return true if the given bfd contains at least one shared object.  */
+
+static bfd_boolean
+xcoff_archive_contains_shared_object_p (bfd *archive)
+{
+  bfd *member;
+
+  member = bfd_openr_next_archived_file (archive, NULL);
+  while (member != NULL && (member->flags & DYNAMIC) == 0)
+    member = bfd_openr_next_archived_file (archive, member);
+  return member != NULL;
+}
+
+/* Symbol H qualifies for export by -bexpfull.  Return true if it also
+   qualifies for export by -bexpall.  */
+
+static bfd_boolean
+xcoff_covered_by_expall_p (struct xcoff_link_hash_entry *h)
+{
+  /* Exclude symbols beginning with '_'.  */
+  if (h->root.root.string[0] == '_')
+    return FALSE;
+
+  /* Exclude archive members that would otherwise be unreferenced.  */
+  if ((h->flags & XCOFF_MARK) == 0
+      && (h->root.type == bfd_link_hash_defined
+	  || h->root.type == bfd_link_hash_defweak)
+      && h->root.u.def.section->owner != NULL
+      && h->root.u.def.section->owner->my_archive != NULL)
+    return FALSE;
+
+  return TRUE;
+}
+
+/* Return true if symbol H qualifies for the forms of automatic export
+   specified by AUTO_EXPORT_FLAGS.  */
+
+static bfd_boolean
+xcoff_auto_export_p (struct xcoff_link_hash_entry *h,
+		     unsigned int auto_export_flags)
+{
+  /* Don't automatically export things that were explicitly exported.  */
+  if ((h->flags & XCOFF_EXPORT) != 0)
+    return FALSE;
+
+  /* Don't export things that we don't define.  */
+  if ((h->flags & XCOFF_DEF_REGULAR) == 0)
+    return FALSE;
+
+  /* Don't export functions; export their descriptors instead.  */
+  if (h->root.root.string[0] == '.')
+    return FALSE;
+
+  /* We don't export a symbol which is being defined by an object
+     included from an archive which contains a shared object.  The
+     rationale is that if an archive contains both an unshared and
+     a shared object, then there must be some reason that the
+     unshared object is unshared, and we don't want to start
+     providing a shared version of it.  In particular, this solves
+     a bug involving the _savefNN set of functions.  gcc will call
+     those functions without providing a slot to restore the TOC,
+     so it is essential that these functions be linked in directly
+     and not from a shared object, which means that a shared
+     object which also happens to link them in must not export
+     them.  This is confusing, but I haven't been able to think of
+     a different approach.  Note that the symbols can, of course,
+     be exported explicitly.  */
+  if (h->root.type == bfd_link_hash_defined
+      || h->root.type == bfd_link_hash_defweak)
+    {
+      bfd *owner;
+
+      owner = h->root.u.def.section->owner;
+      if (owner != NULL
+	  && owner->my_archive != NULL
+	  && xcoff_archive_contains_shared_object_p (owner->my_archive))
+	return FALSE;
+    }
+
+  /* Otherwise, all symbols are exported by -bexpfull.  */
+  if ((auto_export_flags & XCOFF_EXPFULL) != 0)
+    return TRUE;
+
+  /* Despite its name, -bexpall exports most but not all symbols.  */
+  if ((auto_export_flags & XCOFF_EXPALL) != 0
+      && xcoff_covered_by_expall_p (h))
+    return TRUE;
+
+  return FALSE;
+}
+\f
 /* Mark a symbol as not being garbage, including the section in which
    it is defined.  */
 
@@ -2878,6 +2969,24 @@ bfd_xcoff_record_link_assignment (bfd *o
   return TRUE;
 }
 
+/* An xcoff_link_hash_traverse callback for which DATA points to an
+   xcoff_loader_info.  Mark all symbols that should be automatically
+   exported.  */
+
+static bfd_boolean
+xcoff_mark_auto_exports (struct xcoff_link_hash_entry *h, void *data)
+{
+  struct xcoff_loader_info *ldinfo;
+
+  ldinfo = (struct xcoff_loader_info *) data;
+  if (xcoff_auto_export_p (h, ldinfo->auto_export_flags))
+    {
+      if (!xcoff_mark_symbol (ldinfo->info, h))
+	ldinfo->failed = TRUE;
+    }
+  return TRUE;
+}
+
 /* Add a symbol to the .loader symbols, if necessary.  */
 
 /* INPUT_BFD has an external symbol associated with hash table entry H
@@ -2939,50 +3048,8 @@ xcoff_build_ldsyms (struct xcoff_link_ha
   /* If all defined symbols should be exported, mark them now.  We
      don't want to export the actual functions, just the function
      descriptors.  */
-  if (ldinfo->export_defineds
-      && (h->flags & XCOFF_DEF_REGULAR) != 0
-      && h->root.root.string[0] != '.')
-    {
-      bfd_boolean export;
-
-      /* We don't export a symbol which is being defined by an object
-	 included from an archive which contains a shared object.  The
-	 rationale is that if an archive contains both an unshared and
-	 a shared object, then there must be some reason that the
-	 unshared object is unshared, and we don't want to start
-	 providing a shared version of it.  In particular, this solves
-	 a bug involving the _savefNN set of functions.  gcc will call
-	 those functions without providing a slot to restore the TOC,
-	 so it is essential that these functions be linked in directly
-	 and not from a shared object, which means that a shared
-	 object which also happens to link them in must not export
-	 them.  This is confusing, but I haven't been able to think of
-	 a different approach.  Note that the symbols can, of course,
-	 be exported explicitly.  */
-      export = TRUE;
-      if ((h->root.type == bfd_link_hash_defined
-	   || h->root.type == bfd_link_hash_defweak)
-	  && h->root.u.def.section->owner != NULL
-	  && h->root.u.def.section->owner->my_archive != NULL)
-	{
-	  bfd *arbfd, *member;
-
-	  arbfd = h->root.u.def.section->owner->my_archive;
-	  member = bfd_openr_next_archived_file (arbfd, NULL);
-	  while (member != NULL)
-	    {
-	      if ((member->flags & DYNAMIC) != 0)
-		{
-		  export = FALSE;
-		  break;
-		}
-	      member = bfd_openr_next_archived_file (arbfd, member);
-	    }
-	}
-
-      if (export)
-	h->flags |= XCOFF_EXPORT;
-    }
+  if (xcoff_auto_export_p (h, ldinfo->auto_export_flags))
+    h->flags |= XCOFF_EXPORT;
 
   /* We don't want to garbage collect symbols which are not defined in
      XCOFF files.  This is a convenient place to mark them.  */
@@ -3181,10 +3248,9 @@ xcoff_keep_symbol_p (struct bfd_link_inf
    -bmaxdata linker option).  GC is whether to do garbage collection
    (the -bgc linker option).  MODTYPE is the module type (the
    -bmodtype linker option).  TEXTRO is whether the text section must
-   be read only (the -btextro linker option).  EXPORT_DEFINEDS is
-   whether all defined symbols should be exported (the -unix linker
-   option).  SPECIAL_SECTIONS is set by this routine to csects with
-   magic names like _end.  */
+   be read only (the -btextro linker option).  AUTO_EXPORT_FLAGS
+   is a mask of XCOFF_EXPALL and XCOFF_EXPFULL.  SPECIAL_SECTIONS
+   is set by this routine to csects with magic names like _end.  */
 
 bfd_boolean
 bfd_xcoff_size_dynamic_sections (bfd *output_bfd,
@@ -3197,7 +3263,7 @@ bfd_xcoff_size_dynamic_sections (bfd *ou
 				 bfd_boolean gc,
 				 int modtype,
 				 bfd_boolean textro,
-				 bfd_boolean export_defineds,
+				 unsigned int auto_export_flags,
 				 asection **special_sections,
 				 bfd_boolean rtld)
 {
@@ -3225,7 +3291,7 @@ bfd_xcoff_size_dynamic_sections (bfd *ou
   ldinfo.failed = FALSE;
   ldinfo.output_bfd = output_bfd;
   ldinfo.info = info;
-  ldinfo.export_defineds = export_defineds;
+  ldinfo.auto_export_flags = auto_export_flags;
   ldinfo.ldsym_count = 0;
   ldinfo.string_size = 0;
   ldinfo.strings = NULL;
@@ -3328,6 +3394,13 @@ bfd_xcoff_size_dynamic_sections (bfd *ou
       if (info->fini_function != NULL
 	  && !xcoff_mark_symbol_by_name (info, info->fini_function, 0))
 	goto error_return;
+      if (auto_export_flags != 0)
+	{
+	  xcoff_link_hash_traverse (xcoff_hash_table (info),
+				    xcoff_mark_auto_exports, &ldinfo);
+	  if (ldinfo.failed)
+	    goto error_return;
+	}
       xcoff_sweep (info);
       xcoff_hash_table (info)->gc = TRUE;
     }
Index: ld/emultempl/aix.em
===================================================================
--- ld/emultempl/aix.em	2009-03-10 13:46:23.000000000 +0000
+++ ld/emultempl/aix.em	2009-03-10 13:52:51.000000000 +0000
@@ -84,6 +84,14 @@ static unsigned short modtype = ('1' << 
    permitted).  */
 static int textro;
 
+/* A mask of XCOFF_EXPALL and XCOFF_EXPFULL flags, as set by their
+   associated -b and -bno options.  */
+static unsigned int auto_export_flags;
+
+/* A mask of auto_export_flags bits that were explicitly set on the
+   command line.  */
+static unsigned int explicit_auto_export_flags;
+
 /* Whether to implement Unix like linker semantics.  */
 static int unix_ld;
 
@@ -156,6 +164,8 @@ enum
     OPTION_AUTOIMP,
     OPTION_ERNOTOK,
     OPTION_EROK,
+    OPTION_EXPALL,
+    OPTION_EXPFULL,
     OPTION_EXPORT,
     OPTION_IMPORT,
     OPTION_INITFINI,
@@ -164,6 +174,8 @@ enum
     OPTION_MAXSTACK,
     OPTION_MODTYPE,
     OPTION_NOAUTOIMP,
+    OPTION_NOEXPALL,
+    OPTION_NOEXPFULL,
     OPTION_NOSTRCMPCT,
     OPTION_PD,
     OPTION_PT,
@@ -201,6 +213,8 @@ gld${EMULATION_NAME}_add_options
     {"bernotok", no_argument, NULL, OPTION_ERNOTOK},
     {"berok", no_argument, NULL, OPTION_EROK},
     {"berrmsg", no_argument, NULL, OPTION_IGNORE},
+    {"bexpall", no_argument, NULL, OPTION_EXPALL},
+    {"bexpfull", no_argument, NULL, OPTION_EXPFULL},
     {"bexport", required_argument, NULL, OPTION_EXPORT},
     {"bf", no_argument, NULL, OPTION_ERNOTOK},
     {"bgc", no_argument, &gc, 1},
@@ -216,6 +230,8 @@ gld${EMULATION_NAME}_add_options
     {"bM", required_argument, NULL, OPTION_MODTYPE},
     {"bmodtype", required_argument, NULL, OPTION_MODTYPE},
     {"bnoautoimp", no_argument, NULL, OPTION_NOAUTOIMP},
+    {"bnoexpall", no_argument, NULL, OPTION_NOEXPALL},
+    {"bnoexpfull", no_argument, NULL, OPTION_NOEXPFULL},
     {"bnodelcsect", no_argument, NULL, OPTION_IGNORE},
     {"bnoentry", no_argument, NULL, OPTION_IGNORE},
     {"bnogc", no_argument, &gc, 0},
@@ -388,6 +404,16 @@ gld${EMULATION_NAME}_handle_option (int 
       link_info.unresolved_syms_in_shared_libs = RM_IGNORE;
       break;
 
+    case OPTION_EXPALL:
+      auto_export_flags |= XCOFF_EXPALL;
+      explicit_auto_export_flags |= XCOFF_EXPALL;
+      break;
+
+    case OPTION_EXPFULL:
+      auto_export_flags |= XCOFF_EXPFULL;
+      explicit_auto_export_flags |= XCOFF_EXPFULL;
+      break;
+
     case OPTION_EXPORT:
       gld${EMULATION_NAME}_read_file (optarg, FALSE);
       break;
@@ -444,6 +470,16 @@ gld${EMULATION_NAME}_handle_option (int 
       link_info.static_link = TRUE;
       break;
 
+    case OPTION_NOEXPALL:
+      auto_export_flags &= ~XCOFF_EXPALL;
+      explicit_auto_export_flags |= XCOFF_EXPALL;
+      break;
+
+    case OPTION_NOEXPFULL:
+      auto_export_flags &= ~XCOFF_EXPFULL;
+      explicit_auto_export_flags |= XCOFF_EXPFULL;
+      break;
+
     case OPTION_NOSTRCMPCT:
       link_info.traditional_format = TRUE;
       break;
@@ -624,7 +660,7 @@ gld${EMULATION_NAME}_before_allocation (
     ".data",
     ".bss"
   };
-  unsigned int i;
+  unsigned int i, flags;
 
   /* Handle the import and export files, if any.  */
   for (fl = import_files; fl != NULL; fl = fl->next)
@@ -710,11 +746,16 @@ gld${EMULATION_NAME}_before_allocation (
 	}
     }
 
+  /* Default to -bexpfull for SVR4-like semantics.  */
+  flags = (unix_ld ? XCOFF_EXPFULL : 0);
+  flags &= ~explicit_auto_export_flags;
+  flags |= auto_export_flags;
+
   /* Let the XCOFF backend set up the .loader section.  */
   if (!bfd_xcoff_size_dynamic_sections
       (link_info.output_bfd, &link_info, libpath, entry_symbol.name, file_align,
        maxstack, maxdata, gc && !unix_ld ? TRUE : FALSE,
-       modtype,	textro ? TRUE : FALSE, unix_ld, special_sections,
+       modtype, textro ? TRUE : FALSE, flags, special_sections,
        rtld ? TRUE : FALSE))
     einfo ("%P%F: failed to set dynamic section sizes: %E\n");
 
Index: ld/testsuite/ld-powerpc/aix-export-1-all.dd
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-export-1-all.dd	2009-03-10 13:52:51.000000000 +0000
@@ -0,0 +1,11 @@
+
+.*
+
+
+Disassembly of section \.data:
+
+0*10000000 <main1>:
+ *10000000:	10 00 00 04 	.*
+
+0*10000004 <lib1>:
+ *10000004:	11 11 00 01 	.*
Index: ld/testsuite/ld-powerpc/aix-export-1-full.dd
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-export-1-full.dd	2009-03-10 13:52:51.000000000 +0000
@@ -0,0 +1,21 @@
+
+.*
+
+
+Disassembly of section .data:
+
+0*10000000 <main1>:
+ *10000000:	10 00 00 08 	.*
+
+0*10000004 <_main2>:
+ *10000004:	10 00 00 0c 	.*
+
+0*10000008 <lib1>:
+ *10000008:	11 11 00 01 	.*
+
+0*1000000c <_lib2>:
+ *1000000c:	11 11 00 02 	.*
+
+0*10000010 <lib3>:
+ *10000010:	11 11 00 03 	.*
+ *10000014:	00 00 00 00 	.*
Index: ld/testsuite/ld-powerpc/aix-export-1a.s
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-export-1a.s	2009-03-10 13:52:51.000000000 +0000
@@ -0,0 +1,14 @@
+	.globl	lib1
+	.csect	lib1[RW]
+lib1:
+	.long	0x11110001
+
+	.globl	_lib2
+	.csect	_lib2[RW]
+_lib2:
+	.long	0x11110002
+
+	.globl	lib3
+	.csect	lib3[RW]
+lib3:
+	.long	0x11110003
Index: ld/testsuite/ld-powerpc/aix-export-1b.s
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-export-1b.s	2009-03-10 13:52:51.000000000 +0000
@@ -0,0 +1,9 @@
+	.globl	main1
+	.csect	main1[RW]
+main1:
+	.long	lib1
+
+	.globl	_main2
+	.csect	_main2[RW]
+_main2:
+	.long	_lib2
Index: ld/testsuite/ld-powerpc/aix52.exp
===================================================================
--- ld/testsuite/ld-powerpc/aix52.exp	2009-03-10 13:52:29.000000000 +0000
+++ ld/testsuite/ld-powerpc/aix52.exp	2009-03-10 13:52:51.000000000 +0000
@@ -108,6 +108,26 @@ set aix52tests {
       {nm -D aix-no-dup-syms-1-dso.dnd} {objdump -R aix-no-dup-syms-1-dso.drd}}
      "aix-no-dup-syms-1.so"}
 
+    {"Export test 1 (archive)" ""
+      "" {aix-export-1a.s}
+      {} "libaix-export-1.a"}
+
+    {"Export test 1 (object)" "-r"
+      "" {aix-export-1b.s}
+      {} "aix-export-1.o"}
+
+    {"Export test 1 (-bexpall)"
+     "-shared -bexpall tmpdir/aix-export-1.o -Ltmpdir -laix-export-1"
+     "" {}
+     {{objdump -dj.data aix-export-1-all.dd}}
+     "aix-export-1-all.so"}
+
+    {"Export test 1 (-bexpfull)"
+     "-shared -bexpfull tmpdir/aix-export-1.o -Ltmpdir -laix-export-1"
+     "" {}
+     {{objdump -dj.data aix-export-1-full.dd}}
+     "aix-export-1-full.so"}
+
     {"Garbage collection test 1"
      "-shared -binitfini:init_function:fini_function -bE:aix-gc-1.ex"
      "" {aix-gc-1.s}

^ permalink raw reply	[flat|nested] 50+ messages in thread

* [19/21] Give imported function descriptors class XMC_DS
  2009-03-10 13:58 [0/21] Add support for AIX 6 Richard Sandiford
                   ` (18 preceding siblings ...)
  2009-03-10 14:49 ` [18/21] Add -bexpall and -bexpfull Richard Sandiford
@ 2009-03-10 14:50 ` Richard Sandiford
  2009-03-13 15:24   ` Nick Clifton
  2009-03-10 14:51 ` [20/21] Fix free() of in-use memory when handling archives Richard Sandiford
  2009-03-10 14:53 ` [21/21] GAS testsuite fix Richard Sandiford
  21 siblings, 1 reply; 50+ messages in thread
From: Richard Sandiford @ 2009-03-10 14:50 UTC (permalink / raw)
  To: binutils

If we import a symbol that turns out to be a function descriptor,
the .loader symbol table still lists it as XMC_UA (unclassified).
We should list it as XMC_DS (descriptor) instead.

OK to install?

Richard


bfd/
	* xcofflink.c (xcoff_build_ldsyms): Give imported descriptors
	class XMC_DS rather than XMC_UA.

Index: bfd/xcofflink.c
===================================================================
--- bfd/xcofflink.c	2009-03-10 13:52:51.000000000 +0000
+++ bfd/xcofflink.c	2009-03-10 13:54:27.000000000 +0000
@@ -3128,7 +3128,12 @@ xcoff_build_ldsyms (struct xcoff_link_ha
     }
 
   if ((h->flags & XCOFF_IMPORT) != 0)
-    h->ldsym->l_ifile = h->ldindx;
+    {
+      /* Give imported descriptors class XMC_DS rather than XMC_UA.  */
+      if ((h->flags & XCOFF_DESCRIPTOR) != 0)
+	h->smclas = XMC_DS;
+      h->ldsym->l_ifile = h->ldindx;
+    }
 
   /* The first 3 symbol table indices are reserved to indicate the
      data, text and bss sections.  */

^ permalink raw reply	[flat|nested] 50+ messages in thread

* [20/21] Fix free() of in-use memory when handling archives
  2009-03-10 13:58 [0/21] Add support for AIX 6 Richard Sandiford
                   ` (19 preceding siblings ...)
  2009-03-10 14:50 ` [19/21] Give imported function descriptors class XMC_DS Richard Sandiford
@ 2009-03-10 14:51 ` Richard Sandiford
  2009-03-13 15:24   ` Nick Clifton
  2009-03-10 14:53 ` [21/21] GAS testsuite fix Richard Sandiford
  21 siblings, 1 reply; 50+ messages in thread
From: Richard Sandiford @ 2009-03-10 14:51 UTC (permalink / raw)
  To: binutils

xcoff_link_check_archive_element tries to be a good citizen and free
symbol tables for unneeded archive members.  The problem is that it
can be called twice for the same member (if the same library is listed
twice on the command line).  The second call can then end up freeing
information that was entered into the hash table by the first call.

OK to install?

Richard


bfd/
	* xcofflink.c (xcoff_link_check_archive_element): Only free the
	symbol table if it was created by the current call.

Index: bfd/xcofflink.c
===================================================================
--- bfd/xcofflink.c	2009-03-10 13:54:27.000000000 +0000
+++ bfd/xcofflink.c	2009-03-10 13:54:49.000000000 +0000
@@ -2149,6 +2149,9 @@ xcoff_link_check_archive_element (bfd *a
 				  struct bfd_link_info *info,
 				  bfd_boolean *pneeded)
 {
+  bfd_boolean keep_syms_p;
+
+  keep_syms_p = (obj_coff_external_syms (abfd) != NULL);
   if (! _bfd_coff_get_external_symbols (abfd))
     return FALSE;
 
@@ -2159,9 +2162,11 @@ xcoff_link_check_archive_element (bfd *a
     {
       if (! xcoff_link_add_symbols (abfd, info))
 	return FALSE;
+      if (info->keep_memory)
+	keep_syms_p = TRUE;
     }
 
-  if (! info->keep_memory || ! *pneeded)
+  if (!keep_syms_p)
     {
       if (! _bfd_coff_free_symbols (abfd))
 	return FALSE;

^ permalink raw reply	[flat|nested] 50+ messages in thread

* [21/21] GAS testsuite fix
  2009-03-10 13:58 [0/21] Add support for AIX 6 Richard Sandiford
                   ` (20 preceding siblings ...)
  2009-03-10 14:51 ` [20/21] Fix free() of in-use memory when handling archives Richard Sandiford
@ 2009-03-10 14:53 ` Richard Sandiford
  2009-03-13 15:25   ` Nick Clifton
  21 siblings, 1 reply; 50+ messages in thread
From: Richard Sandiford @ 2009-03-10 14:53 UTC (permalink / raw)
  To: binutils

Finally, a simple testsuite fix.  gas/ppc/textalign-xcoff-001.d and
gas/ppc/textalign-xcoff-002.d expect the data section to have a
particular VMA, but the VMA they're looking for doesn't honour the
section alignment.  This seems wrong, and it got fixed at some time
since the test was added.

The patch updates the testsuite accordingly.  OK to install?

Richard


gas/testsuite/
	* gas/ppc/textalign-xcoff-001.d: Expect the section VMAs to be
	properly aligned.
	* gas/ppc/textalign-xcoff-002.d: Likewise.

Index: gas/testsuite/gas/ppc/textalign-xcoff-001.d
===================================================================
--- gas/testsuite/gas/ppc/textalign-xcoff-001.d	2009-03-10 08:58:40.000000000 +0000
+++ gas/testsuite/gas/ppc/textalign-xcoff-001.d	2009-03-10 13:55:09.000000000 +0000
@@ -8,7 +8,7 @@ Sections:
 Idx Name          Size      VMA               LMA               File off  Algn
   0 \.text         00000004  0+0  0+0  000000a8  2\*\*2
                   CONTENTS, ALLOC, LOAD, CODE
-  1 \.data         00000008  0+04  0+04  000000ac  2\*\*3
+  1 \.data         00000008  0+08  0+08  000000ac  2\*\*3
                   CONTENTS, ALLOC, LOAD, RELOC, DATA
-  2 \.bss          00000000  0+0c  0+0c  00000000  2\*\*3
+  2 \.bss          00000000  0+10  0+10  00000000  2\*\*3
                   ALLOC
Index: gas/testsuite/gas/ppc/textalign-xcoff-002.d
===================================================================
--- gas/testsuite/gas/ppc/textalign-xcoff-002.d	2009-03-10 08:58:40.000000000 +0000
+++ gas/testsuite/gas/ppc/textalign-xcoff-002.d	2009-03-10 13:55:09.000000000 +0000
@@ -8,7 +8,7 @@ Sections:
 Idx Name          Size      VMA               LMA               File off  Algn
   0 \.text         00000004  0000000000000000  0000000000000000  000000f0  2\*\*2
                   CONTENTS, ALLOC, LOAD, CODE
-  1 \.data         00000008  0000000000000004  0000000000000004  000000f4  2\*\*3
+  1 \.data         00000008  0000000000000008  0000000000000008  000000f4  2\*\*3
                   CONTENTS, ALLOC, LOAD, RELOC, DATA
-  2 \.bss          00000000  000000000000000c  000000000000000c  00000000  2\*\*3
+  2 \.bss          00000000  0000000000000010  0000000000000010  00000000  2\*\*3
                   ALLOC

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [0/21] Add support for AIX 6
  2009-03-10 14:13 ` [0/21] Add support for AIX 6 Ian Lance Taylor
@ 2009-03-10 15:22   ` Richard Sandiford
  2009-03-10 15:45   ` Michael Haubenwallner
  1 sibling, 0 replies; 50+ messages in thread
From: Richard Sandiford @ 2009-03-10 15:22 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: binutils

Ian Lance Taylor <iant@google.com> writes:
> Richard Sandiford <richards@transitive.com> writes:
>> Now the AIX linker appears to apply something like --whole-archive
>> semantics to _all_ archives.
>
> That is correct.  The AIX linker uses the equivalent of --whole-archive,
> and then uses garbage collection to discarded unreferenced csects.
>
> My attitude when I did the original GNU ld port to AIX was that GNU ld
> should, as much as possible, present the same interface on every host.
> I figured that the main reason that people would use GNU ld for AIX
> would be because they were cross-compiling to AIX, and that the most
> likely scenario there was a program which ran on many different hosts.
> I felt that it would be more convenient in that scenario if they did not
> have to invoke the linker differently on different hosts.  This shows up
> most drastically on AIX, but we also see it in, e.g., the default for
> --export-dynamic, which is different in the native linkers on Solaris
> and System V, but which is always the same for GNU ld.
>
> I don't feel all that strongly about this then or now, but that was my
> reasoning and it still seems valid to me.

Me too FWIW.  The only time this caused us trouble in practice was in
a makefile that (when expanded) used the equivalent of "gcc -lpthread".
It was easy to convince folks that "gcc -pthread" was a better idea
anyway, since it sets the appropriate preprocessor macros and picks
the right gcc multilibs.

Richard

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [0/21] Add support for AIX 6
  2009-03-10 14:13 ` [0/21] Add support for AIX 6 Ian Lance Taylor
  2009-03-10 15:22   ` Richard Sandiford
@ 2009-03-10 15:45   ` Michael Haubenwallner
  2009-03-10 16:30     ` Ian Lance Taylor
  1 sibling, 1 reply; 50+ messages in thread
From: Michael Haubenwallner @ 2009-03-10 15:45 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: binutils, richards

On Tue, 2009-03-10 at 07:12 -0700, Ian Lance Taylor wrote:

> My attitude when I did the original GNU ld port to AIX was that GNU ld
> should, as much as possible, present the same interface on every host.

Did you also think on providing some 'soname' support for AIX?

As far I understand the manpage (from AIX 5.3), using the native linker
it could work this way, but maybe via libtool only (assume libtool's
soname is "libNAME.so.X"):

*) create a shared object with a defined name (shr.o),
   using -G native-linker flag
*) create an import file containing "#! libNAME.so.X(shr.o)"
*) pack the import file into "libNAME.so.X.Y.Z" *first*
*) pack the shared object into "libNAME.so.X.Y.Z" *second*
*) create the symlinks known from linux/elf:
     libNAME.so -> libNAME.so.X
     libNAME.so.X -> libNAME.so.X.Y.Z

When runtime linking (-brtl) is active, at link-time the import file is
found, recording "libNAME.so.X(shr.o)" into the resulting binary for
run-time.

Sorry for maybe being off-topic.

/haubi/

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [0/21] Add support for AIX 6
  2009-03-10 15:45   ` Michael Haubenwallner
@ 2009-03-10 16:30     ` Ian Lance Taylor
  0 siblings, 0 replies; 50+ messages in thread
From: Ian Lance Taylor @ 2009-03-10 16:30 UTC (permalink / raw)
  To: Michael Haubenwallner; +Cc: binutils, richards

Michael Haubenwallner <michael.haubenwallner@salomon.at> writes:

> On Tue, 2009-03-10 at 07:12 -0700, Ian Lance Taylor wrote:
>
>> My attitude when I did the original GNU ld port to AIX was that GNU ld
>> should, as much as possible, present the same interface on every host.
>
> Did you also think on providing some 'soname' support for AIX?

I did not, but it's an interesting idea.

Ian

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [1/21] Fix handling of archive tests
  2009-03-10 14:00 ` [1/21] Fix handling of archive tests Richard Sandiford
@ 2009-03-12 16:15   ` Nick Clifton
  0 siblings, 0 replies; 50+ messages in thread
From: Nick Clifton @ 2009-03-12 16:15 UTC (permalink / raw)
  To: binutils, richards

Hi Richard,

> ld/testsuite/
> 	* lib/ld-lib.exp (ar_simple_create): Add an "aropts" parameter.
> 	(run_ld_link_tests): Treat the second list element as "ar" options
> 	when creating an archive.  Don't run the linker in this case.
> 	(run_cc_link_tests): Likewise.

Approved - please apply.

Cheers
   Nick


^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [2/21] Add support for AIX 6
  2009-03-10 14:01 ` [2/21] Add support for AIX 6 Richard Sandiford
@ 2009-03-12 16:17   ` Nick Clifton
  0 siblings, 0 replies; 50+ messages in thread
From: Nick Clifton @ 2009-03-12 16:17 UTC (permalink / raw)
  To: binutils, richards

Hi Richard,

> bfd/
> 	* config.bfd: Treat AIX 6+ in the same way as AIX 5.
> 	* configure.in: Likewise.
> 	* configure: Regenerate.
> 
> binutils/
> 	* configure.tgt: Extend AIX 5 behavior to AIX 6 and above.
> 	* configure.in: Likewise.
> 	* configure: Regenerate.
> 
> gas/
> 	* configure.tgt: Extend AIX 5 behavior to AIX 6 and above.
> 	* configure.in: Likewise.
> 	* configure: Regenerate.
> 
> ld/
> 	* configure.tgt: Extend AIX 5 behavior to AIX 6 and above.

Approved - please apply.

Cheers
   Nick


^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [3/21] Keep .text, .data and .bss on AIX
  2009-03-10 14:04 ` [3/21] Keep .text, .data and .bss on AIX Richard Sandiford
@ 2009-03-12 16:36   ` Nick Clifton
  2009-03-13  9:43     ` Richard Sandiford
  0 siblings, 1 reply; 50+ messages in thread
From: Nick Clifton @ 2009-03-12 16:36 UTC (permalink / raw)
  To: binutils, richards

Hi Richard,

> ld/
> 	* emultempl/aix.em (gld${EMULATION_NAME}_before_allocation): Mark
> 	.text, .data and .bss output sections as SEC_KEEP.
> 
> ld/testsuite/
> 	* ld-powerpc/aix-core-sec-1.s, ld-powerpc/aix-core-sec-1.ex,
> 	ld-powerpc/aix-core-sec-1.hd, ld-powerpc/aix-core-sec-2.s,
> 	ld-powerpc/aix-core-sec-2.ex, ld-powerpc/aix-core-sec-2.hd,
> 	ld-powerpc/aix-core-sec-3.s, ld-powerpc/aix-core-sec-3.ex,
> 	ld-powerpc/aix-core-sec-3.hd: New tests.
> 	* ld-powerpc/aix52.exp: New harness.

Approved - please apply, but ...

> +  /* We must always have .text, .data and .bss output sections, so that
> +     the header can refer to them.  The kernel refuses to load shared
> +     objects that have missing sections.  */
> +  for (i = 0; i < ARRAY_SIZE (must_keep_sections); i++)
> +    {
> +      asection *sec;
> +
> +      sec = bfd_get_section_by_name (link_info.output_bfd,
> +				     must_keep_sections[i]);
> +      if (sec)
> +	sec->flags |= SEC_KEEP;
> +    }

Should a warning be issued if one of these must-keep sections cannot be 
found ?  Presumably this would only matter if they are missing in the 
output bfd (and the bfd is an executabe or shared library) so maybe this 
is not the right place for such a test.

Cheers
   Nick

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [4/21] Fix o_cputype for 64-bit XCOFF objects
  2009-03-10 14:05 ` [4/21] Fix o_cputype for 64-bit XCOFF objects Richard Sandiford
@ 2009-03-12 16:38   ` Nick Clifton
  0 siblings, 0 replies; 50+ messages in thread
From: Nick Clifton @ 2009-03-12 16:38 UTC (permalink / raw)
  To: binutils, richards

Hi Richard,

> bfd/
> 	* coff64-rs6000.c (xcoff64_write_object_contents): Set the cputype
> 	to 2 for bfd_mach_ppc_620.

Approved - please apply.

Cheers
   Nick


^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [5/21] Set config.dynamic_link for AIX
  2009-03-10 14:07 ` [5/21] Set config.dynamic_link for AIX Richard Sandiford
@ 2009-03-12 16:39   ` Nick Clifton
  0 siblings, 0 replies; 50+ messages in thread
From: Nick Clifton @ 2009-03-12 16:39 UTC (permalink / raw)
  To: binutils, richards

Hi Richard,

> ld/
> 	* emultempl/aix.em (gld${EMULATION_NAME}_before_parse): Set
> 	config.dynamic_link to TRUE.

Approved - please apply.

Cheers
   Nick


^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [3/21] Keep .text, .data and .bss on AIX
  2009-03-12 16:36   ` Nick Clifton
@ 2009-03-13  9:43     ` Richard Sandiford
  2009-03-13 11:42       ` Nick Clifton
  0 siblings, 1 reply; 50+ messages in thread
From: Richard Sandiford @ 2009-03-13  9:43 UTC (permalink / raw)
  To: Nick Clifton; +Cc: binutils

Hi Nick,

Thanks for the reviews.

Nick Clifton <nickc@redhat.com> writes:
> Hi Richard,
>> +  /* We must always have .text, .data and .bss output sections, so that
>> +     the header can refer to them.  The kernel refuses to load shared
>> +     objects that have missing sections.  */
>> +  for (i = 0; i < ARRAY_SIZE (must_keep_sections); i++)
>> +    {
>> +      asection *sec;
>> +
>> +      sec = bfd_get_section_by_name (link_info.output_bfd,
>> +				     must_keep_sections[i]);
>> +      if (sec)
>> +	sec->flags |= SEC_KEEP;
>> +    }
>
> Should a warning be issued if one of these must-keep sections cannot be 
> found ?

Good point.

> Presumably this would only matter if they are missing in the 
> output bfd (and the bfd is an executabe or shared library) so maybe this 
> is not the right place for such a test.

Yeah, the code should probably be restricted to non-relocatable links.
Keeping sections unconditionally should be conservatively correct,
but it's probably too conservative.

I checked that, unlike gas, the native assembler only emits
referenced sections.  For example, the output for:

	.extern	f2
	.globl	foo
	.csect	foo[RW]
foo:
	.long	f2

only has a .data section.  If you then do a relocatable link with the
native linker, the output also only has a .data section.  If, on the
other hand, you do a shared library link, you get empty .text and .bss
sections too.  So I agree a !link_info.relocatable guard is appropriate.

I think the check is in the right place though.  The code is checking
whether the sections are in the output bfd, and is marking the output
section as SEC_KEEP.

Does this revised patch look OK?  I checked that the error triggers for
non-relocatable links with a .text-less linker script and with .text-less
input bfds.  (I created the latter using objcopy --remove-section,
to get around the gas behaviour mentioned above.)

Richard


ld/
	* emultempl/aix.em (gld${EMULATION_NAME}_before_allocation): Mark
	.text, .data and .bss output sections as SEC_KEEP.

ld/testsuite/
	* ld-powerpc/aix-core-sec-1.s, ld-powerpc/aix-core-sec-1.ex,
	ld-powerpc/aix-core-sec-1.hd, ld-powerpc/aix-core-sec-2.s,
	ld-powerpc/aix-core-sec-2.ex, ld-powerpc/aix-core-sec-2.hd,
	ld-powerpc/aix-core-sec-3.s, ld-powerpc/aix-core-sec-3.ex,
	ld-powerpc/aix-core-sec-3.hd: New tests.
	* ld-powerpc/aix52.exp: New harness.

Index: ld/emultempl/aix.em
===================================================================
--- ld/emultempl/aix.em	2009-03-12 17:06:11.000000000 +0000
+++ ld/emultempl/aix.em	2009-03-13 09:19:16.000000000 +0000
@@ -616,7 +616,12 @@ gld${EMULATION_NAME}_before_allocation (
   struct export_symbol_list *el;
   char *libpath;
   asection *special_sections[XCOFF_NUMBER_OF_SPECIAL_SECTIONS];
-  int i;
+  static const char *const must_keep_sections[] = {
+    ".text",
+    ".data",
+    ".bss"
+  };
+  unsigned int i;
 
   /* Handle the import and export files, if any.  */
   for (fl = import_files; fl != NULL; fl = fl->next)
@@ -824,6 +829,22 @@ gld${EMULATION_NAME}_before_allocation (
 	}
     }
 
+  /* Executables and shared objects must always have .text, .data
+     and .bss output sections, so that the header can refer to them.
+     The kernel refuses to load objects that have missing sections.  */
+  if (!link_info.relocatable)
+    for (i = 0; i < ARRAY_SIZE (must_keep_sections); i++)
+      {
+	asection *sec;
+
+	sec = bfd_get_section_by_name (link_info.output_bfd,
+				       must_keep_sections[i]);
+	if (sec == NULL)
+	  einfo ("%P: can't find output section %s\n", must_keep_sections[i]);
+	else
+	  sec->flags |= SEC_KEEP;
+      }
+
   before_allocation_default ();
 }
 
Index: ld/testsuite/ld-powerpc/aix-core-sec-1.s
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-core-sec-1.s	2009-03-12 17:06:18.000000000 +0000
@@ -0,0 +1,5 @@
+	.globl	foo
+	.csect	foo[RO]
+foo:
+	.long	0x12345678
+	.long	0xdeadbeef
Index: ld/testsuite/ld-powerpc/aix-core-sec-1.ex
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-core-sec-1.ex	2009-03-12 17:06:18.000000000 +0000
@@ -0,0 +1,1 @@
+foo
Index: ld/testsuite/ld-powerpc/aix-core-sec-1.hd
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-core-sec-1.hd	2009-03-12 17:06:18.000000000 +0000
@@ -0,0 +1,11 @@
+#...
+Sections:
+.*
+ * 0 * \.text * 0+8 .*
+ * CONTENTS, ALLOC, LOAD, CODE
+ * 1 * \.data * 0+0 .*
+ * ALLOC, LOAD, DATA
+ * 2 * \.bss * 0+0 .*
+ * ALLOC
+ * 3 * \.loader .*
+ * CONTENTS, ALLOC, LOAD
Index: ld/testsuite/ld-powerpc/aix-core-sec-2.s
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-core-sec-2.s	2009-03-12 17:06:18.000000000 +0000
@@ -0,0 +1,5 @@
+	.globl	foo
+	.csect	foo[RW]
+foo:
+	.long	0x12345678
+	.long	0xdeadbeef
Index: ld/testsuite/ld-powerpc/aix-core-sec-2.ex
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-core-sec-2.ex	2009-03-12 17:06:18.000000000 +0000
@@ -0,0 +1,1 @@
+foo
Index: ld/testsuite/ld-powerpc/aix-core-sec-2.hd
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-core-sec-2.hd	2009-03-12 17:06:18.000000000 +0000
@@ -0,0 +1,11 @@
+#...
+Sections:
+.*
+ * 0 * \.text * 0+0 .*
+ * ALLOC, LOAD, CODE
+ * 1 * \.data * 0+8 .*
+ * CONTENTS, ALLOC, LOAD, DATA
+ * 2 * \.bss * 0+0 .*
+ * ALLOC
+ * 3 * \.loader .*
+ * CONTENTS, ALLOC, LOAD
Index: ld/testsuite/ld-powerpc/aix-core-sec-3.s
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-core-sec-3.s	2009-03-12 17:06:18.000000000 +0000
@@ -0,0 +1,1 @@
+	.comm	foo,8
Index: ld/testsuite/ld-powerpc/aix-core-sec-3.ex
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-core-sec-3.ex	2009-03-12 17:06:18.000000000 +0000
@@ -0,0 +1,1 @@
+foo
Index: ld/testsuite/ld-powerpc/aix-core-sec-3.hd
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-core-sec-3.hd	2009-03-12 17:06:18.000000000 +0000
@@ -0,0 +1,11 @@
+#...
+Sections:
+.*
+ * 0 * \.text * 0+0 .*
+ * ALLOC, LOAD, CODE
+ * 1 * \.data * 0+0 .*
+ * ALLOC, LOAD, DATA
+ * 2 * \.bss * 0+8 .*
+ * ALLOC
+ * 3 * \.loader .*
+ * CONTENTS, ALLOC, LOAD
Index: ld/testsuite/ld-powerpc/aix52.exp
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix52.exp	2009-03-12 17:06:18.000000000 +0000
@@ -0,0 +1,89 @@
+# Expect script for AIX 5.2+ tests
+#   Copyright 2009 Free Software Foundation
+#
+# This file is part of the GNU Binutils.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+#
+
+if { ![istarget "powerpc*-*-aix\[5-9\]*"]
+     || [istarget "powerpc*-*-aix5.\[01\]*"] } {
+    return
+}
+
+# Run a run_link_tests-style test for AIX.  SIZE selects the target size
+# (32 or 64).  The other arguments are elements of a run_link_tests test.
+#
+# Make the following changes before running the test:
+#
+#    - Mention SIZE in the test name.
+#    - Add "-aSIZE --defsym size=SIZE" to the assembler options.
+#    - Add the source directory to any "-bI:" and "-bE:" linker options.
+#    - Add "-bSIZE" to the linker options.
+#    - Add "-XSIZE" to the archiver options.
+#    - Replace "SIZE" with SIZE in TOOLS.
+#    - When testing 64-bit targets:
+#      - Turn tmpdir/aix-* into tmpdir/aix64-*.
+#      - Turn tmpdir/libaix-* into tmpdir/libaix64-*.
+#      - Turn -laix* into -laix64*, to compensate for the above.
+proc run_aix_test { size name ldopts asopts sources tools output } {
+    global srcdir subdir
+
+    if { $size == 64 } {
+	regsub -all {tmpdir/aix-} $ldopts {tmpdir/aix64-} ldopts
+	regsub {^aix} $output {aix64} output
+
+	regsub -all -- {-laix-} $ldopts {-laix64-} ldopts
+	regsub {^libaix} $output {libaix64} output
+    }
+    if { [regexp {.a$} $output] } {
+	append ldopts " -X$size"
+    } else {
+	regsub -all {(-b[IE]):} $ldopts "\\1:$srcdir/$subdir/" ldopts
+	append ldopts " -b$size"
+    }
+    regsub -all {SIZE} $tools $size tools
+    run_ld_link_tests [list [list "$name ($size-bit)" \
+				 $ldopts \
+				 "$asopts -a$size --defsym size=$size" \
+				 $sources \
+				 $tools \
+				 $output]]
+}
+
+set aix52tests {
+    {"Core sections test 1" "-shared -bE:aix-core-sec-1.ex"
+     "" {aix-core-sec-1.s}
+     {{objdump -h aix-core-sec-1.hd}}
+     "aix-core-sec-1.so"}
+
+    {"Core sections test 2" "-shared -bE:aix-core-sec-2.ex"
+     "" {aix-core-sec-2.s}
+     {{objdump -h aix-core-sec-2.hd}}
+     "aix-core-sec-2.so"}
+
+    {"Core sections test 3" "-shared -bE:aix-core-sec-3.ex"
+     "" {aix-core-sec-3.s}
+     {{objdump -h aix-core-sec-3.hd}}
+     "aix-core-sec-3.so"}
+}
+
+foreach test $aix52tests {
+    foreach { name ldopts asopts sources tools output } $test {
+	run_aix_test 32 $name $ldopts $asopts $sources $tools $output
+	run_aix_test 64 $name $ldopts $asopts $sources $tools $output
+    }
+}

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [3/21] Keep .text, .data and .bss on AIX
  2009-03-13  9:43     ` Richard Sandiford
@ 2009-03-13 11:42       ` Nick Clifton
  2009-03-14  9:42         ` Richard Sandiford
  0 siblings, 1 reply; 50+ messages in thread
From: Nick Clifton @ 2009-03-13 11:42 UTC (permalink / raw)
  To: Nick Clifton, binutils, richards

Hi Richard,

> ld/
> 	* emultempl/aix.em (gld${EMULATION_NAME}_before_allocation): Mark
> 	.text, .data and .bss output sections as SEC_KEEP.
> 
> ld/testsuite/
> 	* ld-powerpc/aix-core-sec-1.s, ld-powerpc/aix-core-sec-1.ex,
> 	ld-powerpc/aix-core-sec-1.hd, ld-powerpc/aix-core-sec-2.s,
> 	ld-powerpc/aix-core-sec-2.ex, ld-powerpc/aix-core-sec-2.hd,
> 	ld-powerpc/aix-core-sec-3.s, ld-powerpc/aix-core-sec-3.ex,
> 	ld-powerpc/aix-core-sec-3.hd: New tests.
> 	* ld-powerpc/aix52.exp: New harness.

Approved - please apply - although ... :-)

> +	  einfo ("%P: can't find output section %s\n", must_keep_sections[i]);

I would suggest changing the wording to "can't find required output 
section" as otherwise the user might think: "well so what if I don't 
have a .bss section, who cares ?".

Cheers
   Nick

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [6/21] XCOFF R_POS and R_NEG relocations against absolute symbols
  2009-03-10 14:08 ` [6/21] XCOFF R_POS and R_NEG relocations against absolute symbols Richard Sandiford
@ 2009-03-13 14:33   ` Nick Clifton
  0 siblings, 0 replies; 50+ messages in thread
From: Nick Clifton @ 2009-03-13 14:33 UTC (permalink / raw)
  To: binutils, richards

Hi Richard,

> bfd/
> 	* xcofflink.c (xcoff_mark, xcoff_link_input_bfd): Don't copy
> 	R_POS and R_NEG relocations against absolute symbols to the
> 	.loader section.
> 
> ld/testsuite/
> 	* ld-powerpc/aix-abs-reloc-1.ex, ld-powerpc/aix-abs-reloc-1.im,
> 	ld-powerpc/aix-abs-reloc-1.od, ld-powerpc/aix-abs-reloc-1.s: New test.
> 	* ld-powerpc/aix52.exp: Run it.

Approved - please apply.

Cheers
   Nick

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [7/21] Handle relative branches to absolute addresses
  2009-03-10 14:13 ` [7/21] Handle relative branches to absolute addresses Richard Sandiford
@ 2009-03-13 14:37   ` Nick Clifton
  0 siblings, 0 replies; 50+ messages in thread
From: Nick Clifton @ 2009-03-13 14:37 UTC (permalink / raw)
  To: binutils, richards

Hi Richard,

> bfd/
> 	* coff-rs6000.c (xcoff_reloc_type_br): Make the branch absolute
> 	if the target is absolute.  Fix comment typo.
> 	(xcoff_ppc_relocate_section): Remove FIXME.
> 	* coff64-rs6000.c (xcoff64_reloc_type_br): Make the branch absolute
> 	if the target is absolute.
> 
> ld/testsuite/
> 	* ld-powerpc/aix-abs-branch-1.im, ld-powerpc/aix-abs-branch-1.ex,
> 	ld-powerpc/aix-abs-branch-1.s,
> 	ld-powerpc/aix-abs-branch-1.dd: New test.
> 	* ld-powerpc/aix52.exp: Run it.

Approved - please apply.

Cheers
   Nick


^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [8/21] bfd_install_relocation strikes again
  2009-03-10 14:15 ` [8/21] bfd_install_relocation strikes again Richard Sandiford
@ 2009-03-13 14:48   ` Nick Clifton
  0 siblings, 0 replies; 50+ messages in thread
From: Nick Clifton @ 2009-03-13 14:48 UTC (permalink / raw)
  To: binutils, richards

Hi Richard,

> gas/
> 	* config/tc-ppc.c (md_apply_fix): On COFF targets, always reread
> 	"value" from fx_offset.  Manually resubtract md_pcrel_from_section
> 	where necessary.
> 
> gas/testsuite/
> 	* gas/ppc/xcoff-branch-1.s, gas/ppc/xcoff-branch-1-32.d,
> 	gas/ppc/xcoff-branch-1-64.d: New tests.
> 	* gas/ppc/aix.exp: Run them.

Approved - please apply.

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [9/21] Implicitly import undefined symbols
  2009-03-10 14:22 ` [9/21] Implicitly import undefined symbols Richard Sandiford
@ 2009-03-13 14:55   ` Nick Clifton
  0 siblings, 0 replies; 50+ messages in thread
From: Nick Clifton @ 2009-03-13 14:55 UTC (permalink / raw)
  To: binutils, richards

Hi Richard,

> include/coff/
> 	* xcoff.h (XCOFF_CALLED, XCOFF_IMPORT): Update comments.
> 	(XCOFF_WAS_UNDEFINED): New flag.
> 	(xcoff_link_hash_table): Add an "rtld" field.
> 
> bfd/
> 	* coff-rs6000.c (xcoff_ppc_relocate_section): Report relocations
> 	against undefined symbols if the symbol's XCOFF_WAS_UNDEFINED
> 	flag is set.  Assert that all undefined symbols are either
> 	imported or defined by a dynamic object.
> 	* coff64-rs6000.c (xcoff64_ppc_relocate_section): Likewise.
> 	* xcofflink.c (xcoff_link_add_symbols): Extend function-symbol
> 	handling to all relocations.  Only set XCOFF_CALLED for function
> 	symbols.
> 	(xcoff_find_function): New function, split out from...
> 	(bfd_xcoff_export_symbol) ...here.
> 	(xcoff_set_import_path): New function, split out from...
> 	(bfd_xcoff_import_symbol): ...here.  Remove assertion for old
> 	meaning of XCOFF_CALLED.
> 	(xcoff_mark_symbol): If we mark an undefined and unimported
> 	symbol, find some way of defining it.  If the symbol is a function
> 	descriptor, fill in its definition automatically.  If the symbol
> 	is a function, mark its descriptor and allocate room for global
> 	linkage code.  Otherwise mark the symbol as implicitly imported.
> 	Move the code for creating function descriptors from...
> 	(xcoff_build_ldsyms): ...here.  Use XCOFF_WAS_UNDEFINED to 
> 	check for symbols that were implicitly defined.
> 	(xcoff_mark): Don't count any dynamic relocations against
> 	function symbols.
> 	(bfd_xcoff_size_dynamic_sections): Save the rtld parameter
> 	in the xcoff link info.
> 	(xcoff_link_input_bfd): Remove handling of undefined and
> 	unexported symbols.
> 
> ld/
> 	* emultempl/aix.em (gld${EMULATION_NAME}_handle_option): Make
> 	-berok and -bernotok control link_info.unresolved_syms_in_objects
> 	and link_info.unresolved_syms_in_shared_libs instead of
> 	force_make_executable.
> 
> ld/testsuite/
> 	* ld-powerpc/aix-glink-1.ex, ld-powerpc/aix-glink-1.s,
> 	ld-powerpc/aix-glink-1-32.dd, ld-powerpc/aix-glink-1-64.dd,
> 	ld-powerpc/aix-glink-1-32.d, ld-powerpc/aix-glink-1-64.d: New tests.
> 	* ld-powerpc/aix52.exp: Run them.

Approved - please apply.

Cheers
   Nick

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [10/21] Fix the csect handling of XTY_ER symbols
  2009-03-10 14:25 ` [10/21] Fix the csect handling of XTY_ER symbols Richard Sandiford
@ 2009-03-13 14:57   ` Nick Clifton
  0 siblings, 0 replies; 50+ messages in thread
From: Nick Clifton @ 2009-03-13 14:57 UTC (permalink / raw)
  To: binutils, richards

Hi Richard,

> bfd/
> 	* libcoff-in.h (xcoff_section_tdata): Update commentary.
> 	* libcoff.h: Regenerate.
> 	* xcofflink.c (xcoff_link_add_symbols): Set the csect of XTY_ER
> 	symbols to bfd_und_section_ptr or bfd_abs_section_ptr, rather than
> 	the previous symbol's csect.  Treat last_symndx as an inclusive value
> 	and simplify its handling.
> 	(xcoff_mark): Treat last_symndx as an inclusive value.  Only mark
> 	symbols with the right csect.  Don't mark rsec when processing
> 	relocations against undefined or absolute sections.  
> 	(bfd_xcoff_size_dynamic_sections): Don't check the SEC_MARK flag
> 	of bfd_und_section_ptr.
> 	(xcoff_link_input_bfd): Likewise.

Approved - please apply.

Cheers
   Nick

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [11/21] Cope with TOCs bigger than 32k, and other TC0 fixes
  2009-03-10 14:29 ` [11/21] Cope with TOCs bigger than 32k, and other TC0 fixes Richard Sandiford
@ 2009-03-13 14:59   ` Nick Clifton
  0 siblings, 0 replies; 50+ messages in thread
From: Nick Clifton @ 2009-03-13 14:59 UTC (permalink / raw)
  To: binutils, richards

Hi Richard,

> bfd/
> 	* xcofflink.c: (xcoff_mark_symbol): Mark the TOC section when
> 	creating a descriptor.
> 	(xcoff_sweep): Don't mark toc_section unless it's needed.
> 	(bfd_xcoff_size_dynamic_sections): Skip the toc_section
> 	when marking every bfd.
> 	(xcoff_link_input_bfd): Skip all TOC anchors.
> 	(xcoff_toc_section_p, xcoff_find_tc0): New functions.
> 	(_bfd_xcoff_bfd_final_link): Don't set the output bfd's TOC anchor
> 	to -1; call xcoff_find_tc0 instead.
> 
> ld/testsuite/
> 	* ld-powerpc/aix-toc-1.ex, ld-powerpc/aix-toc-1a.s,
> 	ld-powerpc/aix-toc-1b.s, ld-powerpc/aix-toc-1-32.dd,
> 	ld-powerpc/aix-toc-1-64.dd: New tests.
> 	* ld-powerpc/aix52.exp: Run them.

Approved - please apply.

Cheers
   Nick

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [12/21] Trim XCOFF symbols earlier in the link process
  2009-03-10 14:34 ` [12/21] Trim XCOFF symbols earlier in the link process Richard Sandiford
@ 2009-03-13 15:01   ` Nick Clifton
  0 siblings, 0 replies; 50+ messages in thread
From: Nick Clifton @ 2009-03-13 15:01 UTC (permalink / raw)
  To: binutils, richards

Hi Richard,

> bfd/
> 	* libcoff-in.h (xcoff_tdata): Change debug_indices to a signed long.
> 	* libcoff.h: Regenerate.
> 	* xcofflink.c (xcoff_keep_symbol_p): New function, using the
> 	"skip" logic from xcoff_link_input_bfd.
> 	(bfd_xcoff_size_dynamic_sections): Explicitly skip dynamic
> 	objects in a dynamic link, rather than checking whether csectpp
> 	is null.  Always allocate debug_index for other objects,
> 	and always go through the loop.  Update the type of debug_index
> 	after the change above.  Read the auxillary csect information
> 	and use xcoff_keep_symbol_p to decide whether a symbol should
> 	be kept.  Set its debug_index to -2 if not.
> 	(xcoff_link_input_bfd): Update the type of debug_index after
> 	the change above and always expect it to be nonnull.  Use it to
> 	test whether a symbol should be stripped, rather than making the
> 	decision here.  Postpone all symbol creation to the second pass.

Approved - please apply.

Cheers
   Nick

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [13/21] Fix counting of line-number entries
  2009-03-10 14:36 ` [13/21] Fix counting of line-number entries Richard Sandiford
@ 2009-03-13 15:04   ` Nick Clifton
  0 siblings, 0 replies; 50+ messages in thread
From: Nick Clifton @ 2009-03-13 15:04 UTC (permalink / raw)
  To: binutils, richards

Hi Richard,

> bfd/
> 	* libcoff-in.h (xcoff_tdata): Add a lineno_counts field.
> 	* libcoff.h: Regenerate.
> 	* xcofflink.c (xcoff_link_add_symbols): Record per-symbol
> 	line-number counts in the bfd's lineno_counts field.
> 	Don't keep per-csect line-number counts.
> 	(xcoff_sweep): Don't update per-csect line-number counts.
> 	(bfd_xcoff_size_dynamic_sections): Count the number of line-number
> 	entries in each output section.
> 	(xcoff_link_input_bfd): Get the number of line numbers from
> 	the bfd's lineno_counts field, rather than recalculating it
> 	from scratch.  Fix the range check when updating C_BINCL and
> 	C_EINCL symbols.
> 	(_bfd_xcoff_bfd_final_link): Don't count the output line numbers
> 	here.  Don't expect csects to have line-number counts.
> 
> ld/testsuite/
> 	* ld-powerpc/aix-lineno-1.s, ld-powerpc/aix-lineno-1.txt,
> 	ld-powerpc/aix-lineno-1a.dd, ld-powerpc/aix-lineno-1a.nd,
> 	ld-powerpc/aix-lineno-1b.dd, ld-powerpc/aix-lineno-1b.nd: New tests.
> 	* ld-powerpc/aix52.exp: Run them.  Copy aix-lineno-1.txt to tmpdir.

Approved - please apply.

Cheers
   Nick

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [14/21] Treat absolute imports as XTY_ER/XMC_XO
  2009-03-10 14:38 ` [14/21] Treat absolute imports as XTY_ER/XMC_XO Richard Sandiford
@ 2009-03-13 15:11   ` Nick Clifton
  0 siblings, 0 replies; 50+ messages in thread
From: Nick Clifton @ 2009-03-13 15:11 UTC (permalink / raw)
  To: binutils, richards

Hi Richard,

> bfd/
> 	* xcofflink.c (bfd_xcoff_import_symbol): Treat imported absolute
> 	symbols as XMC_XO.
> 
> ld/testsuite/
> 	* ld-powerpc/aix-abs-branch-1.nd,
> 	ld-powerpc/aix-abs-reloc-1.nd: New tests.
> 	* ld-powerpc/aix52.exp: Run them.

Approved - please apply.

Cheers
   Nick


^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [15/21] Avoid writing duplicate XCOFF symbols
  2009-03-10 14:40 ` [15/21] Avoid writing duplicate XCOFF symbols Richard Sandiford
@ 2009-03-13 15:12   ` Nick Clifton
  0 siblings, 0 replies; 50+ messages in thread
From: Nick Clifton @ 2009-03-13 15:12 UTC (permalink / raw)
  To: binutils, richards

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


Approved - please apply.

Cheers
   Nick

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [16/21] Add AIX weak support
  2009-03-10 14:45 ` [16/21] Add AIX weak support Richard Sandiford
@ 2009-03-13 15:17   ` Nick Clifton
  0 siblings, 0 replies; 50+ messages in thread
From: Nick Clifton @ 2009-03-13 15:17 UTC (permalink / raw)
  To: binutils, richards

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

Approved - please apply.

Cheers
   Nick

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [18/21] Add -bexpall and -bexpfull
  2009-03-10 14:49 ` [18/21] Add -bexpall and -bexpfull Richard Sandiford
@ 2009-03-13 15:21   ` Nick Clifton
  0 siblings, 0 replies; 50+ messages in thread
From: Nick Clifton @ 2009-03-13 15:21 UTC (permalink / raw)
  To: binutils, richards

Hi Richard,

> include/coff/
> 	* xcoff.h (XCOFF_EXPALL, XCOFF_EXPFULL): New flags.
> 	(xcoff_loader_info): Add auto_export_flags.
> 
> bfd/
> 	* bfd-in.h (bfd_xcoff_size_dynamic_sections): Replace the
> 	bfd_boolean export_defineds parameter with an unsigned int
> 	auto_export_flags parameter.
> 	* bfd-in2.h: Regenerate.
> 	* xcofflink.c (xcoff_archive_contains_shared_object_p): New function,
> 	split out from xcoff_build_ldsyms.
> 	(xcoff_covered_by_expall_p): New function.
> 	(xcoff_auto_export_p): New function, split out from xcoff_build_ldsyms
> 	but with extra code to handle -bexpfull and -bexpall.
> 	(xcoff_mark_auto_exports): New function.
> 	(xcoff_build_ldsyms): Use xcoff_auto_export_p to decide whether
> 	a function should be automatically exported.
> 	(bfd_xcoff_size_dynamic_sections): Replace the export_defineds
> 	parameter with an auto_export_flags parameter.  Update ldinfo
> 	accordingly.  Use xcoff_mark_auto_exports to mark all automatically-
> 	exported symbols.
> 
> ld/
> 	* emultempl/aix.em (auto_export_flags): New variable.
> 	(explicit_auto_export_flags): Likewise.
> 	(OPTION_EXPALL, OPTION_EXPFULL): New enum values.
> 	(OPTION_NOEXPALL, OPTION_NOEXPFULL): Likewise.
> 	(gld${EMULATION_NAME}_add_options): Add -bexpall, -bexpfull,
> 	-bnoexpall and -bnoexpfull.
> 	(gld${EMULATION_NAME}_handle_option): Handle them.
> 	(gld${EMULATION_NAME}_before_allocation): Update the call to
> 	bfd_size_dynamic_sections.
> 
> ld/testsuite/
> 	* ld-powerpc/aix-export-1-all.dd, ld-powerpc/aix-export-1-full.dd,
> 	ld-powerpc/aix-export-1a.s, ld-powerpc/aix-export-1b.s: New tests.
> 	* ld-powerpc/aix52.exp: Run them.

(I need a rubber stamp...) Approved - please apply.

Cheers
   Nick

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [17/21] Suppor garbage collection without an entry point
  2009-03-10 14:46 ` [17/21] Suppor garbage collection without an entry point Richard Sandiford
@ 2009-03-13 15:22   ` Nick Clifton
  0 siblings, 0 replies; 50+ messages in thread
From: Nick Clifton @ 2009-03-13 15:22 UTC (permalink / raw)
  To: binutils, richards

Hi Richard,

> bfd/
> 	* xcofflink.c (xcoff_mark_symbol_by_name): New function.
> 	(bfd_xcoff_size_dynamic_sections): Use it to mark the entry,
> 	init and fini functions.  Do garbage collection for objects
> 	without an entry point too.
> 
> ld/testsuite/
> 	* ld-powerpc/aix-gc-1.s, ld-powerpc/aix-gc-1.ex,
> 	ld-powerpc/aix-gc-1-32.dd, ld-powerpc/aix-gc-1-64.dd,
> 	ld-powerpc/aix-weak-1-gcdso.dnd, ld-powerpc/aix-weak-1-gcdso.hd,
> 	ld-powerpc/aix-weak-1-gcdso.nd: New tests.
> 	* ld-powerpc/aix52.exp: Run them.

Approved - please apply.

Cheers
   Nick

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [19/21] Give imported function descriptors class XMC_DS
  2009-03-10 14:50 ` [19/21] Give imported function descriptors class XMC_DS Richard Sandiford
@ 2009-03-13 15:24   ` Nick Clifton
  0 siblings, 0 replies; 50+ messages in thread
From: Nick Clifton @ 2009-03-13 15:24 UTC (permalink / raw)
  To: binutils, richards

Hi Richard,

> bfd/
> 	* xcofflink.c (xcoff_build_ldsyms): Give imported descriptors
> 	class XMC_DS rather than XMC_UA.

Approved - please apply.

Cheers
   Nick

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [20/21] Fix free() of in-use memory when handling archives
  2009-03-10 14:51 ` [20/21] Fix free() of in-use memory when handling archives Richard Sandiford
@ 2009-03-13 15:24   ` Nick Clifton
  0 siblings, 0 replies; 50+ messages in thread
From: Nick Clifton @ 2009-03-13 15:24 UTC (permalink / raw)
  To: binutils, richards

Hi Richard,

> bfd/
> 	* xcofflink.c (xcoff_link_check_archive_element): Only free the
> 	symbol table if it was created by the current call.

Approved - please apply.

Cheers
   Nick

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [21/21] GAS testsuite fix
  2009-03-10 14:53 ` [21/21] GAS testsuite fix Richard Sandiford
@ 2009-03-13 15:25   ` Nick Clifton
  0 siblings, 0 replies; 50+ messages in thread
From: Nick Clifton @ 2009-03-13 15:25 UTC (permalink / raw)
  To: binutils, richards

Hi Richard,

> gas/testsuite/
> 	* gas/ppc/textalign-xcoff-001.d: Expect the section VMAs to be
> 	properly aligned.
> 	* gas/ppc/textalign-xcoff-002.d: Likewise.

Approved - please apply.

Cheers
   Nick

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [3/21] Keep .text, .data and .bss on AIX
  2009-03-13 11:42       ` Nick Clifton
@ 2009-03-14  9:42         ` Richard Sandiford
  0 siblings, 0 replies; 50+ messages in thread
From: Richard Sandiford @ 2009-03-14  9:42 UTC (permalink / raw)
  To: Nick Clifton; +Cc: binutils

Nick Clifton <nickc@redhat.com> writes:
> Hi Richard,
>
>> ld/
>> 	* emultempl/aix.em (gld${EMULATION_NAME}_before_allocation): Mark
>> 	.text, .data and .bss output sections as SEC_KEEP.
>> 
>> ld/testsuite/
>> 	* ld-powerpc/aix-core-sec-1.s, ld-powerpc/aix-core-sec-1.ex,
>> 	ld-powerpc/aix-core-sec-1.hd, ld-powerpc/aix-core-sec-2.s,
>> 	ld-powerpc/aix-core-sec-2.ex, ld-powerpc/aix-core-sec-2.hd,
>> 	ld-powerpc/aix-core-sec-3.s, ld-powerpc/aix-core-sec-3.ex,
>> 	ld-powerpc/aix-core-sec-3.hd: New tests.
>> 	* ld-powerpc/aix52.exp: New harness.
>
> Approved - please apply - although ... :-)
>
>> +	  einfo ("%P: can't find output section %s\n", must_keep_sections[i]);
>
> I would suggest changing the wording to "can't find required output 
> section" as otherwise the user might think: "well so what if I don't 
> have a .bss section, who cares ?".

Yeah, I agree that's better.  Applied with that change, thanks.

Richard

^ permalink raw reply	[flat|nested] 50+ messages in thread

end of thread, other threads:[~2009-03-14  9:42 UTC | newest]

Thread overview: 50+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-03-10 13:58 [0/21] Add support for AIX 6 Richard Sandiford
2009-03-10 14:00 ` [1/21] Fix handling of archive tests Richard Sandiford
2009-03-12 16:15   ` Nick Clifton
2009-03-10 14:01 ` [2/21] Add support for AIX 6 Richard Sandiford
2009-03-12 16:17   ` Nick Clifton
2009-03-10 14:04 ` [3/21] Keep .text, .data and .bss on AIX Richard Sandiford
2009-03-12 16:36   ` Nick Clifton
2009-03-13  9:43     ` Richard Sandiford
2009-03-13 11:42       ` Nick Clifton
2009-03-14  9:42         ` Richard Sandiford
2009-03-10 14:05 ` [4/21] Fix o_cputype for 64-bit XCOFF objects Richard Sandiford
2009-03-12 16:38   ` Nick Clifton
2009-03-10 14:07 ` [5/21] Set config.dynamic_link for AIX Richard Sandiford
2009-03-12 16:39   ` Nick Clifton
2009-03-10 14:08 ` [6/21] XCOFF R_POS and R_NEG relocations against absolute symbols Richard Sandiford
2009-03-13 14:33   ` Nick Clifton
2009-03-10 14:13 ` [0/21] Add support for AIX 6 Ian Lance Taylor
2009-03-10 15:22   ` Richard Sandiford
2009-03-10 15:45   ` Michael Haubenwallner
2009-03-10 16:30     ` Ian Lance Taylor
2009-03-10 14:13 ` [7/21] Handle relative branches to absolute addresses Richard Sandiford
2009-03-13 14:37   ` Nick Clifton
2009-03-10 14:15 ` [8/21] bfd_install_relocation strikes again Richard Sandiford
2009-03-13 14:48   ` Nick Clifton
2009-03-10 14:22 ` [9/21] Implicitly import undefined symbols Richard Sandiford
2009-03-13 14:55   ` Nick Clifton
2009-03-10 14:25 ` [10/21] Fix the csect handling of XTY_ER symbols Richard Sandiford
2009-03-13 14:57   ` Nick Clifton
2009-03-10 14:29 ` [11/21] Cope with TOCs bigger than 32k, and other TC0 fixes Richard Sandiford
2009-03-13 14:59   ` Nick Clifton
2009-03-10 14:34 ` [12/21] Trim XCOFF symbols earlier in the link process Richard Sandiford
2009-03-13 15:01   ` Nick Clifton
2009-03-10 14:36 ` [13/21] Fix counting of line-number entries Richard Sandiford
2009-03-13 15:04   ` Nick Clifton
2009-03-10 14:38 ` [14/21] Treat absolute imports as XTY_ER/XMC_XO Richard Sandiford
2009-03-13 15:11   ` Nick Clifton
2009-03-10 14:40 ` [15/21] Avoid writing duplicate XCOFF symbols Richard Sandiford
2009-03-13 15:12   ` Nick Clifton
2009-03-10 14:45 ` [16/21] Add AIX weak support Richard Sandiford
2009-03-13 15:17   ` Nick Clifton
2009-03-10 14:46 ` [17/21] Suppor garbage collection without an entry point Richard Sandiford
2009-03-13 15:22   ` Nick Clifton
2009-03-10 14:49 ` [18/21] Add -bexpall and -bexpfull Richard Sandiford
2009-03-13 15:21   ` Nick Clifton
2009-03-10 14:50 ` [19/21] Give imported function descriptors class XMC_DS Richard Sandiford
2009-03-13 15:24   ` Nick Clifton
2009-03-10 14:51 ` [20/21] Fix free() of in-use memory when handling archives Richard Sandiford
2009-03-13 15:24   ` Nick Clifton
2009-03-10 14:53 ` [21/21] GAS testsuite fix Richard Sandiford
2009-03-13 15:25   ` Nick Clifton

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).