/* Symbol, variable and name lookup.
   Copyright (C) 2019-2020 Free Software Foundation, Inc.

   This file is part of libctf.

   libctf 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, or (at your option) any later
   version.

   This program 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; see the file COPYING.  If not see
   <http://www.gnu.org/licenses/>.  */

#include <ctf-impl.h>
#include <elf.h>
#include <string.h>

/* Compare the given input string and length against a table of known C storage
   qualifier keywords.  We just ignore these in ctf_lookup_by_name, below.  To
   do this quickly, we use a pre-computed Perfect Hash Function similar to the
   technique originally described in the classic paper:

   R.J. Cichelli, "Minimal Perfect Hash Functions Made Simple",
   Communications of the ACM, Volume 23, Issue 1, January 1980, pp. 17-19.

   For an input string S of length N, we use hash H = S[N - 1] + N - 105, which
   for the current set of qualifiers yields a unique H in the range [0 .. 20].
   The hash can be modified when the keyword set changes as necessary.  We also
   store the length of each keyword and check it prior to the final strcmp().

   TODO: just use gperf.  */

static int
isqualifier (const char *s, size_t len)
{
  static const struct qual
  {
    const char *q_name;
    size_t q_len;
  } qhash[] = {
    {"static", 6}, {"", 0}, {"", 0}, {"", 0},
    {"volatile", 8}, {"", 0}, {"", 0}, {"", 0}, {"", 0},
    {"", 0}, {"auto", 4}, {"extern", 6}, {"", 0}, {"", 0},
    {"", 0}, {"", 0}, {"const", 5}, {"register", 8},
    {"", 0}, {"restrict", 8}, {"_Restrict", 9}
  };

  int h = s[len - 1] + (int) len - 105;
  const struct qual *qp = &qhash[h];

  return (h >= 0 && (size_t) h < sizeof (qhash) / sizeof (qhash[0])
	  && (size_t) len == qp->q_len &&
	  strncmp (qp->q_name, s, qp->q_len) == 0);
}

/* Attempt to convert the given C type name into the corresponding CTF type ID.
   It is not possible to do complete and proper conversion of type names
   without implementing a more full-fledged parser, which is necessary to
   handle things like types that are function pointers to functions that
   have arguments that are function pointers, and fun stuff like that.
   Instead, this function implements a very simple conversion algorithm that
   finds the things that we actually care about: structs, unions, enums,
   integers, floats, typedefs, and pointers to any of these named types.  */

ctf_id_t
ctf_lookup_by_name (ctf_file_t *fp, const char *name)
{
  static const char delimiters[] = " \t\n\r\v\f*";

  const ctf_lookup_t *lp;
  const char *p, *q, *end;
  ctf_id_t type = 0;
  ctf_id_t ntype, ptype;

  if (name == NULL)
    return (ctf_set_errno (fp, EINVAL));

  for (p = name, end = name + strlen (name); *p != '\0'; p = q)
    {
      while (isspace ((int) *p))
	p++;			/* Skip leading whitespace.  */

      if (p == end)
	break;

      if ((q = strpbrk (p + 1, delimiters)) == NULL)
	q = end;		/* Compare until end.  */

      if (*p == '*')
	{
	  /* Find a pointer to type by looking in fp->ctf_ptrtab.
	     If we can't find a pointer to the given type, see if
	     we can compute a pointer to the type resulting from
	     resolving the type down to its base type and use
	     that instead.  This helps with cases where the CTF
	     data includes "struct foo *" but not "foo_t *" and
	     the user tries to access "foo_t *" in the debugger.

	     TODO need to handle parent containers too.  */

	  ntype = fp->ctf_ptrtab[LCTF_TYPE_TO_INDEX (fp, type)];
	  if (ntype == 0)
	    {
	      ntype = ctf_type_resolve_unsliced (fp, type);
	      if (ntype == CTF_ERR
		  || (ntype =
		      fp->ctf_ptrtab[LCTF_TYPE_TO_INDEX (fp, ntype)]) == 0)
		{
		  (void) ctf_set_errno (fp, ECTF_NOTYPE);
		  goto err;
		}
	    }

	  type = LCTF_INDEX_TO_TYPE (fp, ntype, (fp->ctf_flags & LCTF_CHILD));

	  q = p + 1;
	  continue;
	}

      if (isqualifier (p, (size_t) (q - p)))
	continue;		/* Skip qualifier keyword.  */

      for (lp = fp->ctf_lookups; lp->ctl_prefix != NULL; lp++)
	{
	  /* TODO: This is not MT-safe.  */
	  if ((lp->ctl_prefix[0] == '\0' ||
	       strncmp (p, lp->ctl_prefix, (size_t) (q - p)) == 0) &&
	      (size_t) (q - p) >= lp->ctl_len)
	    {
	      for (p += lp->ctl_len; isspace ((int) *p); p++)
		continue;	/* Skip prefix and next whitespace.  */

	      if ((q = strchr (p, '*')) == NULL)
		q = end;	/* Compare until end.  */

	      while (isspace ((int) q[-1]))
		q--;		/* Exclude trailing whitespace.  */

	      /* Expand and/or allocate storage for a slice of the name, then
		 copy it in.  */

	      if (fp->ctf_tmp_typeslicelen >= (size_t) (q - p) + 1)
		{
		  memcpy (fp->ctf_tmp_typeslice, p, (size_t) (q - p));
		  fp->ctf_tmp_typeslice[(size_t) (q - p)] = '\0';
		}
	      else
		{
		  free (fp->ctf_tmp_typeslice);
		  fp->ctf_tmp_typeslice = xstrndup (p, (size_t) (q - p));
		  if (fp->ctf_tmp_typeslice == NULL)
		    {
		      (void) ctf_set_errno (fp, ENOMEM);
		      return CTF_ERR;
		    }
		}

	      if ((type = ctf_lookup_by_rawhash (fp, lp->ctl_hash,
						 fp->ctf_tmp_typeslice)) == 0)
		{
		  (void) ctf_set_errno (fp, ECTF_NOTYPE);
		  goto err;
		}

	      break;
	    }
	}

      if (lp->ctl_prefix == NULL)
	{
	  (void) ctf_set_errno (fp, ECTF_NOTYPE);
	  goto err;
	}
    }

  if (*p != '\0' || type == 0)
    return (ctf_set_errno (fp, ECTF_SYNTAX));

  return type;

err:
  if (fp->ctf_parent != NULL
      && (ptype = ctf_lookup_by_name (fp->ctf_parent, name)) != CTF_ERR)
    return ptype;

  return CTF_ERR;
}

