[1/2] MIPS/LD: Set symtab's `sh_info' correctly for IRIX emulations

Message ID alpine.LFD.2.21.2007262238190.1561071@eddie.linux-mips.org
State New
Headers show
Series
  • MIPS: IRIX ELF format symbol table sort/section symbol name fixes
Related show

Commit Message

Maciej W. Rozycki July 27, 2020, 9:47 a.m.
Correct ELF linker code so as to set the `sh_info' value of the static 
symbol table section according to the section symbols vs other symbols 
split where required by the selection of the IRIX compatibility mode for 
MIPS target.  Add a `elf_backend_elfsym_local_is_section' hook for that 
purpose, returning TRUE if it is only STB_LOCAL/STT_SECTION symbols that 
are to be considered local for the purpose of this split rather than all 
STB_LOCAL symbols.

We do it already in generic ELF code, and have done it since 1993, with 
the `elf_backend_sym_is_global' hook, affecting GAS and `objcopy', so 
these tools produce correct ELF output in the IRIX compatibility mode, 
however if such output is fed as input to `ld -r', then the linker's 
output is no longer valid for that mode.  The relevant changes to 
generic ELF code are:

commit 062189c6eab72c7ba1bab1cf30fdb27d67a7d668
Author: Ian Lance Taylor <ian@airs.com>
Date:   Thu Nov 18 17:12:47 1993 +0000

and:

commit 6e07e54f1b347f885cc6c021c3fd912c79bdaf55
Author: Ian Lance Taylor <ian@airs.com>
Date:   Thu Jan 6 20:01:42 1994 +0000

(split across two GIT commits likely due to repository conversion 
peculiarities).

The `elf_backend_sym_is_global' hook however operates on BFD rather than 
ELF symbols, making it unsuitable for the ELF linker as the linker does 
not convert any symbol tables processed into the BFD format.  Converting 
the hook to operate on ELF symbols would in principle be possible, but 
it would still require a considerable rewrite of `bfd_elf_final_link' to 
adapt to the interface.

Therefore, especially given that no new use for the IRIX compatibility 
mode is expected, minimize changes made to the ELF linker code and just 
add an entirely new hook, and wire it in the o32 and n32 MIPS backends 
accordingly; the n64 backend never uses the IRIX compatibility mode.

Since we have no coverage here at all add suitable GAS, LD and `objcopy' 
test cases to the relevant testsuites to keep these tools consistently 
verified.

	bfd/
	* elf-bfd.h (elf_backend_data): Add
	`elf_backend_elfsym_local_is_section' member.
	* elfxx-target.h (elf_backend_elfsym_local_is_section): New 
	macro.
	(elfNN_bed): Add `elf_backend_elfsym_local_is_section' member.
	* elflink.c (bfd_elf_final_link): Use it to determine whether 
	set the `.symtab' section's `sh_info' value to the index of the 
	first non-local or non-section symbol.
	* elf32-mips.c (mips_elf32_elfsym_local_is_section): New 
	function.
	(elf_backend_elfsym_local_is_section): New macro.
	* elfn32-mips.c (mips_elf_n32_elfsym_local_is_section): New 
	function.
	(elf_backend_elfsym_local_is_section): New macro.

	binutils/
	* testsuite/binutils-all/mips/global-local-symtab-o32.d: New 
	test.
	* testsuite/binutils-all/mips/global-local-symtab-o32t.d: New 
	test.
	* testsuite/binutils-all/mips/global-local-symtab-n32.d: New 
	test.
	* testsuite/binutils-all/mips/global-local-symtab-n32t.d: New 
	test.
	* testsuite/binutils-all/mips/global-local-symtab-n64.d: New 
	test.
	* testsuite/binutils-all/mips/mips.exp: Run the new tests.

	gas/
	* testsuite/gas/mips/global-local-symtab-o32.d: New test.
	* testsuite/gas/mips/global-local-symtab-o32t.d: New test.
	* testsuite/gas/mips/global-local-symtab-n32.d: New test.
	* testsuite/gas/mips/global-local-symtab-n32t.d: New test.
	* testsuite/gas/mips/global-local-symtab-n64.d: New test.
	* testsuite/gas/mips/global-local-symtab.s: New test source.
	* testsuite/gas/mips/mips.exp: Run the new tests.

	ld/
	* testsuite/ld-mips-elf/global-local-symtab-o32.d: New test.
	* testsuite/ld-mips-elf/global-local-symtab-o32t.d: New test.
	* testsuite/ld-mips-elf/global-local-symtab-n32.d: New test.
	* testsuite/ld-mips-elf/global-local-symtab-n32t.d: New test.
	* testsuite/ld-mips-elf/global-local-symtab-n64.d: New test.
	* testsuite/ld-mips-elf/global-local-symtab.ld: New test linker 
	script.
	* testsuite/ld-mips-elf/mips-elf.exp: Run the new tests.
