New bfd elf hook: force naming of local section symbols

Richard Sandiford rsandifo@redhat.com
Sun Feb 8 14:02:00 GMT 2004


OK, I know this is lame, but I'd like to add a hook to force
swap_out_syms() to name local section symbols.  Besides the
obvious file bloat, is there any reason why this would be
a bad thing?

The reason I need the hook is to work around a bug in the MIPSpro
linker.  If you use MIPSpro to build the attached test case:

    as got-disp-2.s -o got-disp-2.o
    ld /usr/lib32/crt1.o got-disp-2.o -lc /usr/lib32/crtn.o
    ./a.out

then it works OK.  Use gas instead, and you get:

    Trace/BPT/RangeErr/DivZero/Ovflow trap (core dumped)

The crucial difference is that MIPSpro names the section symbols:

   Num:    Value  Size Type    Bind   Vis      Ndx Name
     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 00000000     0 SECTION LOCAL  DEFAULT    4 .text
     2: 00000000     0 SECTION LOCAL  DEFAULT    5 .data

but bfd doesn't.  For some reason, if the symbols for .text and .data
don't have names, then the MIPSpro linker will resolve both of the
following relocations to .data:

	lw	$4,%got_disp(.data)($gp)
	lw	$25,%got_disp(.text)($gp)
	jalr	$25

The program ends up jumping there rather than to .text.

Note that got-disp-2.s is just the explicit-reloc version of what gas
produces for got-disp-1.s.  This is the cause of many gcc testsuite
failures when using gas with the native linker, see:

    http://gcc.gnu.org/ml/gcc-testresults/2004-02/msg00250.html

for the full horror.

Patch tested by bootstrapping & regression testing gcc on IRIX with
the combination of gas and the native linker.  Fixes many testsuite
failures and the got-disp-* ones below.  OK to install?

Thanks to Rainer for the heads-up about this.

Richard



	* bfd-elf.h (elf_backend_name_local_section_symbols): New hook.
	* elf.c (swap_out_syms): Use it to decide whether local section
	symbols should be named.
	* elfxx-target.h (elf_backend_name_local_section_symbols): New macro.
	* elfxx-mips.h (_bfd_mips_elf_name_local_section_symbols): Declare.
	(elf_backend_name_local_section_symbols): Define.
	* elfxx-mips.c (_bfd_mips_elf_name_local_section_symbols): New.

Index: bfd/elf-bfd.h
===================================================================
RCS file: /cvs/src/src/bfd/elf-bfd.h,v
retrieving revision 1.124
diff -c -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.124 elf-bfd.h
*** bfd/elf-bfd.h	8 Dec 2003 13:05:09 -0000	1.124
--- bfd/elf-bfd.h	8 Feb 2004 13:28:06 -0000
*************** struct elf_backend_data
*** 576,581 ****
--- 576,586 ----
    int (*elf_backend_get_symbol_type)
      (Elf_Internal_Sym *, int);
  
+   /* Return true if local section symbols should have a non-null st_name.
+      NULL implies false.  */
+   bfd_boolean (*elf_backend_name_local_section_symbols)
+     (bfd *);
+ 
    /* A function to do additional processing on the ELF section header
       just before writing it out.  This is used to set the flags and
       type fields for some sections, or to actually write out data for
Index: bfd/elf.c
===================================================================
RCS file: /cvs/src/src/bfd/elf.c,v
retrieving revision 1.215
diff -c -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.215 elf.c
*** bfd/elf.c	11 Dec 2003 18:10:19 -0000	1.215
--- bfd/elf.c	8 Feb 2004 13:28:08 -0000
*************** swap_out_syms (bfd *abfd,
*** 5261,5266 ****
--- 5261,5267 ----
    char *outbound_shndx;
    int idx;
    bfd_size_type amt;
+   bfd_boolean name_local_sections;
  
    if (!elf_map_symbols (abfd))
      return FALSE;
*************** swap_out_syms (bfd *abfd,
*** 5326,5331 ****
--- 5327,5336 ----
        outbound_shndx += sizeof (Elf_External_Sym_Shndx);
    }
  
+   name_local_sections
+     = (bed->elf_backend_name_local_section_symbols
+        && bed->elf_backend_name_local_section_symbols (abfd));
+ 
    syms = bfd_get_outsymbols (abfd);
    for (idx = 0; idx < symcount; idx++)
      {
*************** swap_out_syms (bfd *abfd,
*** 5335,5341 ****
        flagword flags = syms[idx]->flags;
        int type;
  
!       if ((flags & (BSF_SECTION_SYM | BSF_GLOBAL)) == BSF_SECTION_SYM)
  	{
  	  /* Local section symbols have no name.  */
  	  sym.st_name = 0;
