sparc .got fill failure

Richard Henderson rth@redhat.com
Sun Mar 31 01:29:00 GMT 2002


On Sat, Mar 30, 2002 at 06:19:47PM -0800, David S. Miller wrote:
>    > 	Sure enough, the resulting libgcc/_bb.oS, due to
>    > 	this hidden transformation, lacks the GOT10/GOT22 relocs for
>    > 	__bb_exit_func and thus it does not get resolved at link
>    > 	time because the linker doesn't see it anywhere.

Actually, the GOT10/GOT22 relocs are still there, but the linker
failed to actually fill in the .got entry.

The following appears to fix the problem.  I'm currently running
a combined binutils+gcc bootstrap on (32-bit) solaris, but it'd
be good if one of you could build glibc on linux, as that will
stress things a bit more...


r~


	* elf32-sparc.c (WILL_CALL_FINISH_DYNAMIC_SYMBOL): New.
	(elf32_sparc_relocate_section): Use it to figure out when to 
	initialize .got entries.
	* elf64-sparc.c: Similarly.

Index: elf32-sparc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-sparc.c,v
retrieving revision 1.36
diff -c -p -d -r1.36 elf32-sparc.c
*** elf32-sparc.c	2002/02/19 12:40:27	1.36
--- elf32-sparc.c	2002/03/31 09:23:21
*************** elf32_sparc_relax_section (abfd, section
*** 1084,1089 ****
--- 1084,1100 ----
    return true;
  }
  
+ /* This is the condition under which finish_dynamic_symbol will be called
+    from elflink.h.  If elflink.h doesn't call our finish_dynamic_symbol
+    routine, we'll need to do something about initializing any .plt and .got
+    entries in relocate_section.  */
+ #define WILL_CALL_FINISH_DYNAMIC_SYMBOL(DYN, INFO, H)			\
+   ((DYN)								\
+    && ((INFO)->shared							\
+        || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)	\
+    && ((H)->dynindx != -1						\
+        || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0))
+ 
  /* Relocate a SPARC ELF section.  */
  
  static boolean
