This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: a problem with ld options


Hi Chenyu,

 readelf try.o -r
 readelf try.out -r
 The first readelf works well, but the second exits with segment fault.


Well, that's at least two bugs. readelf shouldn't segfault, and ld -q
ought to work. :-(

Attached is a patch for the first bug. It fixes readelf so that it no longer assumes that the string table offset for dynamic relocs will be a valid offset into the dynamic string table. Instead it checks and prints a suitable error message if a corrupt index is found. I will be applying this patch shortly.


Cheers
  Nick

binutils/ChangeLog

2004-10-25 Nick Clifton <nickc@redhat.com>

	* readelf.c (dynamic_strings_length): New global variable.
	(VALID_DYNAMIC_NAME, GET_DYNAMIC_NAME): New macros for accessing
	strings in the dynamic string table.
	(process_section_headers): Initialise dynamic_strings_length.
	(process_dynamic_section): Likewise.
	(process_object): Reset dynamic_string_length when the buffer is freed.
	(dynamic_sections_mips_val): Use the new macros.
	(process_dynamic_section): Likewise.
	(process_version_sections): Likewise.
	(process_symbol_table): Likewise.
	(process_syminfo): Likewise.
	(process_mips_specific): Likewise.
	(dump_relocations): Add a new parameter 'strtablen' and use this
	to verify that string offset in a given reloc is valid.  Print a
	suitable error message otherwise.
	(process_relocs): Pass the new argument to dump_relocations.

Index: binutils/readelf.c
===================================================================
RCS file: /cvs/src/src/binutils/readelf.c,v
retrieving revision 1.258
diff -c -3 -p -r1.258 readelf.c
*** binutils/readelf.c	19 Oct 2004 19:30:33 -0000	1.258
--- binutils/readelf.c	25 Oct 2004 09:49:24 -0000
*************** unsigned long dynamic_addr;
*** 123,128 ****
--- 123,129 ----
  bfd_size_type dynamic_size;
  unsigned int dynamic_nent;
  char *dynamic_strings;
+ unsigned long dynamic_strings_length;
  char *string_table;
  unsigned long string_table_length;
  unsigned long num_dynamic_syms;
*************** static void (*byte_put) (unsigned char *
*** 254,260 ****
    (is_32bit_elf ? get_32bit_elf_symbols (file, section)	\
     : get_64bit_elf_symbols (file, section))
  
! 
  static void
  error (const char *message, ...)
  {
--- 255,265 ----
    (is_32bit_elf ? get_32bit_elf_symbols (file, section)	\
     : get_64bit_elf_symbols (file, section))
  
! #define VALID_DYNAMIC_NAME(offset)	((dynamic_strings != NULL) && (offset < dynamic_strings_length))
! /* GET_DYNAMIC_NAME asssumes that VALID_DYNAMIC_NAME has
!    already been called and verified that the string exists.  */
! #define GET_DYNAMIC_NAME(offset)	(dynamic_strings + offset)
! 
  static void
  error (const char *message, ...)
  {
*************** dump_relocations (FILE *file,
*** 863,868 ****
--- 868,874 ----
  		  Elf_Internal_Sym *symtab,
  		  unsigned long nsyms,
  		  char *strtab,
+ 		  unsigned long strtablen,
  		  int is_rela)
  {
    unsigned int i;
*************** dump_relocations (FILE *file,
*** 1250,1256 ****
  		  print_symbol (22, sec_name);
  		}
  	      else if (strtab == NULL)
! 		printf (_("<string table index %3ld>"), psym->st_name);
  	      else
  		print_symbol (22, strtab + psym->st_name);
  
--- 1256,1264 ----
  		  print_symbol (22, sec_name);
  		}
  	      else if (strtab == NULL)
! 		printf (_("<string table index: %3ld>"), psym->st_name);
! 	      else if (psym->st_name > strtablen)
! 		printf (_("<corrupt string table index: %3ld>"), psym->st_name);
  	      else
  		print_symbol (22, strtab + psym->st_name);
  
*************** process_section_headers (FILE *file)
*** 3718,3723 ****
--- 3726,3732 ----
  
  	  dynamic_strings = get_data (NULL, file, section->sh_offset,
  				      section->sh_size, _("dynamic strings"));
+ 	  dynamic_strings_length = section->sh_size;
  	}
        else if (section->sh_type == SHT_SYMTAB_SHNDX)
  	{
*************** process_relocs (FILE *file)
*** 4114,4120 ****
  				offset_from_vma (file, rel_offset, rel_size),
  				rel_size,
  				dynamic_symbols, num_dynamic_syms,
! 				dynamic_strings, is_rela);
  	    }
  	}
  
--- 4123,4129 ----
  				offset_from_vma (file, rel_offset, rel_size),
  				rel_size,
  				dynamic_symbols, num_dynamic_syms,
! 				dynamic_strings, dynamic_strings_length, is_rela);
  	    }
  	}
  