typedef struct ctf_lookup_var_key
{
  ctf_file_t *clvk_fp;
  const char *clvk_name;
} ctf_lookup_var_key_t;

/* A bsearch function for variable names.  */

static int
ctf_lookup_var (const void *key_, const void *memb_)
{
  const ctf_lookup_var_key_t *key = key_;
  const ctf_varent_t *memb = memb_;

  return (strcmp (key->clvk_name, ctf_strptr (key->clvk_fp, memb->ctv_name)));
}

/* Given a variable name, return the type of the variable with that name.  */

ctf_id_t
ctf_lookup_variable (ctf_file_t *fp, const char *name)
{
  ctf_varent_t *ent;
  ctf_lookup_var_key_t key = { fp, name };

  /* This array is sorted, so we can bsearch for it.  */

  ent = bsearch (&key, fp->ctf_vars, fp->ctf_nvars, sizeof (ctf_varent_t),
		 ctf_lookup_var);

  if (ent == NULL)
    {
      if (fp->ctf_parent != NULL)
	return ctf_lookup_variable (fp->ctf_parent, name);

      return (ctf_set_errno (fp, ECTF_NOTYPEDAT));
    }

  return ent->ctv_type;
}

/* Given a symbol table index, return the name of that symbol from the secondary
   string table, or the null string (never NULL).  */
const char *
ctf_lookup_symbol_name (ctf_file_t *fp, unsigned long symidx)
{
  const ctf_sect_t *sp = &fp->ctf_symtab;
  Elf64_Sym sym, *gsp;

  if (sp->cts_data == NULL)
    {
      ctf_set_errno (fp, ECTF_NOSYMTAB);
      return _CTF_NULLSTR;
    }

  if (symidx >= fp->ctf_nsyms)
    {
      ctf_set_errno (fp, EINVAL);
      return _CTF_NULLSTR;
    }

  if (sp->cts_entsize == sizeof (Elf32_Sym))
    {
      const Elf32_Sym *symp = (Elf32_Sym *) sp->cts_data + symidx;
      gsp = ctf_sym_to_elf64 (symp, &sym);
    }
  else
      gsp = (Elf64_Sym *) sp->cts_data + symidx;

  if (gsp->st_name < fp->ctf_str[CTF_STRTAB_1].cts_len)
    return (const char *) fp->ctf_str[CTF_STRTAB_1].cts_strs + gsp->st_name;

  return _CTF_NULLSTR;
}

/* Given a symbol table index, return the type of the data object described
   by the corresponding entry in the symbol table.  */

ctf_id_t
ctf_lookup_by_symbol (ctf_file_t *fp, unsigned long symidx)
{
  const ctf_sect_t *sp = &fp->ctf_symtab;
  ctf_id_t type;

  if (sp->cts_data == NULL)
    return (ctf_set_errno (fp, ECTF_NOSYMTAB));

  if (symidx >= fp->ctf_nsyms)
    return (ctf_set_errno (fp, EINVAL));

  if (sp->cts_entsize == sizeof (Elf32_Sym))
    {
      const Elf32_Sym *symp = (Elf32_Sym *) sp->cts_data + symidx;
      if (ELF32_ST_TYPE (symp->st_info) != STT_OBJECT)
	return (ctf_set_errno (fp, ECTF_NOTDATA));
    }
  else
    {
      const Elf64_Sym *symp = (Elf64_Sym *) sp->cts_data + symidx;
      if (ELF64_ST_TYPE (symp->st_info) != STT_OBJECT)
	return (ctf_set_errno (fp, ECTF_NOTDATA));
    }

  if (fp->ctf_sxlate[symidx] == -1u)
    return (ctf_set_errno (fp, ECTF_NOTYPEDAT));

  type = *(uint32_t *) ((uintptr_t) fp->ctf_buf + fp->ctf_sxlate[symidx]);
  if (type == 0)
    return (ctf_set_errno (fp, ECTF_NOTYPEDAT));

  return type;
}

