diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 77f080c9278c97a965cf9f74e880cd7f06ab70ff..b43f595ca0d8252e5c65c9667236ae802fce8931 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,10 @@
+2009-06-02  Richard Sandiford  <r.sandiford@uk.ibm.com>
+
+	* coff-rs6000.c (xcoff_ppc_relocate_section): Allow undefined
+	symbols to be left unimported when linking statically.
+	* xcofflink.c (xcoff_link_add_symbols): Ignore global linkage
+	code when linking statically.
+
 2009-06-02  H.J. Lu  <hongjiu.lu@intel.com>
 
 	* elf32-i386.c (elf_i386_check_relocs): Increment
diff --git a/bfd/coff-rs6000.c b/bfd/coff-rs6000.c
index 4859f31b2b4c3f57511684fa9e8b71b7d402d327..d1931538c145cb7a1ad9bb877d7fd8d745b119e8 100644
--- a/bfd/coff-rs6000.c
+++ b/bfd/coff-rs6000.c
@@ -3460,6 +3460,8 @@ xcoff_ppc_relocate_section (output_bfd, info, input_bfd,
 	      else
 		{
 		  BFD_ASSERT (info->relocatable
+			      || (info->static_link
+				  && (h->flags & XCOFF_WAS_UNDEFINED) != 0)
 			      || (h->flags & XCOFF_DEF_DYNAMIC) != 0
 			      || (h->flags & XCOFF_IMPORT) != 0);
 		}
diff --git a/bfd/xcofflink.c b/bfd/xcofflink.c
index 896292b393e8f8685dbcad1bb74e86c4dbae1953..1c2d0cbc23f25774be801e9e3f2f0de27d5b854e 100644
--- a/bfd/xcofflink.c
+++ b/bfd/xcofflink.c
@@ -1889,6 +1889,15 @@ xcoff_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
 	      || sym._n._n_n._n_offset == 0)
 	    copy = TRUE;
 
+	  /* Ignore global linkage code when linking statically.  */
+	  if (info->static_link
+	      && (smtyp == XTY_SD || smtyp == XTY_LD)
+	      && aux.x_csect.x_smclas == XMC_GL)
+	    {
+	      section = bfd_und_section_ptr;
+	      value = 0;
+	    }
+
 	  /* The AIX linker appears to only detect multiple symbol
 	     definitions when there is a reference to the symbol.  If
 	     a symbol is defined multiple times, and the only
@@ -1913,8 +1922,7 @@ xcoff_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
 	     We also have to handle the case of statically linking a
 	     shared object, which will cause symbol redefinitions,
 	     although this is an easier case to detect.  */