*************** process_relocs (FILE *file)
*** 4141,4150 ****
  	  if (rel_size)
  	    {
  	      Elf_Internal_Shdr *strsec;
- 	      Elf_Internal_Sym *symtab;
- 	      char *strtab;
  	      int is_rela;
- 	      unsigned long nsyms;
  
  	      printf (_("\nRelocation section "));
  
--- 4150,4156 ----
*************** process_relocs (FILE *file)
*** 4156,4168 ****
  	      printf (_(" at offset 0x%lx contains %lu entries:\n"),
  		 rel_offset, (unsigned long) (rel_size / section->sh_entsize));
  
! 	      symtab = NULL;
! 	      strtab = NULL;
! 	      nsyms = 0;
  	      if (section->sh_link)
  		{
  		  Elf_Internal_Shdr *symsec;
! 
  		  symsec = SECTION_HEADER (section->sh_link);
  		  nsyms = symsec->sh_size / symsec->sh_entsize;
  		  symtab = GET_ELF_SYMBOLS (file, symsec);
--- 4162,4177 ----
  	      printf (_(" at offset 0x%lx contains %lu entries:\n"),
  		 rel_offset, (unsigned long) (rel_size / section->sh_entsize));
  
! 	      is_rela = section->sh_type == SHT_RELA;
! 
  	      if (section->sh_link)
  		{
  		  Elf_Internal_Shdr *symsec;
! 		  Elf_Internal_Sym *symtab;
! 		  unsigned long nsyms;
! 		  unsigned long strtablen;
! 		  char *strtab = NULL;
! 		  
  		  symsec = SECTION_HEADER (section->sh_link);
  		  nsyms = symsec->sh_size / symsec->sh_entsize;
  		  symtab = GET_ELF_SYMBOLS (file, symsec);
*************** process_relocs (FILE *file)
*** 4174,4189 ****
  
  		  strtab = get_data (NULL, file, strsec->sh_offset,
  				     strsec->sh_size, _("string table"));
! 		}
! 	      is_rela = section->sh_type == SHT_RELA;
  
! 	      dump_relocations (file, rel_offset, rel_size,
! 				symtab, nsyms, strtab, is_rela);
! 
! 	      if (strtab)
! 		free (strtab);
! 	      if (symtab)
! 		free (symtab);
  
  	      found = 1;
  	    }
--- 4183,4199 ----
  
  		  strtab = get_data (NULL, file, strsec->sh_offset,
  				     strsec->sh_size, _("string table"));
! 		  strtablen = strtab == NULL ? 0 : strsec->sh_size;
  
! 		  dump_relocations (file, rel_offset, rel_size,
! 				    symtab, nsyms, strtab, strtablen, is_rela);
! 		  if (strtab)
! 		    free (strtab);
! 		  free (symtab);
! 		}
! 	      else
! 		dump_relocations (file, rel_offset, rel_size,
! 				  NULL, 0, NULL, 0, is_rela);
  
  	      found = 1;
  	    }
