/*
** dynamic.c for libelfsh
** 
** Started on  Tue Feb 27 04:36:53 2001 mayhem
** Last update Sun Mar 17 09:12:59 2002 mayhem
*/
#include "libelfsh.h"



/* Return a ptr on the dynamic section */
Elf32_Dyn	*elfsh_get_dynamic(Elfsh32_Obj *file, int *num)
{
  Elfsh32_Sect	*new;
  int		nbr;

  if (!file->dynamic)
    {
      
      new = elfsh_get_section_by_type(file, SHT_DYNAMIC, NULL, NULL, &nbr, 0);
      if (!new)
	return (NULL);
    
      new->data = elfsh_load_section(file, new->shdr);
      if (!new->data)
	return (NULL);

      file->dynamic = new;
      new->nbr = nbr / sizeof(Elf32_Dyn);
    }
  
  if (num)
    *num = new->nbr;
  
  return (file->dynamic->data);
}




/* Return the ascii description for the dynamic entry type */
u_int	elfsh_get_dynentry_type(Elf32_Dyn *d)
{
  return (d->d_tag);
}






/*
** Its a lame formatting function to get some human readable output
** for the dynamic section information .
*/
char		*elfsh_get_dynentry_info(Elfsh32_Obj *file, Elf32_Dyn *entry)
{


  switch (entry->d_tag)
    {

      /*
      ** Use the d_val field of the entry as an index in the string table .
      **
      ** We cannot use elfsh_get_dynsymbol_name() because we have only the index
      ** in the string table for the requested symbol and we need the symbol
      ** entry offset to call this function .
      */
    case DT_NEEDED:
    case DT_SONAME:
    case DT_RPATH:
      if (!file->dynsym && !elfsh_get_dynsymtab(file, NULL))
	return (NULL);

      return ((char *) file->dyn_strtab->data + entry->d_un.d_val);
  
	
      /*
      ** These entry types are flags
      */
    case DT_SYMBOLIC:
      return ("Current object is now the first checked for symbol resolution");

    case DT_TEXTREL:
      return ("Relocation can now overwrite the .text section");

    case DT_BIND_NOW:
      return ("Symbol binding is now completed before execution");
    
    case DT_PLTREL:
      snprintf(file->buff, sizeof(file->buff), "%d", entry->d_un.d_val);
      return (file->buff);

    case DT_NULL:
      return ("END OF SECTION");

      /*
      ** Use the d_val field of the entry
      */
    case DT_PLTRELSZ:
    case DT_RELASZ:
    case DT_RELAENT:
    case DT_STRSZ:
    case DT_RELSZ:
    case DT_RELENT:
    case DT_SYMENT:
      snprintf(file->buff, sizeof(file->buff), "%u bytes", entry->d_un.d_val);
      return (file->buff);

      
      /*
      ** Use the d_ptr field of the entry
      */
    case DT_PLTGOT:
    case DT_STRTAB:
    case DT_SYMTAB:
    case DT_HASH:
    case DT_RELA:
    case DT_INIT:
    case DT_FINI:
    case DT_REL:
    case DT_DEBUG:
    case DT_JMPREL:
      bzero(file->buff, sizeof(file->buff));
      snprintf(file->buff, sizeof(file->buff), "%8p", (void *) entry->d_un.d_ptr);
      return (file->buff);
      
    default:
      return ("Unknown content");
    }

}




/* Get .dynamic entries by type */
Elf32_Dyn	*elfsh_get_dynamic_entry_by_type(Elfsh32_Obj *file, char type)
{
  int		index;
  int		size;
  Elf32_Dyn	*table;

  table = elfsh_get_dynamic(file, &size);
  if (!table)
    return (NULL);

  for (index = 0; index < size; index++)
    if (elfsh_get_dynentry_type(table + index) == type)
      return (table + index);
  
  ELFSH_SETERROR("libelfsh: No dynamic entry with that type .", NULL);
}