-
- 	  if (info->output_bfd->xvec == abfd->xvec)
+ 	  else if (info->output_bfd->xvec == abfd->xvec)
 	    {
 	      if (! bfd_is_und_section (section))
 		*sym_hash = xcoff_link_hash_lookup (xcoff_hash_table (info),
@@ -1934,23 +1942,8 @@ xcoff_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
 		  && ! bfd_is_com_section (section))
 		{
 		  /* This is a second definition of a defined symbol.  */
-		  if ((abfd->flags & DYNAMIC) != 0
-		      && ((*sym_hash)->smclas != XMC_GL
-			  || aux.x_csect.x_smclas == XMC_GL
-			  || ((*sym_hash)->root.u.def.section->owner->flags
-			      & DYNAMIC) == 0))
-		    {
-		      /* The new symbol is from a shared library, and
-			 either the existing symbol is not global
-			 linkage code or this symbol is global linkage
-			 code.  If the existing symbol is global
-			 linkage code and the new symbol is not, then
-			 we want to use the new symbol.  */
-		      section = bfd_und_section_ptr;
-		      value = 0;
-		    }
-		  else if (((*sym_hash)->flags & XCOFF_DEF_REGULAR) == 0
-			   && ((*sym_hash)->flags & XCOFF_DEF_DYNAMIC) != 0)
+		  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.  */
@@ -2049,7 +2042,9 @@ xcoff_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
 	    {
 	      int flag;
 
-	      if (smtyp == XTY_ER || smtyp == XTY_CM)
+	      if (smtyp == XTY_ER
+		  || smtyp == XTY_CM
+		  || section == bfd_und_section_ptr)
 		flag = XCOFF_REF_REGULAR;
 	      else
 		flag = XCOFF_DEF_REGULAR;
@@ -2741,6 +2736,10 @@ xcoff_mark_symbol (struct bfd_link_info *info, struct xcoff_link_hash_entry *h)
 	  /* We handle writing out the contents of the descriptor in
 	     xcoff_write_global_symbol.  */
 	}
+      else if (info->static_link)
+	/* We can't get a symbol value dynamically, so just assume
+	   that it's undefined.  */
+	h->flags |= XCOFF_WAS_UNDEFINED;
       else if ((h->flags & XCOFF_CALLED) != 0)
 	{
 	  /* This is a function symbol for which we need to create
diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog
index 6c73acfe214a60f78bcd0e7d967cc0b0751c55cb..fc606d1da8a32691186ba9a37985f6a21e976cd8 100644
--- a/ld/testsuite/ChangeLog
+++ b/ld/testsuite/ChangeLog
@@ -1,3 +1,11 @@
+2009-06-02  Richard Sandiford  <r.sandiford@uk.ibm.com>
+
+	* ld-powerpc/aix-glink-3.s, ld-powerpc/aix-glink-3a.s,
+	ld-powerpc/aix-glink-3b.s, ld-powerpc/aix-glink-3.dd,
+	ld-powerpc/aix-glink-3-32.d, ld-powerpc/aix-glink-3-64.d: New tests.
+	* ld-powerpc/aix52.exp: Run them.  Move the lineno tests to maintain
+	alphabetical order.
+
 2009-06-02  H.J. Lu  <hongjiu.lu@intel.com>
 
 	* ld-ifunc/ifunc-5-i386.d: Renamed to ...
diff --git a/ld/testsuite/ld-powerpc/aix-glink-3-32.d b/ld/testsuite/ld-powerpc/aix-glink-3-32.d
new file mode 100644
index 0000000000000000000000000000000000000000..754789f5677465282b3db7c0033a6a4bf6c7ceaf
--- /dev/null
+++ b/ld/testsuite/ld-powerpc/aix-glink-3-32.d
@@ -0,0 +1,5 @@
+#name: Glink test 3 (error) (32-bit)
+#source: aix-glink-3.s
+#as: -a32
+#ld: -b32 -bnoautoimp tmpdir/aix-glink-3b.so
+#error: undefined reference to `\.g'
diff --git a/ld/testsuite/ld-powerpc/aix-glink-3-64.d b/ld/testsuite/ld-powerpc/aix-glink-3-64.d
new file mode 100644
index 0000000000000000000000000000000000000000..3ea6817a47388391d8e9bf0a7db813b63b839af5
--- /dev/null
+++ b/ld/testsuite/ld-powerpc/aix-glink-3-64.d
@@ -0,0 +1,5 @@
+#name: Glink test 3 (error) (64-bit)
+#source: aix-glink-3.s
+#as: -a64
+#ld: -b64 -bnoautoimp tmpdir/aix64-glink-3b.so
+#error: undefined reference to `\.g'
diff --git a/ld/testsuite/ld-powerpc/aix-glink-3.dd b/ld/testsuite/ld-powerpc/aix-glink-3.dd
new file mode 100644
index 0000000000000000000000000000000000000000..b1549362f15be8384dd68068cbf41f7c2138a898
--- /dev/null
+++ b/ld/testsuite/ld-powerpc/aix-glink-3.dd
@@ -0,0 +1,14 @@
+
+.*
+
+
+Disassembly of section \.text:
+
+0*10000000 <\.f>:
+ *10000000:	48 00 00 05 	bl      10000004 <\.g>
+
+0*10000004 <\.g>:
+ *10000004:	4e 80 00 20 	bl?r
+
+0*10000008 <__start>:
+ *10000008:	4b ff ff f9 	bl      10000000 <\.f>
diff --git a/ld/testsuite/ld-powerpc/aix-glink-3.s b/ld/testsuite/ld-powerpc/aix-glink-3.s
new file mode 100644
index 0000000000000000000000000000000000000000..355dcc6385f5ce2a89a7e111eac99723394b483c
--- /dev/null
+++ b/ld/testsuite/ld-powerpc/aix-glink-3.s
@@ -0,0 +1,5 @@
+	.extern	.f
+	.globl	__start
+	.csect	__start[PR]
+__start:
+	bl	.f
diff --git a/ld/testsuite/ld-powerpc/aix-glink-3a.s b/ld/testsuite/ld-powerpc/aix-glink-3a.s
new file mode 100644
index 0000000000000000000000000000000000000000..76aad8c8af74c5b063c0753ee8f9cdfb9d42107d
--- /dev/null
+++ b/ld/testsuite/ld-powerpc/aix-glink-3a.s
@@ -0,0 +1,10 @@
+	.toc
+
+	.globl	.g
+	.csect	.g[PR]
+.g:
+	blr
+
+	.globl	g
+	.csect	g[DS]
+g:	.long	.g,TOC[tc0],0
diff --git a/ld/testsuite/ld-powerpc/aix-glink-3b.s b/ld/testsuite/ld-powerpc/aix-glink-3b.s
new file mode 100644
index 0000000000000000000000000000000000000000..0bedb3b0049aa7ebc5ee9fec4b7dc09c2aeba8d4
--- /dev/null
+++ b/ld/testsuite/ld-powerpc/aix-glink-3b.s
@@ -0,0 +1,11 @@
+	.toc
+
+	.extern	.g
+	.globl	.f
+	.csect	.f[PR]
+.f:
+	bl	.g
+
+	.globl	f
+	.csect	f[DS]
+f:	.long	.f,TOC[tc0],0
diff --git a/ld/testsuite/ld-powerpc/aix52.exp b/ld/testsuite/ld-powerpc/aix52.exp
index 25479ddb39059860453722caa52b802e92a9fbdd..d608490259d54dd245b2bc36b68b97454e305fc1 100644
--- a/ld/testsuite/ld-powerpc/aix52.exp
+++ b/ld/testsuite/ld-powerpc/aix52.exp
@@ -145,16 +145,6 @@ 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"}
-
     {"Glink test 2 (part a)" "-shared -bE:aix-glink-2a.ex"
      "" {aix-glink-2a.s}
      {}
@@ -176,6 +166,32 @@ set aix52tests {
      {{objdump -d aix-glink-2-SIZE.dd}}
      "aix-glink-2"}
 
+    {"Glink test 3 (shared library a)"
+     "-shared -bexpall"
+     "" {aix-glink-3a.s}
+     {} "aix-glink-3a.so"}
+
+    {"Glink test 3 (shared library b)"
+     "-shared -bexpall"
+     "" {aix-glink-3b.s}
+     {} "aix-glink-3b.so"}
+
+    {"Glink test 3 (main test)"
+     "-bnoautoimp tmpdir/aix-glink-3b.so tmpdir/aix-glink-3a.so"
+     "" {aix-glink-3.s}
+     {{objdump -d aix-glink-3.dd}}
+     "aix-glink-3"}
+
+    {"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"}
+
     {"Relocatable test 1" "-r"
      "" {aix-rel-1.s}
      {{objdump -hr aix-rel-1.od}} "aix-rel-1.ro"}
@@ -236,5 +252,9 @@ foreach test $aix52tests {
     }
 }
 
+run_dump_test "aix-glink-1-32"
+run_dump_test "aix-glink-1-64"
+run_dump_test "aix-glink-3-32"
+run_dump_test "aix-glink-3-64"
 run_dump_test "aix-weak-3-32"
 run_dump_test "aix-weak-3-64"