*************** dynamic_section_mips_val (Elf_Internal_D
*** 4648,4658 ****
        break;
  
      case DT_MIPS_IVERSION:
!       if (dynamic_strings != NULL)
! 	printf ("Interface Version: %s\n",
! 		dynamic_strings + entry->d_un.d_val);
        else
! 	printf ("%ld\n", (long) entry->d_un.d_ptr);
        break;
  
      case DT_MIPS_TIME_STAMP:
--- 4658,4667 ----
        break;
  
      case DT_MIPS_IVERSION:
!       if (VALID_DYNAMIC_NAME (entry->d_un.d_val))
! 	printf ("Interface Version: %s\n", GET_DYNAMIC_NAME (entry->d_un.d_val));
        else
! 	printf ("<corrupt: %ld>\n", (long) entry->d_un.d_ptr);
        break;
  
      case DT_MIPS_TIME_STAMP:
*************** process_dynamic_section (FILE *file)
*** 4995,5000 ****
--- 5004,5010 ----
  
  	  dynamic_strings = get_data (NULL, file, offset, str_tab_len,
  				      _("dynamic string table"));
+ 	  dynamic_strings_length = str_tab_len;
  	  break;
  	}
      }
*************** process_dynamic_section (FILE *file)
*** 5112,5119 ****
  		  break;
  		}
  
! 	      if (dynamic_strings)
! 		printf (": [%s]\n", dynamic_strings + entry->d_un.d_val);
  	      else
  		{
  		  printf (": ");
--- 5122,5129 ----
  		  break;
  		}
  