---
 bfd/elf-bfd.h                                                   |    8 ++++++
 bfd/elf32-mips.c                                                |   12 ++++++++++
 bfd/elflink.c                                                   |   10 +++++++-
 bfd/elfn32-mips.c                                               |   12 ++++++++++
 bfd/elfxx-target.h                                              |    4 +++
 binutils/testsuite/binutils-all/mips/global-local-symtab-n32.d  |    8 ++++++
 binutils/testsuite/binutils-all/mips/global-local-symtab-n32t.d |    8 ++++++
 binutils/testsuite/binutils-all/mips/global-local-symtab-n64.d  |   10 ++++++++
 binutils/testsuite/binutils-all/mips/global-local-symtab-o32.d  |   10 ++++++++
 binutils/testsuite/binutils-all/mips/global-local-symtab-o32t.d |   10 ++++++++
 binutils/testsuite/binutils-all/mips/mips.exp                   |    5 ++++
 gas/testsuite/gas/mips/global-local-symtab-n32.d                |    6 +++++
 gas/testsuite/gas/mips/global-local-symtab-n32t.d               |    6 +++++
 gas/testsuite/gas/mips/global-local-symtab-n64.d                |    8 ++++++
 gas/testsuite/gas/mips/global-local-symtab-o32.d                |    8 ++++++
 gas/testsuite/gas/mips/global-local-symtab-o32t.d               |    8 ++++++
 gas/testsuite/gas/mips/global-local-symtab.s                    |   10 ++++++++
 gas/testsuite/gas/mips/mips.exp                                 |    6 +++++
 ld/testsuite/ld-mips-elf/global-local-symtab-n32.d              |    6 +++++
 ld/testsuite/ld-mips-elf/global-local-symtab-n32t.d             |    6 +++++
 ld/testsuite/ld-mips-elf/global-local-symtab-n64.d              |    8 ++++++
 ld/testsuite/ld-mips-elf/global-local-symtab-o32.d              |    8 ++++++
 ld/testsuite/ld-mips-elf/global-local-symtab-o32t.d             |    8 ++++++
 ld/testsuite/ld-mips-elf/global-local-symtab.ld                 |    8 ++++++
 ld/testsuite/ld-mips-elf/mips-elf.exp                           |    6 +++++
 25 files changed, 198 insertions(+), 1 deletion(-)

binutils-mips-bfd-elfsym-local-is-section.diff

Patch

Index: binutils/bfd/elf-bfd.h
===================================================================
--- binutils.orig/bfd/elf-bfd.h
+++ binutils/bfd/elf-bfd.h
@@ -1402,6 +1402,14 @@  struct elf_backend_data
   bfd_boolean (*elf_backend_write_section)
     (bfd *, struct bfd_link_info *, asection *, bfd_byte *);
 