*************** elf32_sparc_relocate_section (output_bfd
*** 1133,1141 ****
        struct elf_link_hash_entry *h;
        Elf_Internal_Sym *sym;
        asection *sec;
!       bfd_vma relocation;
        bfd_reloc_status_type r;
        boolean is_plt = false;
  
        r_type = ELF32_R_TYPE (rel->r_info);
  
--- 1144,1153 ----
        struct elf_link_hash_entry *h;
        Elf_Internal_Sym *sym;
        asection *sec;
!       bfd_vma relocation, off;
        bfd_reloc_status_type r;
        boolean is_plt = false;
+       boolean unresolved_reloc;
  
        r_type = ELF32_R_TYPE (rel->r_info);
  
*************** elf32_sparc_relocate_section (output_bfd
*** 1175,1180 ****
--- 1187,1193 ----
        h = NULL;
        sym = NULL;
        sec = NULL;
+       unresolved_reloc = false;
        if (r_symndx < symtab_hdr->sh_info)
  	{
  	  sym = local_syms + r_symndx;
*************** elf32_sparc_relocate_section (output_bfd
*** 1187,1257 ****
  	  while (h->root.type == bfd_link_hash_indirect
  		 || h->root.type == bfd_link_hash_warning)
  	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
  	  if (h->root.type == bfd_link_hash_defined
  	      || h->root.type == bfd_link_hash_defweak)
  	    {
  	      sec = h->root.u.def.section;
! 	      if (((r_type == R_SPARC_WPLT30
! 		    || r_type == R_SPARC_PLT32)
! 		   && h->plt.offset != (bfd_vma) -1)
! 		  || ((r_type == R_SPARC_GOT10
! 		       || r_type == R_SPARC_GOT13
! 		       || r_type == R_SPARC_GOT22)
! 		      && elf_hash_table (info)->dynamic_sections_created
! 		      && (! info->shared
! 			  || (! info->symbolic && h->dynindx != -1)
! 			  || (h->elf_link_hash_flags
! 			      & ELF_LINK_HASH_DEF_REGULAR) == 0))
! 		  || (info->shared
! 		      && ((! info->symbolic && h->dynindx != -1)
! 			  || (h->elf_link_hash_flags
! 			      & ELF_LINK_HASH_DEF_REGULAR) == 0)
! 		      && (r_type == R_SPARC_8
! 			  || r_type == R_SPARC_16
! 			  || r_type == R_SPARC_32
! 			  || r_type == R_SPARC_DISP8
! 			  || r_type == R_SPARC_DISP16
! 			  || r_type == R_SPARC_DISP32
! 			  || r_type == R_SPARC_WDISP30
! 			  || r_type == R_SPARC_WDISP22
! 			  || r_type == R_SPARC_WDISP19
! 			  || r_type == R_SPARC_WDISP16
! 			  || r_type == R_SPARC_HI22
! 			  || r_type == R_SPARC_22
! 			  || r_type == R_SPARC_13
! 			  || r_type == R_SPARC_LO10
! 			  || r_type == R_SPARC_UA16
! 			  || r_type == R_SPARC_UA32
! 			  || ((r_type == R_SPARC_PC10
! 			       || r_type == R_SPARC_PC22)
! 			      && strcmp (h->root.root.string,
! 					 "_GLOBAL_OFFSET_TABLE_") != 0))
! 		      && ((input_section->flags & SEC_ALLOC) != 0
! 			  /* DWARF will emit R_SPARC_32 relocations in its
! 			     sections against symbols defined externally
! 			     in shared libraries.  We can't do anything
! 			     with them here.  */
! 			  || ((input_section->flags & SEC_DEBUGGING) != 0
! 			      && (h->elf_link_hash_flags
! 				  & ELF_LINK_HASH_DEF_DYNAMIC) != 0))))
! 		{
! 		  /* In these cases, we don't need the relocation
!                      value.  We check specially because in some
!                      obscure cases sec->output_section will be NULL.  */
! 		  relocation = 0;
! 		}
  	      else
  		relocation = (h->root.u.def.value
  			      + sec->output_section->vma
  			      + sec->output_offset);
  	    }
  	  else if (h->root.type == bfd_link_hash_undefweak)
! 	    relocation = 0;
  	  else if (info->shared
  		   && (!info->symbolic || info->allow_shlib_undefined)
  		   && !info->no_undefined
  		   && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
! 	    relocation = 0;
  	  else
  	    {
  	      if (! ((*info->callbacks->undefined_symbol)
--- 1200,1229 ----
  	  while (h->root.type == bfd_link_hash_indirect
  		 || h->root.type == bfd_link_hash_warning)
  	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+ 
+ 	  relocation = 0;
  	  if (h->root.type == bfd_link_hash_defined
  	      || h->root.type == bfd_link_hash_defweak)
  	    {
  	      sec = h->root.u.def.section;
! 	      if (sec->output_section == NULL)
! 		 /* Set a flag that will be cleared later if we find a
! 		   relocation value for this symbol.  output_section
! 		   is typically NULL for symbols satisfied by a shared
! 		   library.  */
! 		unresolved_reloc = true;
  	      else
  		relocation = (h->root.u.def.value
  			      + sec->output_section->vma
  			      + sec->output_offset);
  	    }
  	  else if (h->root.type == bfd_link_hash_undefweak)
! 	    ;
  	  else if (info->shared
  		   && (!info->symbolic || info->allow_shlib_undefined)
  		   && !info->no_undefined
  		   && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
! 	    ;
  	  else
  	    {
  	      if (! ((*info->callbacks->undefined_symbol)
*************** elf32_sparc_relocate_section (output_bfd
*** 1260,1266 ****
  		      (!info->shared || info->no_undefined
  		       || ELF_ST_VISIBILITY (h->other)))))
  		return false;
- 	      relocation = 0;
  	    }
  	}
  
--- 1232,1237 ----
*************** elf32_sparc_relocate_section (output_bfd
*** 1279,1292 ****
  
  	  if (h != NULL)
  	    {
! 	      bfd_vma off;
  
  	      off = h->got.offset;
  	      BFD_ASSERT (off != (bfd_vma) -1);
  
! 	      if (! elf_hash_table (info)->dynamic_sections_created
  		  || (info->shared
! 		      && (info->symbolic || h->dynindx == -1)
  		      && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)))
  		{
  		  /* This is actually a static link, or it is a
--- 1250,1266 ----
  
  	  if (h != NULL)
  	    {
! 	      boolean dyn;
  
  	      off = h->got.offset;
  	      BFD_ASSERT (off != (bfd_vma) -1);
+ 	      dyn = elf_hash_table (info)->dynamic_sections_created;
  
! 	      if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h)
  		  || (info->shared
! 		      && (info->symbolic
! 			  || h->dynindx == -1
! 			  || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL))
  		      && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)))
  		{
  		  /* This is actually a static link, or it is a
*************** elf32_sparc_relocate_section (output_bfd
*** 1310,1322 ****
  		      h->got.offset |= 1;
  		    }
  		}
! 
! 	      relocation = sgot->output_offset + off - got_base;
  	    }
  	  else
  	    {
- 	      bfd_vma off;
- 
  	      BFD_ASSERT (local_got_offsets != NULL
  			  && local_got_offsets[r_symndx] != (bfd_vma) -1);
  
--- 1284,1294 ----
  		      h->got.offset |= 1;
  		    }
  		}
! 	      else
! 		unresolved_reloc = false;
  	    }
  	  else
  	    {
  	      BFD_ASSERT (local_got_offsets != NULL
  			  && local_got_offsets[r_symndx] != (bfd_vma) -1);
  
*************** elf32_sparc_relocate_section (output_bfd
*** 1355,1364 ****
  
  		  local_got_offsets[r_symndx] |= 1;
  		}
- 
- 	      relocation = sgot->output_offset + off - got_base;
  	    }
! 
  	  break;
  
  	case R_SPARC_PLT32:
--- 1327,1334 ----
  
  		  local_got_offsets[r_symndx] |= 1;
  		}
  	    }
! 	  relocation = sgot->output_offset + off - got_base;
  	  break;
  
  	case R_SPARC_PLT32:
*************** elf32_sparc_relocate_section (output_bfd
*** 1396,1401 ****
--- 1366,1372 ----
  	  relocation = (splt->output_section->vma
  			+ splt->output_offset
  			+ h->plt.offset);
+ 	  unresolved_reloc = false;
  	  if (r_type == R_SPARC_PLT32)
  	    {
  	      r_type = R_SPARC_32;
*************** elf32_sparc_relocate_section (output_bfd
*** 1581,1586 ****
--- 1552,1569 ----
  	default:
  	  break;
  	}
+ 
+       /* ??? Copied from elf32-i386.c, debugging section check and all.  */
+       if (unresolved_reloc
+ 	  && !(info->shared
+ 	       && (input_section->flags & SEC_DEBUGGING) != 0
+ 	       && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0))
+ 	(*_bfd_error_handler)
+ 	  (_("%s(%s+0x%lx): unresolvable relocation against symbol `%s'"),
+ 	   bfd_archive_filename (input_bfd),
+ 	   bfd_get_section_name (input_bfd, input_section),
+ 	   (long) rel->r_offset,
+ 	   h->root.root.string);
  
        r = bfd_reloc_continue;
        if (r_type == R_SPARC_WDISP16)
Index: elf64-sparc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-sparc.c,v
retrieving revision 1.49
diff -c -p -d -r1.49 elf64-sparc.c
*** elf64-sparc.c	2002/02/19 12:40:28	1.49
--- elf64-sparc.c	2002/03/31 09:23:22
*************** sparc64_elf_relax_section (abfd, section
*** 1881,1886 ****
--- 1881,1897 ----
    return true;
  }
  
+ /* This is the condition under which finish_dynamic_symbol will be called
+    from elflink.h.  If elflink.h doesn't call our finish_dynamic_symbol
+    routine, we'll need to do something about initializing any .plt and
+    .got entries in relocate_section.  */
+ #define WILL_CALL_FINISH_DYNAMIC_SYMBOL(DYN, INFO, H)			\
+   ((DYN)								\
+    && ((INFO)->shared							\
+        || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)	\
+    && ((H)->dynindx != -1						\
+        || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0))
+ 
  /* Relocate a SPARC64 ELF section.  */
  
  static boolean
*************** sparc64_elf_relocate_section (output_bfd
*** 1928,1936 ****
        struct elf_link_hash_entry *h;
        Elf_Internal_Sym *sym;
        asection *sec;
!       bfd_vma relocation;
        bfd_reloc_status_type r;
        boolean is_plt = false;
  
        r_type = ELF64_R_TYPE_ID (rel->r_info);
        if (r_type < 0 || r_type >= (int) R_SPARC_max_std)
--- 1939,1948 ----
        struct elf_link_hash_entry *h;
        Elf_Internal_Sym *sym;
        asection *sec;
!       bfd_vma relocation, off;
        bfd_reloc_status_type r;
        boolean is_plt = false;
+       boolean unresolved_reloc;
  
        r_type = ELF64_R_TYPE_ID (rel->r_info);
        if (r_type < 0 || r_type >= (int) R_SPARC_max_std)
*************** sparc64_elf_relocate_section (output_bfd
*** 1965,1970 ****
--- 1977,1983 ----
        h = NULL;
        sym = NULL;
        sec = NULL;
+       unresolved_reloc = false;
        if (r_symndx < symtab_hdr->sh_info)
  	{
  	  sym = local_syms + r_symndx;
*************** sparc64_elf_relocate_section (output_bfd
*** 1977,2092 ****
  	  while (h->root.type == bfd_link_hash_indirect
  		 || h->root.type == bfd_link_hash_warning)
  	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
  	  if (h->root.type == bfd_link_hash_defined
  	      || h->root.type == bfd_link_hash_defweak)
  	    {
- 	      boolean skip_it = false;
  	      sec = h->root.u.def.section;
! 
! 	      switch (r_type)
! 		{
! 		case R_SPARC_WPLT30:
! 		case R_SPARC_PLT32:
! 		case R_SPARC_HIPLT22:
! 		case R_SPARC_LOPLT10:
! 		case R_SPARC_PCPLT32:
! 		case R_SPARC_PCPLT22:
! 		case R_SPARC_PCPLT10:
! 		case R_SPARC_PLT64:
! 		  if (h->plt.offset != (bfd_vma) -1)
! 		    skip_it = true;
! 		  break;
! 
! 		case R_SPARC_GOT10:
! 		case R_SPARC_GOT13:
! 		case R_SPARC_GOT22:
! 		  if (elf_hash_table(info)->dynamic_sections_created
! 		      && (!info->shared
! 			  || (!info->symbolic && h->dynindx != -1)
! 			  || !(h->elf_link_hash_flags
! 			       & ELF_LINK_HASH_DEF_REGULAR)))
! 		    skip_it = true;
! 		  break;
! 
! 		case R_SPARC_PC10:
! 		case R_SPARC_PC22:
! 		case R_SPARC_PC_HH22:
! 		case R_SPARC_PC_HM10:
! 		case R_SPARC_PC_LM22:
! 		  if (!strcmp(h->root.root.string, "_GLOBAL_OFFSET_TABLE_"))
! 		    break;
! 		  /* FALLTHRU */
! 
! 		case R_SPARC_8:
! 		case R_SPARC_16:
! 		case R_SPARC_32:
! 		case R_SPARC_DISP8:
! 		case R_SPARC_DISP16:
! 		case R_SPARC_DISP32:
! 		case R_SPARC_WDISP30:
! 		case R_SPARC_WDISP22:
! 		case R_SPARC_HI22:
! 		case R_SPARC_22:
! 		case R_SPARC_13:
! 		case R_SPARC_LO10:
! 		case R_SPARC_UA32:
! 		case R_SPARC_10:
! 		case R_SPARC_11:
! 		case R_SPARC_64:
! 		case R_SPARC_OLO10:
! 		case R_SPARC_HH22:
! 		case R_SPARC_HM10:
! 		case R_SPARC_LM22:
! 		case R_SPARC_WDISP19:
! 		case R_SPARC_WDISP16:
! 		case R_SPARC_7:
! 		case R_SPARC_5:
! 		case R_SPARC_6:
! 		case R_SPARC_DISP64:
! 		case R_SPARC_HIX22:
! 		case R_SPARC_LOX10:
! 		case R_SPARC_H44:
! 		case R_SPARC_M44:
! 		case R_SPARC_L44:
! 		case R_SPARC_UA64:
! 		case R_SPARC_UA16:
! 		  if (info->shared
! 		      && ((!info->symbolic && h->dynindx != -1)
! 			  || !(h->elf_link_hash_flags
! 			       & ELF_LINK_HASH_DEF_REGULAR))
! 		      && ((input_section->flags & SEC_ALLOC) != 0
! 			  /* DWARF will emit R_SPARC_{32,64} relocations in
! 			     its sections against symbols defined externally
! 			     in shared libraries.  We can't do anything
! 			     with them here.  */
! 			  || ((input_section->flags & SEC_DEBUGGING) != 0
! 			      && (h->elf_link_hash_flags
! 				  & ELF_LINK_HASH_DEF_DYNAMIC) != 0)))
! 		    skip_it = true;
! 		  break;
! 		}
! 
! 	      if (skip_it)
! 		{
! 		  /* In these cases, we don't need the relocation
!                      value.  We check specially because in some
!                      obscure cases sec->output_section will be NULL.  */
! 		  relocation = 0;
! 		}
  	      else
! 		{
! 		  relocation = (h->root.u.def.value
! 				+ sec->output_section->vma
! 				+ sec->output_offset);
! 		}
  	    }
  	  else if (h->root.type == bfd_link_hash_undefweak)
! 	    relocation = 0;
  	  else if (info->shared
  		   && (!info->symbolic || info->allow_shlib_undefined)
  		   && !info->no_undefined
  		   && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
! 	    relocation = 0;
  	  else
  	    {
  	      if (! ((*info->callbacks->undefined_symbol)
--- 1990,2019 ----
  	  while (h->root.type == bfd_link_hash_indirect
  		 || h->root.type == bfd_link_hash_warning)
  	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+ 
+ 	  relocation = 0;
  	  if (h->root.type == bfd_link_hash_defined
  	      || h->root.type == bfd_link_hash_defweak)
  	    {
  	      sec = h->root.u.def.section;
! 	      if (sec->output_section == NULL)
! 		/* Set a flag that will be cleared later if we find a
! 		   relocation value for this symbol.  output_section
! 		   is typically NULL for symbols satisfied by a shared
! 		   library.  */
! 		unresolved_reloc = true;
  	      else
! 		relocation = (h->root.u.def.value
! 			      + sec->output_section->vma
! 			      + sec->output_offset);
  	    }
  	  else if (h->root.type == bfd_link_hash_undefweak)
! 	    ;
  	  else if (info->shared
  		   && (!info->symbolic || info->allow_shlib_undefined)
  		   && !info->no_undefined
  		   && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
! 	    ;
  	  else
  	    {
  	      if (! ((*info->callbacks->undefined_symbol)
*************** sparc64_elf_relocate_section (output_bfd
*** 2107,2113 ****
  	    }
  	}
  
! do_dynreloc:
        /* When generating a shared object, these relocations are copied
  	 into the output file to be resolved at run time.  */
        if (info->shared && r_symndx != 0 && (input_section->flags & SEC_ALLOC))
--- 2034,2040 ----
  	    }
  	}
  
!  do_dynreloc:
        /* When generating a shared object, these relocations are copied
  	 into the output file to be resolved at run time.  */
        if (info->shared && r_symndx != 0 && (input_section->flags & SEC_ALLOC))
*************** do_dynreloc:
*** 2326,2339 ****
  
  	  if (h != NULL)
  	    {
! 	      bfd_vma off = h->got.offset;
  	      BFD_ASSERT (off != (bfd_vma) -1);
  
! 	      if (! elf_hash_table (info)->dynamic_sections_created
  		  || (info->shared
! 		      && (info->symbolic || h->dynindx == -1)
! 		      && (h->elf_link_hash_flags
! 			  & ELF_LINK_HASH_DEF_REGULAR)))
  		{
  		  /* This is actually a static link, or it is a -Bsymbolic
  		     link and the symbol is defined locally, or the symbol
--- 2253,2270 ----
  
  	  if (h != NULL)
  	    {
! 	      boolean dyn;
! 
! 	      off = h->got.offset;
  	      BFD_ASSERT (off != (bfd_vma) -1);
+ 	      dyn = elf_hash_table (info)->dynamic_sections_created;
  
! 	      if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h)
  		  || (info->shared
! 		      && (info->symbolic
! 			  || h->dynindx == -1
! 			  || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL))
! 		      && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)))
  		{
  		  /* This is actually a static link, or it is a -Bsymbolic
  		     link and the symbol is defined locally, or the symbol
*************** do_dynreloc:
*** 2356,2367 ****
  		      h->got.offset |= 1;
  		    }
  		}
! 	      relocation = sgot->output_offset + off - got_base;
  	    }
  	  else
  	    {
- 	      bfd_vma off;
- 
  	      BFD_ASSERT (local_got_offsets != NULL);
  	      off = local_got_offsets[r_symndx];
  	      BFD_ASSERT (off != (bfd_vma) -1);
--- 2287,2297 ----
  		      h->got.offset |= 1;
  		    }
  		}
! 	      else
! 		unresolved_reloc = false;
  	    }
  	  else
  	    {
  	      BFD_ASSERT (local_got_offsets != NULL);
  	      off = local_got_offsets[r_symndx];
  	      BFD_ASSERT (off != (bfd_vma) -1);
*************** do_dynreloc:
*** 2407,2414 ****
  		  else
  		    bfd_put_64 (output_bfd, relocation, sgot->contents + off);
  		}
- 	      relocation = sgot->output_offset + off - got_base;
  	    }
  	  goto do_default;
  
  	case R_SPARC_WPLT30:
--- 2337,2344 ----
  		  else
  		    bfd_put_64 (output_bfd, relocation, sgot->contents + off);
  		}
  	    }
+ 	  relocation = sgot->output_offset + off - got_base;
  	  goto do_default;
  
  	case R_SPARC_WPLT30:
*************** do_dynreloc:
*** 2440,2445 ****
--- 2370,2376 ----
  	  relocation = (splt->output_section->vma
  			+ splt->output_offset
  			+ sparc64_elf_plt_entry_offset (h->plt.offset));
+ 	  unresolved_reloc = false;
  	  if (r_type == R_SPARC_WPLT30)
  	    goto do_wplt30;
  	  if (r_type == R_SPARC_PLT32 || r_type == R_SPARC_PLT64)
*************** do_dynreloc:
*** 2622,2627 ****
--- 2553,2569 ----
  					relocation, rel->r_addend);
  	  break;
  	}
+ 
+       if (unresolved_reloc
+ 	  && !(info->shared
+ 	       && (input_section->flags & SEC_DEBUGGING) != 0
+ 	       && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0))
+ 	(*_bfd_error_handler)
+ 	  (_("%s(%s+0x%lx): unresolvable relocation against symbol `%s'"),
+ 	   bfd_archive_filename (input_bfd),
+ 	   bfd_get_section_name (input_bfd, input_section),
+ 	   (long) rel->r_offset,
+ 	   h->root.root.string);
  
        switch (r)
  	{



More information about the Binutils mailing list