! 	      if (VALID_DYNAMIC_NAME (entry->d_un.d_val))
! 		printf (": [%s]\n", GET_DYNAMIC_NAME (entry->d_un.d_val));
  	      else
  		{
  		  printf (": ");
*************** process_dynamic_section (FILE *file)
*** 5295,5304 ****
  	    {
  	      char *name;
  
! 	      if (dynamic_strings == NULL)
! 		name = NULL;
  	      else
! 		name = dynamic_strings + entry->d_un.d_val;
  
  	      if (name)
  		{
--- 5305,5314 ----
  	    {
  	      char *name;
  
! 	      if (VALID_DYNAMIC_NAME (entry->d_un.d_val))
! 		name = GET_DYNAMIC_NAME (entry->d_un.d_val);
  	      else
! 		name = NULL;
  
  	      if (name)
  		{
*************** process_dynamic_section (FILE *file)
*** 5376,5386 ****
  	case DT_FINI_ARRAY:
  	  if (do_dynamic)
  	    {
! 	      if (dynamic_strings != NULL && entry->d_tag == DT_USED)
  		{
! 		  char *name;
! 
! 		  name = dynamic_strings + entry->d_un.d_val;
  
  		  if (*name)
  		    {
--- 5386,5395 ----
  	case DT_FINI_ARRAY:
  	  if (do_dynamic)
  	    {
! 	      if (entry->d_tag == DT_USED
! 		  && VALID_DYNAMIC_NAME (entry->d_un.d_val))
  		{
! 		  char *name = GET_DYNAMIC_NAME (entry->d_un.d_val);
  
  		  if (*name)
  		    {
*************** process_version_sections (FILE *file)
*** 5547,5554 ****
  		aux.vda_name = BYTE_GET (eaux->vda_name);
  		aux.vda_next = BYTE_GET (eaux->vda_next);
  
! 		if (dynamic_strings)
! 		  printf (_("Name: %s\n"), dynamic_strings + aux.vda_name);
  		else
  		  printf (_("Name index: %ld\n"), aux.vda_name);
  
--- 5556,5563 ----
  		aux.vda_name = BYTE_GET (eaux->vda_name);
  		aux.vda_next = BYTE_GET (eaux->vda_next);
  
! 		if (VALID_DYNAMIC_NAME (aux.vda_name))
! 		  printf (_("Name: %s\n"), GET_DYNAMIC_NAME (aux.vda_name));
  		else
  		  printf (_("Name index: %ld\n"), aux.vda_name);
  
*************** process_version_sections (FILE *file)
*** 5564,5572 ****
  		    aux.vda_name = BYTE_GET (eaux->vda_name);
  		    aux.vda_next = BYTE_GET (eaux->vda_next);
  
! 		    if (dynamic_strings)
  		      printf (_("  %#06x: Parent %d: %s\n"),
! 			      isum, j, dynamic_strings + aux.vda_name);
  		    else
  		      printf (_("  %#06x: Parent %d, name index: %ld\n"),
  			      isum, j, aux.vda_name);
--- 5573,5581 ----
  		    aux.vda_name = BYTE_GET (eaux->vda_name);
  		    aux.vda_next = BYTE_GET (eaux->vda_next);
  
! 		    if (VALID_DYNAMIC_NAME (aux.vda_name))
  		      printf (_("  %#06x: Parent %d: %s\n"),
! 			      isum, j, GET_DYNAMIC_NAME (aux.vda_name));
  		    else
  		      printf (_("  %#06x: Parent %d, name index: %ld\n"),
  			      isum, j, aux.vda_name);
*************** process_version_sections (FILE *file)
*** 5621,5628 ****
  
  		printf (_("  %#06x: Version: %d"), idx, ent.vn_version);
  
! 		if (dynamic_strings)
! 		  printf (_("  File: %s"), dynamic_strings + ent.vn_file);
  		else
  		  printf (_("  File: %lx"), ent.vn_file);
  
--- 5630,5637 ----
  
  		printf (_("  %#06x: Version: %d"), idx, ent.vn_version);
  
! 		if (VALID_DYNAMIC_NAME (ent.vn_file))
! 		  printf (_("  File: %s"), GET_DYNAMIC_NAME (ent.vn_file));
  		else
  		  printf (_("  File: %lx"), ent.vn_file);
  
*************** process_version_sections (FILE *file)
*** 5643,5651 ****
  		    aux.vna_name  = BYTE_GET (eaux->vna_name);
  		    aux.vna_next  = BYTE_GET (eaux->vna_next);
  
! 		    if (dynamic_strings)
  		      printf (_("  %#06x:   Name: %s"),
! 			      isum, dynamic_strings + aux.vna_name);
  		    else
  		      printf (_("  %#06x:   Name index: %lx"),
  			      isum, aux.vna_name);
--- 5652,5660 ----
  		    aux.vna_name  = BYTE_GET (eaux->vna_name);
  		    aux.vna_next  = BYTE_GET (eaux->vna_next);
  
! 		    if (VALID_DYNAMIC_NAME (aux.vna_name))
  		      printf (_("  %#06x:   Name: %s"),
! 			      isum, GET_DYNAMIC_NAME (aux.vna_name));
  		    else
  		      printf (_("  %#06x:   Name index: %lx"),
  			      isum, aux.vna_name);
*************** process_symbol_table (FILE *file)
*** 6105,6111 ****
  	      printf (" %6s",  get_symbol_binding (ELF_ST_BIND (psym->st_info)));
  	      printf (" %3s",  get_symbol_visibility (ELF_ST_VISIBILITY (psym->st_other)));
  	      printf (" %3.3s ", get_symbol_index_type (psym->st_shndx));
! 	      print_symbol (25, dynamic_strings + psym->st_name);
  	      putchar ('\n');
  	    }
  	}
--- 6114,6123 ----
  	      printf (" %6s",  get_symbol_binding (ELF_ST_BIND (psym->st_info)));
  	      printf (" %3s",  get_symbol_visibility (ELF_ST_VISIBILITY (psym->st_other)));
  	      printf (" %3.3s ", get_symbol_index_type (psym->st_shndx));
! 	      if (VALID_DYNAMIC_NAME (psym->st_name))
! 		print_symbol (25, GET_DYNAMIC_NAME (psym->st_name));
! 	      else
! 		printf (" <corrupt: %14ld>", psym->st_name);
  	      putchar ('\n');
  	    }
  	}
*************** process_syminfo (FILE *file ATTRIBUTE_UN
*** 6404,6410 ****
        unsigned short int flags = dynamic_syminfo[i].si_flags;
  
        printf ("%4d: ", i);
!       print_symbol (30, dynamic_strings + dynamic_symbols[i].st_name);
        putchar (' ');
  
        switch (dynamic_syminfo[i].si_boundto)
--- 6416,6425 ----
        unsigned short int flags = dynamic_syminfo[i].si_flags;
  
        printf ("%4d: ", i);
!       if (VALID_DYNAMIC_NAME (dynamic_symbols[i].st_name))
! 	print_symbol (30, GET_DYNAMIC_NAME (dynamic_symbols[i].st_name));
!       else
! 	printf ("<corrupt: %19ld>", dynamic_symbols[i].st_name);
        putchar (' ');
  
        switch (dynamic_syminfo[i].si_boundto)
*************** process_syminfo (FILE *file ATTRIBUTE_UN
*** 6417,6428 ****
  	  break;
  	default:
  	  if (dynamic_syminfo[i].si_boundto > 0
! 	      && dynamic_syminfo[i].si_boundto < dynamic_nent)
  	    {
! 	      print_symbol (10,
! 			    dynamic_strings
! 			    + (dynamic_section
! 			       [dynamic_syminfo[i].si_boundto].d_un.d_val));
  	      putchar (' ' );
  	    }
  	  else
--- 6432,6441 ----
  	  break;
  	default:
  	  if (dynamic_syminfo[i].si_boundto > 0
! 	      && dynamic_syminfo[i].si_boundto < dynamic_nent
! 	      && VALID_DYNAMIC_NAME (dynamic_section[dynamic_syminfo[i].si_boundto].d_un.d_val))
  	    {
! 	      print_symbol (10, GET_DYNAMIC_NAME (dynamic_section[dynamic_syminfo[i].si_boundto].d_un.d_val));
  	      putchar (' ' );
  	    }
  	  else
*************** process_mips_specific (FILE *file)
*** 9951,9957 ****
  		       tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
  
  	      printf ("%3lu: ", (unsigned long) cnt);
! 	      print_symbol (20, dynamic_strings + liblist.l_name);
  	      printf (" %s %#10lx %-7ld", timebuf, liblist.l_checksum,
  		      liblist.l_version);
  
--- 9964,9973 ----
  		       tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
  
  	      printf ("%3lu: ", (unsigned long) cnt);
! 	      if (VALID_DYNAMIC_NAME (liblist.l_name))
! 		print_symbol (20, GET_DYNAMIC_NAME (liblist.l_name));
! 	      else
! 		printf ("<corrupt: %9ld>", liblist.l_name);
  	      printf (" %s %#10lx %-7ld", timebuf, liblist.l_checksum,
  		      liblist.l_version);
  
*************** process_mips_specific (FILE *file)
*** 10251,10257 ****
  	  printf ("%5lu: %8lu  ", (unsigned long) cnt, iconf[cnt]);
  	  print_vma (psym->st_value, FULL_HEX);
  	  putchar (' ');
! 	  print_symbol (25, dynamic_strings + psym->st_name);
  	  putchar ('\n');
  	}
  
--- 10267,10276 ----
  	  printf ("%5lu: %8lu  ", (unsigned long) cnt, iconf[cnt]);
  	  print_vma (psym->st_value, FULL_HEX);
  	  putchar (' ');
! 	  if (VALID_DYNAMIC_NAME (psym->st_name))
! 	    print_symbol (25, GET_DYNAMIC_NAME (psym->st_name));
! 	  else
! 	    printf ("<corrupt: %14ld>", psym->st_name);
  	  putchar ('\n');
  	}
  
*************** process_object (char *file_name, FILE *f
*** 10780,10785 ****
--- 10799,10805 ----
      {
        free (dynamic_strings);
        dynamic_strings = NULL;
+       dynamic_strings_length = 0;
      }
  
    if (dynamic_symbols)

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]