+  /* This function, if defined, returns TRUE if it is section symbols
+     only that are considered local for the purpose of partitioning the
+     symbol table into local and global symbols.  This should be NULL
+     for most targets, in which case the correct thing will be done.
+     MIPS ELF, at least on the Irix 5, has special requirements.  */
+  bfd_boolean (*elf_backend_elfsym_local_is_section)
+    (bfd *);
+
   /* The level of IRIX compatibility we're striving for.
      MIPS ELF specific function.  */
   irix_compat_t (*elf_backend_mips_irix_compat)
Index: binutils/bfd/elf32-mips.c
===================================================================
--- binutils.orig/bfd/elf32-mips.c
+++ binutils/bfd/elf32-mips.c
@@ -63,6 +63,8 @@  static bfd_boolean mips_info_to_howto_re
   (bfd *, arelent *, Elf_Internal_Rela *);
 static bfd_boolean mips_elf_sym_is_global
   (bfd *, asymbol *);
+static bfd_boolean mips_elf32_elfsym_local_is_section
+  (bfd *);
 static bfd_boolean mips_elf32_object_p
   (bfd *);
 static bfd_boolean mips_elf_is_local_label_name
@@ -2284,6 +2286,14 @@  mips_elf_sym_is_global (bfd *abfd ATTRIB
 	    || bfd_is_und_section (bfd_asymbol_section (sym))
 	    || bfd_is_com_section (bfd_asymbol_section (sym)));
 }
+
+/* Likewise, return TRUE if the symbol table split overall must be
+   between section symbols and all other symbols.  */
+static bfd_boolean
+mips_elf32_elfsym_local_is_section (bfd *abfd)
+{
+  return SGI_COMPAT (abfd);
+}
 
 /* Set the right machine number for a MIPS ELF file.  */
 
@@ -2552,6 +2562,8 @@  static const struct ecoff_debug_swap mip
 #define elf_backend_ignore_discarded_relocs \
 					_bfd_mips_elf_ignore_discarded_relocs
 #define elf_backend_write_section	_bfd_mips_elf_write_section
+#define elf_backend_elfsym_local_is_section \
+					mips_elf32_elfsym_local_is_section
 #define elf_backend_mips_irix_compat	elf32_mips_irix_compat
 #define elf_backend_mips_rtype_to_howto	mips_elf32_rtype_to_howto
 #define elf_backend_sort_relocs_p	_bfd_mips_elf_sort_relocs_p
Index: binutils/bfd/elflink.c
===================================================================
--- binutils.orig/bfd/elflink.c
+++ binutils/bfd/elflink.c
@@ -12315,6 +12315,13 @@  bfd_elf_final_link (bfd *abfd, struct bf
 	}
     }
 
+  /* On some targets like Irix 5 the symbol split between local and global
+     ones recorded in the sh_info field needs to be done between section
+     and all other symbols.  */
+  if (bed->elf_backend_elfsym_local_is_section
+      && bed->elf_backend_elfsym_local_is_section (abfd))
+    symtab_hdr->sh_info = bfd_get_symcount (abfd);
+
   /* Allocate some memory to hold information read in from the input
      files.  */
   if (max_contents_size != 0)