--- 5340,5347 ----
        flagword flags = syms[idx]->flags;
        int type;
  
!       if (!name_local_sections
! 	  && (flags & (BSF_SECTION_SYM | BSF_GLOBAL)) == BSF_SECTION_SYM)
  	{
  	  /* Local section symbols have no name.  */
  	  sym.st_name = 0;
Index: bfd/elfxx-target.h
===================================================================
RCS file: /cvs/src/src/bfd/elfxx-target.h,v
retrieving revision 1.58
diff -c -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.58 elfxx-target.h
*** bfd/elfxx-target.h	3 Nov 2003 15:17:40 -0000	1.58
--- bfd/elfxx-target.h	8 Feb 2004 13:28:08 -0000
*************** #define elf_backend_symbol_table_process
*** 274,279 ****
--- 274,282 ----
  #ifndef elf_backend_get_symbol_type
  #define elf_backend_get_symbol_type 0
  #endif
+ #ifndef elf_backend_name_local_section_symbols
+ #define elf_backend_name_local_section_symbols	0
+ #endif
  #ifndef elf_backend_section_processing
  #define elf_backend_section_processing	0
  #endif
*************** static const struct elf_backend_data elf
*** 456,461 ****
--- 459,465 ----
    elf_backend_symbol_processing,
    elf_backend_symbol_table_processing,
    elf_backend_get_symbol_type,
+   elf_backend_name_local_section_symbols,
    elf_backend_section_processing,
    elf_backend_section_from_shdr,
    elf_backend_section_flags,
Index: bfd/elfxx-mips.h
===================================================================
RCS file: /cvs/src/src/bfd/elfxx-mips.h,v
retrieving revision 1.17
diff -c -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.17 elfxx-mips.h
*** bfd/elfxx-mips.h	18 Dec 2003 10:23:07 -0000	1.17
--- bfd/elfxx-mips.h	8 Feb 2004 13:28:08 -0000
*************** extern bfd_boolean _bfd_mips_elf_new_sec
*** 24,29 ****
--- 24,31 ----
    (bfd *, asection *);
  extern void _bfd_mips_elf_symbol_processing
    (bfd *, asymbol *);
+ extern bfd_boolean _bfd_mips_elf_name_local_section_symbols
+   (bfd *);
  extern bfd_boolean _bfd_mips_elf_section_processing
    (bfd *, Elf_Internal_Shdr *);
  extern bfd_boolean _bfd_mips_elf_section_from_shdr
*************** extern bfd_vma _bfd_mips_elf_sign_extend
*** 119,122 ****
--- 121,126 ----
    (bfd_vma, int);
  
  extern struct bfd_elf_special_section const _bfd_mips_elf_special_sections[];
+ #define elf_backend_name_local_section_symbols \
+   _bfd_mips_elf_name_local_section_symbols
  #define elf_backend_special_sections _bfd_mips_elf_special_sections
Index: bfd/elfxx-mips.c
===================================================================
RCS file: /cvs/src/src/bfd/elfxx-mips.c,v
retrieving revision 1.88
diff -c -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.88 elfxx-mips.c
*** bfd/elfxx-mips.c	18 Dec 2003 10:23:07 -0000	1.88
--- bfd/elfxx-mips.c	8 Feb 2004 13:28:10 -0000
*************** _bfd_mips_elf_symbol_processing (bfd *ab
*** 4271,4276 ****
--- 4271,4296 ----
      }
  }
  
+ /* There appears to be a bug in the MIPSpro linker that causes GOT_DISP
+    relocations against two unnamed section symbols to resolve to the
+    same address.  For example, if we have code like:
+ 
+ 	lw	$4,%got_disp(.data)($gp)
+ 	lw	$25,%got_disp(.text)($gp)
+ 	jalr	$25
+ 
+    then the linker will resolve both relocations to .data and the program
+    will jump there rather than to .text.
+ 
+    We can work around this problem by giving names to local section symbols.
+    This is also what the MIPSpro tools do.  */
+ 
+ bfd_boolean
+ _bfd_mips_elf_name_local_section_symbols (bfd *abfd)
+ {
+   return SGI_COMPAT (abfd);
+ }
+ 
  /* Work over a section just before writing it out.  This routine is
     used by both the 32-bit and the 64-bit ABI.  FIXME: We recognize
     sections that need the SHF_MIPS_GPREL flag by name; there has to be
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: got-disp-1.s
URL: <https://sourceware.org/pipermail/binutils/attachments/20040208/97f841fc/attachment.ksh>
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: got-disp-2.s
URL: <https://sourceware.org/pipermail/binutils/attachments/20040208/97f841fc/attachment-0001.ksh>


More information about the Binutils mailing list