/*
** sym.c for elfsh
** 
** Started on  Fri Nov  2 15:19:38 2001 mayhem
** Last update Sun Mar 10 01:13:04 2002 mayhem
*/
#include "elfsh.h"









/* Print the chosen symbol table */
void		__display_sym(Elfsh32_Obj	*file,
			      void		*tab,
			      int		num,
			      regex_t		*regx,
			      argv_t		*args,
			      char		*(*get_symname)(Elfsh32_Obj *file, Elf32_Sym *s))
{
  Elf32_Sym	*table;
  char		*name;
  char		*type;
  char		*bind;
  u_int		typenum;
  u_int		bindnum;
  int		index;
  int		need_to_free_table = 0;
  Elfsh32_Sect	*sect;
  char		*sect_name;
  char		buff[256];

  /* Sort the table if necessary */
  if (args->sort)
    {
      if ((table = elfsh_copy_symtab(tab, num)) == NULL)
	{
	  elfsh_error();
	  return;
	}
      if  (elfsh_sort_symtab(table, num, *args->sort) < 0)
	{
	  fprintf(stderr, "elfsh: Invalid sort mode, printing unsorted symbol table . \n");  
	  free(table);
	  table = tab;
	}
      else
	need_to_free_table = 1;
    }
  else
    table = tab;
  

  /* Browse symbol entry */
  for (index = 0; index < num; index++)
    {
      
      typenum = (elfsh_get_symbol_type(table + index) >= SYMTYPE_MAX ? 0 : elfsh_get_symbol_type(table + index));
      bindnum = (elfsh_get_symbol_bind(table + index) >= SYMBIND_MAX ? 0 : elfsh_get_symbol_bind(table + index));
      type = elfsh_sym_type[typenum];
      bind = elfsh_sym_bind[bindnum];
      
      name = get_symname(file, table + index);

      sect_name = NULL;
      sect = elfsh_get_parent_section(file, table[index].st_value, NULL);
      if (sect)
	sect_name = elfsh_get_section_name(file, sect->shdr);

      if (!name || *name == 0)
	name = ELFSH_NULL_STRING;
      if (!type || *type == 0)
	type = ELFSH_NULL_STRING;
      if (!bind || *bind == 0)
	bind = ELFSH_NULL_STRING;
      if (!sect_name)
	sect_name = ELFSH_NULL_STRING;
      
      snprintf(buff, sizeof(buff), "[%03u] %10p %30s \t type: %-10s \t size: %05d bytes \t [%s] \t => %s",
	       index, elfsh_get_symbol_offset(table + index),
	       name, type, elfsh_get_symbol_size(table + index), bind, sect_name);

      if (!regx || (regx && !regexec(regx, buff, 0, 0, 0)))
	puts(buff);

      
    }
  

  puts("");
  if (need_to_free_table)
    free(table);

}







/* Display the symbol table */
int		display_sym(Elfsh32_Obj *file, argv_t *args)
{
  Elf32_Sym	*symtab;
  regex_t	*tmp;
  int		num;

  if ((symtab = elfsh_get_symtab(file, &num)) == NULL)
    RET(-1);

  puts("\n[SYMBOL TABLE]");

  tmp = (REGX_IS_USED(args->sym_use_regx) ? &args->sym_regx : 
	 REGX_IS_USED(args->gl_use_regx)  ? &args->gl_regx  : NULL);
  
  __display_sym(file, symtab, num, tmp, args, elfsh_get_symbol_name);

  return (0);
}









/* Display the dynamic symbol table */
int		display_dynsym(Elfsh32_Obj *file, argv_t *args)
{
  Elf32_Sym	*symtab;
  regex_t	*tmp;
  int		num;

  if ((symtab = elfsh_get_dynsymtab(file, &num)) == NULL)
    RET(-1);

  puts("\n[DYNAMIC SYMBOL TABLE]");

  tmp = (REGX_IS_USED(args->dynsym_use_regx) ? &args->dynsym_regx : 
	 REGX_IS_USED(args->gl_use_regx)     ? &args->gl_regx  : NULL);
  
  __display_sym(file, symtab, num, tmp, args, elfsh_get_dynsymbol_name);
  
  return (0);
}