@@ -12541,7 +12548,8 @@  bfd_elf_final_link (bfd *abfd, struct bf
      converted to local in a version script.  */
 
   /* The sh_info field records the index of the first non local symbol.  */
-  symtab_hdr->sh_info = bfd_get_symcount (abfd);
+  if (!symtab_hdr->sh_info)
+    symtab_hdr->sh_info = bfd_get_symcount (abfd);
 
   if (dynamic
       && htab->dynsym != NULL
Index: binutils/bfd/elfn32-mips.c
===================================================================
--- binutils.orig/bfd/elfn32-mips.c
+++ binutils/bfd/elfn32-mips.c
@@ -72,6 +72,8 @@  static bfd_boolean mips_info_to_howto_re
   (bfd *, arelent *, Elf_Internal_Rela *);
 static bfd_boolean mips_elf_sym_is_global
   (bfd *, asymbol *);
+static bfd_boolean mips_elf_n32_elfsym_local_is_section
+  (bfd *);
 static bfd_boolean mips_elf_n32_object_p
   (bfd *);
 static bfd_boolean elf32_mips_grok_prstatus
@@ -3844,6 +3846,14 @@  mips_elf_sym_is_global (bfd *abfd ATTRIB
 	    || bfd_is_und_section (bfd_asymbol_section (sym))
 	    || bfd_is_com_section (bfd_asymbol_section (sym)));
 }
+
+/* Likewise, return TRUE if the symbol table split overall must be
+   between section symbols and all other symbols.  */
+static bfd_boolean
+mips_elf_n32_elfsym_local_is_section (bfd *abfd)
+{
+  return SGI_COMPAT (abfd);
+}
 
 /* Set the right machine number for a MIPS ELF file.  */
 
@@ -4160,6 +4170,8 @@  static const struct ecoff_debug_swap mip
 #define elf_backend_ignore_discarded_relocs \
 					_bfd_mips_elf_ignore_discarded_relocs
 #define elf_backend_write_section	_bfd_mips_elf_write_section
+#define elf_backend_elfsym_local_is_section \
+					mips_elf_n32_elfsym_local_is_section
 #define elf_backend_mips_irix_compat	elf_n32_mips_irix_compat
 #define elf_backend_mips_rtype_to_howto	mips_elf_n32_rtype_to_howto
 #define bfd_elf32_bfd_is_target_special_symbol \
Index: binutils/bfd/elfxx-target.h
===================================================================
--- binutils.orig/bfd/elfxx-target.h
+++ binutils/bfd/elfxx-target.h
@@ -660,6 +660,9 @@ 
 #ifndef elf_backend_write_section
 #define elf_backend_write_section		NULL
 #endif
+#ifndef elf_backend_elfsym_local_is_section
+#define elf_backend_elfsym_local_is_section	NULL
+#endif
 #ifndef elf_backend_mips_irix_compat
 #define elf_backend_mips_irix_compat		NULL
 #endif
@@ -884,6 +887,7 @@  static struct elf_backend_data elfNN_bed
   elf_backend_can_make_lsda_relative_eh_frame,
   elf_backend_encode_eh_address,
   elf_backend_write_section,
+  elf_backend_elfsym_local_is_section,
   elf_backend_mips_irix_compat,
   elf_backend_mips_rtype_to_howto,
   elf_backend_ecoff_debug_swap,
Index: binutils/binutils/testsuite/binutils-all/mips/global-local-symtab-n32.d
===================================================================
--- /dev/null
+++ binutils/binutils/testsuite/binutils-all/mips/global-local-symtab-n32.d
@@ -0,0 +1,8 @@ 
+#PROG: objcopy
+#DUMPPROG: readelf
+#name: MIPS global/local symbol table split (n32)
+#as: -n32 -mno-pdr -mips3
+#objcopy: -j .data -j .symtab -j .strtab -j .shstrtab
+#readelf: -S
+#source: ../../../../gas/testsuite/gas/mips/global-local-symtab.s
+#dump: global-local-symtab-o32.d
Index: binutils/binutils/testsuite/binutils-all/mips/global-local-symtab-n32t.d
===================================================================
--- /dev/null
+++ binutils/binutils/testsuite/binutils-all/mips/global-local-symtab-n32t.d
@@ -0,0 +1,8 @@ 
+#PROG: objcopy
+#DUMPPROG: readelf
+#name: MIPS global/local symbol table split (n32)
+#as: -n32 -mno-pdr -mips3
+#objcopy: -j .data -j .symtab -j .strtab -j .shstrtab
+#readelf: -S
+#source: ../../../../gas/testsuite/gas/mips/global-local-symtab.s
+#dump: global-local-symtab-o32t.d
Index: binutils/binutils/testsuite/binutils-all/mips/global-local-symtab-n64.d
===================================================================
--- /dev/null
+++ binutils/binutils/testsuite/binutils-all/mips/global-local-symtab-n64.d
@@ -0,0 +1,10 @@ 
+#PROG: objcopy
+#DUMPPROG: readelf
+#name: MIPS global/local symbol table split (n64)
+#as: -64 -mno-pdr -mips3
+#objcopy: -j .data -j .symtab -j .strtab -j .shstrtab
+#readelf: -SW
+#source: ../../../../gas/testsuite/gas/mips/global-local-symtab.s
+#...
+ *\[ *[0-9]+\] +\.symtab +SYMTAB +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +18 +3 +3 +8
+#pass
Index: binutils/binutils/testsuite/binutils-all/mips/global-local-symtab-o32.d
===================================================================
--- /dev/null
+++ binutils/binutils/testsuite/binutils-all/mips/global-local-symtab-o32.d
@@ -0,0 +1,10 @@ 
+#PROG: objcopy
+#DUMPPROG: readelf
+#name: MIPS global/local symbol table split (o32)
+#as: -32 -mno-pdr
+#objcopy: -j .data -j .symtab -j .strtab -j .shstrtab
+#readelf: -S
+#source: ../../../../gas/testsuite/gas/mips/global-local-symtab.s
+#...
+ *\[ *[0-9]+\] +\.symtab +SYMTAB +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +10 +3 +2 +4
+#pass
Index: binutils/binutils/testsuite/binutils-all/mips/global-local-symtab-o32t.d
===================================================================
--- /dev/null
+++ binutils/binutils/testsuite/binutils-all/mips/global-local-symtab-o32t.d
@@ -0,0 +1,10 @@ 
+#PROG: objcopy
+#DUMPPROG: readelf
+#name: MIPS global/local symbol table split (o32)
+#as: -32 -mno-pdr
+#objcopy: -j .data -j .symtab -j .strtab -j .shstrtab
+#readelf: -S
+#source: ../../../../gas/testsuite/gas/mips/global-local-symtab.s
+#...
+ *\[ *[0-9]+\] +\.symtab +SYMTAB +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +10 +3 +3 +4
+#pass
Index: binutils/binutils/testsuite/binutils-all/mips/mips.exp
===================================================================
--- binutils.orig/binutils/testsuite/binutils-all/mips/mips.exp
+++ binutils/binutils/testsuite/binutils-all/mips/mips.exp
@@ -218,6 +218,7 @@  if {[istarget *-*-openbsd*] } {
     set abi_asflags(o32) -32
     set irixemul 1
 }
+set tmips [expr $irixemul ? {""} : {"t"}]
 
 run_dump_test_o32 "mips-ase-1"
 run_dump_test_o32 "mips-ase-2"
@@ -247,3 +248,7 @@  run_dump_test_n64 "mips-note-2r-n64"
 
 run_dump_test_o32 "mips-reginfo"
 run_dump_test_n32 "mips-reginfo-n32"
+
+run_dump_test_o32 "global-local-symtab-o32${tmips}"
+run_dump_test_n32 "global-local-symtab-n32${tmips}"
+run_dump_test_n64 "global-local-symtab-n64"
Index: binutils/gas/testsuite/gas/mips/global-local-symtab-n32.d
===================================================================
--- /dev/null
+++ binutils/gas/testsuite/gas/mips/global-local-symtab-n32.d
@@ -0,0 +1,6 @@ 
+#DUMPPROG: readelf
+#readelf: -S
+#name: MIPS global/local symbol table split (n32)
+#as: -n32 -mno-pdr -mips3
+#source: global-local-symtab.s
+#dump: global-local-symtab-o32.d
Index: binutils/gas/testsuite/gas/mips/global-local-symtab-n32t.d
===================================================================
--- /dev/null
+++ binutils/gas/testsuite/gas/mips/global-local-symtab-n32t.d
@@ -0,0 +1,6 @@ 
+#DUMPPROG: readelf
+#readelf: -S
+#name: MIPS global/local symbol table split (n32)
+#as: -n32 -mno-pdr -mips3
+#source: global-local-symtab.s
+#dump: global-local-symtab-o32t.d
Index: binutils/gas/testsuite/gas/mips/global-local-symtab-n64.d
===================================================================
--- /dev/null
+++ binutils/gas/testsuite/gas/mips/global-local-symtab-n64.d
@@ -0,0 +1,8 @@ 
+#DUMPPROG: readelf
+#readelf: -SW
+#name: MIPS global/local symbol table split (n64)
+#as: -64 -mno-pdr -mips3
+#source: global-local-symtab.s
+#...
+ *\[ *[0-9]+\] +\.symtab +SYMTAB +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +18 +8 +8 +8
+#pass
Index: binutils/gas/testsuite/gas/mips/global-local-symtab-o32.d
===================================================================
--- /dev/null
+++ binutils/gas/testsuite/gas/mips/global-local-symtab-o32.d
@@ -0,0 +1,8 @@ 
+#DUMPPROG: readelf
+#readelf: -S
+#name: MIPS global/local symbol table split (o32)
+#as: -32 -mno-pdr
+#source: global-local-symtab.s
+#...
+ *\[ *[0-9]+\] +\.symtab +SYMTAB +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +10 +8 +7 +4
+#pass
Index: binutils/gas/testsuite/gas/mips/global-local-symtab-o32t.d
===================================================================
--- /dev/null
+++ binutils/gas/testsuite/gas/mips/global-local-symtab-o32t.d
@@ -0,0 +1,8 @@ 
+#DUMPPROG: readelf
+#readelf: -S
+#name: MIPS global/local symbol table split (o32)
+#as: -32 -mno-pdr
+#source: global-local-symtab.s
+#...
+ *\[ *[0-9]+\] +\.symtab +SYMTAB +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +10 +8 +8 +4
+#pass
Index: binutils/gas/testsuite/gas/mips/global-local-symtab.s
===================================================================
--- /dev/null
+++ binutils/gas/testsuite/gas/mips/global-local-symtab.s
@@ -0,0 +1,10 @@ 
+	.data
+	.globl	foo
+	.type	foo, @object
+foo:
+	.dc.l	0
+	.size	foo, . - foo
+	.type	bar, @object
+bar:
+	.dc.l	0
+	.size	bar, . - bar
Index: binutils/gas/testsuite/gas/mips/mips.exp
===================================================================
--- binutils.orig/gas/testsuite/gas/mips/mips.exp
+++ binutils/gas/testsuite/gas/mips/mips.exp
@@ -2092,4 +2092,10 @@  if { [istarget mips*-*-vxworks*] } {
 
     run_dump_test "pr14798${imips}"
     run_dump_test "insn-isa-mode"
+    run_dump_test "insn-isa-mode"
+    run_dump_test "global-local-symtab-o32${tmips}"
+    if $has_newabi {
+	run_dump_test "global-local-symtab-n32${tmips}"
+	run_dump_test "global-local-symtab-n64"
+    }
 }
Index: binutils/ld/testsuite/ld-mips-elf/global-local-symtab-n32.d
===================================================================
--- /dev/null
+++ binutils/ld/testsuite/ld-mips-elf/global-local-symtab-n32.d
@@ -0,0 +1,6 @@ 
+#name: MIPS global/local symbol table split (n32)
+#source: ../../../gas/testsuite/gas/mips/global-local-symtab.s
+#as: -mno-pdr
+#ld: -r -T global-local-symtab.ld
+#readelf: -S
+#dump: global-local-symtab-o32.d
Index: binutils/ld/testsuite/ld-mips-elf/global-local-symtab-n32t.d
===================================================================
--- /dev/null
+++ binutils/ld/testsuite/ld-mips-elf/global-local-symtab-n32t.d
@@ -0,0 +1,6 @@ 
+#name: MIPS global/local symbol table split (n32)
+#source: ../../../gas/testsuite/gas/mips/global-local-symtab.s
+#as: -mno-pdr
+#ld: -r -T global-local-symtab.ld
+#readelf: -S
+#dump: global-local-symtab-o32t.d
Index: binutils/ld/testsuite/ld-mips-elf/global-local-symtab-n64.d
===================================================================
--- /dev/null
+++ binutils/ld/testsuite/ld-mips-elf/global-local-symtab-n64.d
@@ -0,0 +1,8 @@ 
+#name: MIPS global/local symbol table split (n64)
+#source: ../../../gas/testsuite/gas/mips/global-local-symtab.s
+#as: -mno-pdr
+#ld: -r -T global-local-symtab.ld
+#readelf: -SW
+#...
+ *\[ *[0-9]+\] +\.symtab +SYMTAB +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +18 +3 +4 +8
+#pass
Index: binutils/ld/testsuite/ld-mips-elf/global-local-symtab-o32.d
===================================================================
--- /dev/null
+++ binutils/ld/testsuite/ld-mips-elf/global-local-symtab-o32.d
@@ -0,0 +1,8 @@ 
+#name: MIPS global/local symbol table split (o32)
+#source: ../../../gas/testsuite/gas/mips/global-local-symtab.s
+#as: -mno-pdr
+#ld: -r -T global-local-symtab.ld
+#readelf: -S
+#...
+ *\[ *[0-9]+\] +\.symtab +SYMTAB +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +10 +3 +2 +4
+#pass
Index: binutils/ld/testsuite/ld-mips-elf/global-local-symtab-o32t.d
===================================================================
--- /dev/null
+++ binutils/ld/testsuite/ld-mips-elf/global-local-symtab-o32t.d
@@ -0,0 +1,8 @@ 
+#name: MIPS global/local symbol table split (o32)
+#source: ../../../gas/testsuite/gas/mips/global-local-symtab.s
+#as: -mno-pdr
+#ld: -r -T global-local-symtab.ld
+#readelf: -S
+#...
+ *\[ *[0-9]+\] +\.symtab +SYMTAB +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +10 +3 +4 +4
+#pass
Index: binutils/ld/testsuite/ld-mips-elf/global-local-symtab.ld
===================================================================
--- /dev/null
+++ binutils/ld/testsuite/ld-mips-elf/global-local-symtab.ld
@@ -0,0 +1,8 @@ 
+SECTIONS
+{
+  .data : { *(.data) }
+  .symtab : { *(.symtab) }
+  .strtab : { *(.strtab) }
+  .shstrtab : { *(.shstrtab) }
+  /DISCARD/ : { *(*) }
+}
Index: binutils/ld/testsuite/ld-mips-elf/mips-elf.exp
===================================================================
--- binutils.orig/ld/testsuite/ld-mips-elf/mips-elf.exp
+++ binutils/ld/testsuite/ld-mips-elf/mips-elf.exp
@@ -248,6 +248,7 @@  if {[istarget *-*-openbsd*] } {
     set abi_asflags(o32) -32
     set irixemul 1
 }
+set tmips [expr $irixemul ? {""} : {"t"}]
 
 if { $linux_gnu } {
     run_ld_link_tests [list \
@@ -1657,3 +1658,8 @@  run_dump_test_n64 "pic-reloc-7" [list [l
 				      [list as "-mmicromips"]]
 
 run_dump_test_o32 "reloc-pcrel-r6"
+
+# Global/local symbol table split tests.
+run_dump_test_o32 "global-local-symtab-o32${tmips}"
+run_dump_test_n32 "global-local-symtab-n32${tmips}"
+run_dump_test_n64 "global-local-symtab-n64"