char   nb [4]; char   nc [4];
unsigned char   nb [4]; unsigned char   nc [4];
process_symbol_table (file)     FILE * file;{  Elf32_Internal_Shdr *   section;  char   nb [4];  char   nc [4];  int    nbuckets = 0;  int    nchains = 0;  int *  buckets = NULL;  int *  chains = NULL;  if (! do_syms && !do_histogram)    return 1;  if (dynamic_info[DT_HASH] && ((do_using_dynamic && dynamic_strings != NULL)				|| do_histogram))    {      if (fseek (file, dynamic_info[DT_HASH] - loadaddr, SEEK_SET))	{	  error (_("Unable to seek to start of dynamic information"));	  return 0;	}      if (fread (nb, sizeof (nb), 1, file) != 1)	{	  error (_("Failed to read in number of buckets\n"));	  return 0;	}      if (fread (nc, sizeof (nc), 1, file) != 1)	{	  error (_("Failed to read in number of chains\n"));	  return 0;	}      nbuckets = byte_get (nb, 4);      nchains  = byte_get (nc, 4);      buckets = get_dynamic_data (file, nbuckets);      chains  = get_dynamic_data (file, nchains);      if (buckets == NULL || chains == NULL)	return 0;    }  if (do_syms      && dynamic_info[DT_HASH] && do_using_dynamic && dynamic_strings != NULL)    {      int    hn;      int    si;      printf (_("\nSymbol table for image:\n"));      if (is_32bit_elf)	printf (_("  Num Buc:    Value  Size   Type   Bind Vis      Ndx Name\n"));      else	printf (_("  Num Buc:    Value          Size   Type   Bind Vis      Ndx Name\n"));      for (hn = 0; hn < nbuckets; hn++)	{	  if (! buckets [hn])	    continue;	  for (si = buckets [hn]; si < nchains && si > 0; si = chains [si])	    {	      Elf_Internal_Sym * psym;	      psym = dynamic_symbols + si;	      printf ("  %3d %3d: ", si, hn);	      print_vma (psym->st_value, LONG_HEX);	      putchar (' ' );	      print_vma (psym->st_size, DEC_5);		      	      printf ("  %6s", get_symbol_type (ELF_ST_TYPE (psym->st_info)));	      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));	      printf (" %s\n", dynamic_strings + psym->st_name);	    }	}    }  else if (do_syms && !do_using_dynamic)    {      unsigned int     i;      for (i = 0, section = section_headers;	   i < elf_header.e_shnum;	   i++, section++)	{	  unsigned int          si;	  char *                strtab;	  Elf_Internal_Sym *    symtab;	  Elf_Internal_Sym *    psym;	  if (   section->sh_type != SHT_SYMTAB	      && section->sh_type != SHT_DYNSYM)	    continue;	  printf (_("\nSymbol table '%s' contains %lu entries:\n"),		  SECTION_NAME (section),		  (unsigned long) (section->sh_size / section->sh_entsize));	  if (is_32bit_elf)	    printf (_("   Num:    Value  Size Type    Bind   Vis      Ndx Name\n"));	  else	    printf (_("   Num:    Value          Size Type    Bind   Vis      Ndx Name\n"));	  symtab = GET_ELF_SYMBOLS (file, section->sh_offset,				    section->sh_size / section->sh_entsize);	  if (symtab == NULL)	    continue;	  if (section->sh_link == elf_header.e_shstrndx)	    strtab = string_table;	  else	    {	      Elf32_Internal_Shdr * string_sec;	      string_sec = section_headers + section->sh_link;	      GET_DATA_ALLOC (string_sec->sh_offset, string_sec->sh_size,			      strtab, char *, "string table");	    }	  for (si = 0, psym = symtab;	       si < section->sh_size / section->sh_entsize;	       si ++, psym ++)	    {	      printf ("%6d: ", si);	      print_vma (psym->st_value, LONG_HEX);	      putchar (' ');	      print_vma (psym->st_size, DEC_5);	      printf (" %-7s", get_symbol_type (ELF_ST_TYPE (psym->st_info)));	      printf (" %-6s", get_symbol_binding (ELF_ST_BIND (psym->st_info)));	      printf (" %-3s", get_symbol_visibility (ELF_ST_VISIBILITY (psym->st_other)));	      printf (" %4s", get_symbol_index_type (psym->st_shndx));	      printf (" %s", strtab + psym->st_name);	      if (section->sh_type == SHT_DYNSYM &&		  version_info [DT_VERSIONTAGIDX (DT_VERSYM)] != 0)		{		  unsigned char   data[2];		  unsigned short  vers_data;		  unsigned long   offset;		  int             is_nobits;		  int             check_def;		  offset = version_info [DT_VERSIONTAGIDX (DT_VERSYM)]		    - loadaddr;		  GET_DATA (offset + si * sizeof (vers_data), data,			    "version data");		  vers_data = byte_get (data, 2);		  is_nobits = psym->st_shndx < SHN_LORESERVE ?		    (section_headers [psym->st_shndx].sh_type == SHT_NOBITS)		    : 0;		  check_def = (psym->st_shndx != SHN_UNDEF);		  if ((vers_data & 0x8000) || vers_data > 1)		    {		      if (is_nobits || ! check_def)			{			  Elf_External_Verneed  evn;			  Elf_Internal_Verneed  ivn;			  Elf_Internal_Vernaux  ivna;			  /* We must test both.  */			  offset = version_info			    [DT_VERSIONTAGIDX (DT_VERNEED)] - loadaddr;			  do			    {			      unsigned long  vna_off;			      GET_DATA (offset, evn, "version need");			      ivn.vn_aux  = BYTE_GET (evn.vn_aux);			      ivn.vn_next = BYTE_GET (evn.vn_next);			      vna_off = offset + ivn.vn_aux;			      do				{				  Elf_External_Vernaux  evna;				  GET_DATA (vna_off, evna,					    "version need aux (3)");				  ivna.vna_other = BYTE_GET (evna.vna_other);				  ivna.vna_next  = BYTE_GET (evna.vna_next);				  ivna.vna_name  = BYTE_GET (evna.vna_name);				  vna_off += ivna.vna_next;				}			      while (ivna.vna_other != vers_data				     && ivna.vna_next != 0);			      if (ivna.vna_other == vers_data)				break;			      offset += ivn.vn_next;			    }			  while (ivn.vn_next != 0);			  if (ivna.vna_other == vers_data)			    {			      printf ("@%s (%d)",				      strtab + ivna.vna_name, ivna.vna_other);			      check_def = 0;			    }			  else if (! is_nobits)			    error (_("bad dynamic symbol"));			  else			    check_def = 1;			}		      if (check_def)			{			  if (vers_data != 0x8001)			    {			      Elf_Internal_Verdef     ivd;			      Elf_Internal_Verdaux    ivda;			      Elf_External_Verdaux  evda;			      unsigned long           offset;			      offset =				version_info [DT_VERSIONTAGIDX (DT_VERDEF)]				- loadaddr;			      do				{				  Elf_External_Verdef   evd;				  GET_DATA (offset, evd, "version def");				  ivd.vd_ndx  = BYTE_GET (evd.vd_ndx);				  ivd.vd_aux  = BYTE_GET (evd.vd_aux);				  ivd.vd_next = BYTE_GET (evd.vd_next);				  offset += ivd.vd_next;				}			      while (ivd.vd_ndx != (vers_data & 0x7fff)				     && ivd.vd_next != 0);			      offset -= ivd.vd_next;			      offset += ivd.vd_aux;			      GET_DATA (offset, evda, "version def aux");			      ivda.vda_name = BYTE_GET (evda.vda_name);			      if (psym->st_name != ivda.vda_name)				printf ((vers_data & 0x8000)					? "@%s" : "@@%s",					strtab + ivda.vda_name);			    }			}		    }		}	      putchar ('\n');	    }	  free (symtab);	  if (strtab != string_table)	    free (strtab);	}    }  else if (do_syms)    printf      (_("\nDynamic symbol information is not available for displaying symbols.\n"));  if (do_histogram && buckets != NULL)    {      int *lengths;      int *counts;      int hn;      int si;      int maxlength = 0;      int nzero_counts = 0;      int nsyms = 0;      printf (_("\nHistogram for bucket list length (total of %d buckets):\n"),	      nbuckets);      printf (_(" Length  Number     %% of total  Coverage\n"));      lengths = (int *) calloc (nbuckets, sizeof (int));      if (lengths == NULL)	{	  error (_("Out of memory"));	  return 0;	}      for (hn = 0; hn < nbuckets; ++hn)	{	  if (! buckets [hn])	    continue;	  for (si = buckets[hn]; si > 0 && si < nchains; si = chains[si])	    {	      ++ nsyms;	      if (maxlength < ++lengths[hn])		++ maxlength;	    }	}      counts = (int *) calloc (maxlength + 1, sizeof (int));      if (counts == NULL)	{	  error (_("Out of memory"));	  return 0;	}      for (hn = 0; hn < nbuckets; ++hn)	++ counts [lengths [hn]];      if (nbuckets > 0)	{	  printf ("      0  %-10d (%5.1f%%)\n",		  counts[0], (counts[0] * 100.0) / nbuckets);	  for (si = 1; si <= maxlength; ++si)	    {	      nzero_counts += counts[si] * si;	      printf ("%7d  %-10d (%5.1f%%)    %5.1f%%\n",		      si, counts[si], (counts[si] * 100.0) / nbuckets,		      (nzero_counts * 100.0) / nsyms);	    }	}      free (counts);      free (lengths);    }  if (buckets != NULL)    {      free (buckets);      free (chains);    }  return 1;}