/* Test program for libdwfl symbol resolving
   Copyright (C) 2013 Red Hat, Inc.
   This file is part of elfutils.

   This file is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.

   elfutils is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

#include <config.h>
#include <assert.h>
#include <inttypes.h>
#include ELFUTILS_HEADER(dwfl)
#include <elf.h>
#include <dwarf.h>
#include <argp.h>
#include <stdio.h>
#include <stdio_ext.h>
#include <stdlib.h>
#include <error.h>
#include <string.h>

static const char *
gelf_type (GElf_Sym *sym)
{
  switch (GELF_ST_TYPE (sym->st_info))
    {
    case STT_NOTYPE:
      return "NOTYPE";
    case STT_OBJECT:
      return "OBJECT";
    case STT_FUNC:
      return "FUNC";
    case STT_SECTION:
      return "SECTION";
    case STT_FILE:
      return "FILE";
    case STT_COMMON:
      return "COMMON";
    case STT_TLS:
      return "TLS";
    default:
      return "UNKNOWN";
    }
}

static const char *
gelf_bind (GElf_Sym *sym)
{
  switch (GELF_ST_BIND (sym->st_info))
    {
    case STB_LOCAL:
      return "LOCAL";
    case STB_GLOBAL:
      return "GLOBAL";
    case STB_WEAK:
      return "WEAK";
    default:
      return "UNKNOWN";
    }
}

static int
gelf_bind_order (GElf_Sym *sym)
{
  switch (GELF_ST_BIND (sym->st_info))
    {
    case STB_LOCAL:
      return 1;
    case STB_WEAK:
      return 2;
    case STB_GLOBAL:
      return 3;
    default:
      return 0;
    }
}

static const char *
elf_section_name (Elf *elf, GElf_Word shndx)
{
  GElf_Ehdr ehdr;
  GElf_Shdr shdr;
  Elf_Scn *scn = elf_getscn (elf, shndx);
  gelf_getshdr (scn, &shdr);
  gelf_getehdr (elf, &ehdr);
  return elf_strptr (elf, ehdr.e_shstrndx, shdr.sh_name);
}

bool
addr_in_section (Elf *elf, GElf_Word shndx, GElf_Addr addr)
{
  GElf_Shdr shdr;
  Elf_Scn *scn = elf_getscn (elf, shndx);
  gelf_getshdr (scn, &shdr);
  return addr >= shdr.sh_addr && addr < shdr.sh_addr + shdr.sh_size;
}

static int
list_syms (struct Dwfl_Module *mod,
	   void **user __attribute__ ((unused)), const char *mod_name,
	   Dwarf_Addr low_addr __attribute__ ((unused)),
	   void *arg __attribute__ ((unused)))
{
  int syms = dwfl_module_getsymtab (mod);
  if (syms < 0)
    {
      printf ("%s: %s\n", mod_name, dwfl_errmsg (-1));
      return DWARF_CB_OK;
    }

  for (int ndx = 0; ndx < syms; ndx++)
    {
      GElf_Sym sym;
      GElf_Word shndxp;
      Elf *elf;
      Dwarf_Addr bias;
      const char *name = dwfl_module_getsym (mod, ndx, &sym, &shndxp);

      printf("%4d: %s\t%s\t%s (%" PRIu64 ") %#" PRIx64,
	     ndx, gelf_type (&sym), gelf_bind (&sym), name,
	     sym.st_size, sym.st_value);

      /* The info variant doesn't adjust st_value but returns the (possible)
	 adjusted value separately. */
      GElf_Addr value;
      GElf_Sym isym;
      name = dwfl_module_getsym_info (mod, ndx, &isym, &value, &shndxp,
				      &elf, &bias);

      GElf_Ehdr ehdr;
      gelf_getehdr (elf, &ehdr);

      // getsym st_values might or might not be adjusted depending on section.
      // For ET_REL the adjustment is section relative.
      assert (sym.st_value == isym.st_value
	      || sym.st_value == isym.st_value + bias
	      || ehdr.e_type == ET_REL);

      /* And the reverse, which works for function symbols at least.
	 Note this only works because the st.value is adjusted by
	 dwfl_module_getsym ().  */
      if (GELF_ST_TYPE (sym.st_info) == STT_FUNC && shndxp != SHN_UNDEF)
	{
	  /* Make sure the adjusted value really falls in the elf section. */
          assert (addr_in_section (elf, shndxp, sym.st_value - bias));

	  GElf_Addr addr = value;
	  GElf_Sym asym;
	  GElf_Word ashndxp;
	  Elf *aelf;
	  Dwarf_Addr abias;
	  GElf_Off off;
	  const char *aname = dwfl_module_addrinfo (mod, addr, &off, &asym,
						    &ashndxp, &aelf, &abias);

	  /* Make sure the adjusted value really falls in the elf section. */
          assert (addr_in_section (aelf, ashndxp, asym.st_value)
		  || ehdr.e_type == ET_REL);

	  /* Either they are the same symbol (name), the binding of
	     asym is "stronger" (or equal) to sym or asym is more specific
	     (has a lower address) than sym.  */
	  assert ((strcmp (name, aname) == 0
		   || gelf_bind_order (&asym) >= gelf_bind_order (&sym))
		  && value <= sym.st_value);

	  addr = sym.st_value;
	  int res = dwfl_module_relocate_address (mod, &addr);
	  assert (res != -1);
	  if (shndxp < SHN_LORESERVE)
	    printf(", rel: %#" PRIx64 " (%s)", addr,
		   elf_section_name (elf, shndxp));
	  else
	    printf(", rel: %#" PRIx64 "", addr);

	  /* Print the section of the actual value if different from sym.  */
	  if (value != isym.st_value + bias && ehdr.e_type != ET_REL)
	    {
	      GElf_Addr ebias;
	      addr = value;
	      Elf_Scn *scn = dwfl_module_address_section (mod, &addr, &ebias);
	      GElf_Shdr shdr_mem;
	      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
	      Elf *melf = dwfl_module_getelf (mod, &ebias);
	      gelf_getehdr (melf, &ehdr);
	      const char *sname = elf_strptr (melf, ehdr.e_shstrndx,
					      shdr->sh_name);
	      printf (" [%#" PRIx64 ", rel: %#" PRIx64 " (%s)]",
		      value, addr, sname);
	    }

	}
      printf ("\n");
    }

  return DWARF_CB_OK;
}

int
main (int argc, char *argv[])
{
  int remaining;
  Dwfl *dwfl;
  error_t res;

  res = argp_parse (dwfl_standard_argp (), argc, argv, 0, &remaining, &dwfl);
  assert (res == 0 && dwfl != NULL);

  ptrdiff_t off = 0;
  do
    off = dwfl_getmodules (dwfl, list_syms, NULL, off);
  while (off > 0);

  dwfl_end (dwfl);

  return off;
}
