/*
** got.c for elfsh
** 
** Started on  Sun Jun 24 21:30:41 2001 mayhem
** Last update Sat Jun  1 15:32:55 2002 mayhem
*/
#include "libelfsh.h"





/* Read the global offset table in section .got */
void		*elfsh_get_got(Elfsh32_Obj *file, int *num)
{
  Elfsh32_Sect	*new;

  new = elfsh_get_section_by_name(file, ELFSH_SECTION_NAME_GOT, NULL, NULL, NULL);
  if (!new)
    return (NULL);

  new->nbr = new->shdr->sh_size / 4;

  new->data = elfsh_load_section(file, new->shdr);
  if (!new->data)
    return (NULL);

  file->got = new;

  if (num)
    *num = new->nbr;

  return (new->data);
}






/* Modify a GOT entry */
int		elfsh_set_got_entry_by_index(Elfsh32_Obj *file, int index, int new_addr)
{
  int		nbr;
  int		*got;
  
  got = elfsh_get_got(file, &nbr);
  if (!got)
    return (-1);
  if (index >= file->got->nbr)
    ELFSH_SETERROR("libelfsh: index too big . \n", -1);
  got[index] = new_addr;
  return (0);
}




/* Modify the got entry for the dynamic symbol 'name' */
int		elfsh_set_got_entry_by_name(Elfsh32_Obj *file, char *name, int new_addr)
{
  Elf32_Sym	*sym;
  int		foffset;
  int		got;

  if (!file || !name)
    return (0);

  sym = elfsh_get_dynsymbol_by_name(file, name);
  if (!sym)
    ELFSH_SETERROR("libelfsh: Unknown dynamic symbol . \n", 0);
  
  if (!elfsh_is_pltentry(file, sym))
    ELFSH_SETERROR("libelfsh: Symbol is not a Procedure Linkage Table entry . \n", 0);

  if (!elfsh_get_got(file, NULL))
    ELFSH_SETERROR("libelfsh: Cant retreive Global offset Table . \n", -1);

  /* We pick up the got entry address from the plt */
  foffset = elfsh_get_foffset_from_vaddr(file, sym->st_value);
  elfsh_raw_read(file, foffset + 2, &got, sizeof(got));
  foffset = elfsh_get_foffset_from_vaddr(file, got);
  elfsh_raw_write(file, foffset, &new_addr, sizeof(got));
  return (0);
}