/* Return the native dict of a given type: if called on a child and the
   type is in the parent, return the parent.  Needed if you plan to access
   the type directly, without using the API.  */
ctf_file_t *
ctf_get_dict (ctf_file_t *fp, ctf_id_t type)
{
    if ((fp->ctf_flags & LCTF_CHILD) && LCTF_TYPE_ISPARENT (fp, type))
      return fp->ctf_parent;

    return fp;
}

/* Return the pointer to the internal CTF type data corresponding to the
   given type ID.  If the ID is invalid, the function returns NULL.
   This function is not exported outside of the library.  */

const ctf_type_t *
ctf_lookup_by_id (ctf_file_t **fpp, ctf_id_t type)
{
  ctf_file_t *fp = *fpp;	/* Caller passes in starting CTF dict.  */
  ctf_id_t idx;

  if ((fp = ctf_get_dict (fp, type)) == NULL)
    {
      (void) ctf_set_errno (*fpp, ECTF_NOPARENT);
      return NULL;
    }

  /* If this dict is writable, check for a dynamic type.  */

  if (fp->ctf_flags & LCTF_RDWR)
    {
      ctf_dtdef_t *dtd;

      if ((dtd = ctf_dynamic_type (fp, type)) != NULL)
	{
	  *fpp = fp;
	  return &dtd->dtd_data;
	}
      (void) ctf_set_errno (*fpp, ECTF_BADID);
      return NULL;
    }

  /* Check for a type in the static portion.  */

  idx = LCTF_TYPE_TO_INDEX (fp, type);
  if (idx > 0 && (unsigned long) idx <= fp->ctf_typemax)
    {
      *fpp = fp;		/* Function returns ending CTF container.  */
      return (LCTF_INDEX_TO_TYPEPTR (fp, idx));
    }

  (void) ctf_set_errno (*fpp, ECTF_BADID);
  return NULL;
}

/* Given a symbol table index, return the info for the function described
   by the corresponding entry in the symbol table.  */

int
ctf_func_info (ctf_file_t *fp, unsigned long symidx, ctf_funcinfo_t *fip)
{
  const ctf_sect_t *sp = &fp->ctf_symtab;
  const uint32_t *dp;
  uint32_t info, kind, n;

  if (sp->cts_data == NULL)
    return (ctf_set_errno (fp, ECTF_NOSYMTAB));

  if (symidx >= fp->ctf_nsyms)
    return (ctf_set_errno (fp, EINVAL));

  if (sp->cts_entsize == sizeof (Elf32_Sym))
    {
      const Elf32_Sym *symp = (Elf32_Sym *) sp->cts_data + symidx;
      if (ELF32_ST_TYPE (symp->st_info) != STT_FUNC)
	return (ctf_set_errno (fp, ECTF_NOTFUNC));
    }
  else
    {
      const Elf64_Sym *symp = (Elf64_Sym *) sp->cts_data + symidx;
      if (ELF64_ST_TYPE (symp->st_info) != STT_FUNC)
	return (ctf_set_errno (fp, ECTF_NOTFUNC));
    }

  if (fp->ctf_sxlate[symidx] == -1u)
    return (ctf_set_errno (fp, ECTF_NOFUNCDAT));

  dp = (uint32_t *) ((uintptr_t) fp->ctf_buf + fp->ctf_sxlate[symidx]);

  info = *dp++;
  kind = LCTF_INFO_KIND (fp, info);
  n = LCTF_INFO_VLEN (fp, info);

  if (kind == CTF_K_UNKNOWN && n == 0)
    return (ctf_set_errno (fp, ECTF_NOFUNCDAT));

  if (kind != CTF_K_FUNCTION)
    return (ctf_set_errno (fp, ECTF_CORRUPT));

  fip->ctc_return = *dp++;
  fip->ctc_argc = n;
  fip->ctc_flags = 0;

  if (n != 0 && dp[n - 1] == 0)
    {
      fip->ctc_flags |= CTF_FUNC_VARARG;
      fip->ctc_argc--;
    }

  return 0;
}

/* Given a symbol table index, return the arguments for the function described
   by the corresponding entry in the symbol table.  */

int
ctf_func_args (ctf_file_t * fp, unsigned long symidx, uint32_t argc,
	       ctf_id_t * argv)
{
  const uint32_t *dp;
  ctf_funcinfo_t f;

  if (ctf_func_info (fp, symidx, &f) < 0)
    return -1;			/* errno is set for us.  */

  /* The argument data is two uint32_t's past the translation table
     offset: one for the function info, and one for the return type. */

  dp = (uint32_t *) ((uintptr_t) fp->ctf_buf + fp->ctf_sxlate[symidx]) + 2;

  for (argc = MIN (argc, f.ctc_argc); argc != 0; argc--)
    *argv++ = *dp++;

  return 0;
}
