Blame libdw/dwarf_getscopevar.c

Packit 032894
/* Find a named variable or parameter within given scopes.
Packit 032894
   Copyright (C) 2005-2009 Red Hat, Inc.
Packit 032894
   This file is part of elfutils.
Packit 032894
Packit 032894
   This file is free software; you can redistribute it and/or modify
Packit 032894
   it under the terms of either
Packit 032894
Packit 032894
     * the GNU Lesser General Public License as published by the Free
Packit 032894
       Software Foundation; either version 3 of the License, or (at
Packit 032894
       your option) any later version
Packit 032894
Packit 032894
   or
Packit 032894
Packit 032894
     * the GNU General Public License as published by the Free
Packit 032894
       Software Foundation; either version 2 of the License, or (at
Packit 032894
       your option) any later version
Packit 032894
Packit 032894
   or both in parallel, as here.
Packit 032894
Packit 032894
   elfutils is distributed in the hope that it will be useful, but
Packit 032894
   WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 032894
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 032894
   General Public License for more details.
Packit 032894
Packit 032894
   You should have received copies of the GNU General Public License and
Packit 032894
   the GNU Lesser General Public License along with this program.  If
Packit 032894
   not, see <http://www.gnu.org/licenses/>.  */
Packit 032894
Packit 032894
#ifdef HAVE_CONFIG_H
Packit 032894
# include <config.h>
Packit 032894
#endif
Packit 032894
Packit 032894
#include <stdbool.h>
Packit 032894
#include <string.h>
Packit 032894
#include "libdwP.h"
Packit 032894
#include <dwarf.h>
Packit 032894
Packit 032894
Packit 032894
/* Find the containing CU's files.  */
Packit 032894
static int
Packit 032894
getfiles (Dwarf_Die *die, Dwarf_Files **files)
Packit 032894
{
Packit 032894
  return INTUSE(dwarf_getsrcfiles) (&CUDIE (die->cu), files, NULL);
Packit 032894
}
Packit 032894
Packit 032894
/* Fetch an attribute that should have a constant integer form.  */
Packit 032894
static int
Packit 032894
getattr (Dwarf_Die *die, int search_name, Dwarf_Word *value)
Packit 032894
{
Packit 032894
  Dwarf_Attribute attr_mem;
Packit 032894
  return INTUSE(dwarf_formudata) (INTUSE(dwarf_attr) (die, search_name,
Packit 032894
						      &attr_mem), value);
Packit 032894
}
Packit 032894
Packit 032894
static inline int
Packit 032894
file_matches (const char *lastfile,
Packit 032894
              size_t match_file_len, const char *match_file,
Packit 032894
              Dwarf_Files *files, size_t idx,
Packit 032894
              bool *lastfile_matches)
Packit 032894
{
Packit 032894
  if (idx >= files->nfiles)
Packit 032894
    return false;
Packit 032894
  const char *file = files->info[idx].name;
Packit 032894
  if (file != lastfile)
Packit 032894
    {
Packit 032894
      size_t len = strlen (file);
Packit 032894
      *lastfile_matches = (len >= match_file_len
Packit 032894
                          && !memcmp (match_file, file, match_file_len)
Packit 032894
                          && (len == match_file_len
Packit 032894
                              || file[len - match_file_len - 1] == '/'));
Packit 032894
    }
Packit 032894
  return *lastfile_matches;
Packit 032894
}
Packit 032894
Packit 032894
/* Search SCOPES[0..NSCOPES-1] for a variable called NAME.
Packit 032894
   Ignore the first SKIP_SHADOWS scopes that match the name.
Packit 032894
   If MATCH_FILE is not null, accept only declaration in that source file;
Packit 032894
   if MATCH_LINENO or MATCH_LINECOL are also nonzero, accept only declaration
Packit 032894
   at that line and column.
Packit 032894
Packit 032894
   If successful, fill in *RESULT with the DIE of the variable found,
Packit 032894
   and return N where SCOPES[N] is the scope defining the variable.
Packit 032894
   Return -1 for errors or -2 for no matching variable found.  */
Packit 032894
Packit 032894
int
Packit 032894
dwarf_getscopevar (Dwarf_Die *scopes, int nscopes,
Packit 032894
		   const char *name, int skip_shadows,
Packit 032894
		   const char *match_file, int match_lineno, int match_linecol,
Packit 032894
		   Dwarf_Die *result)
Packit 032894
{
Packit 032894
  /* Match against the given file name.  */
Packit 032894
  size_t match_file_len = match_file == NULL ? 0 : strlen (match_file);
Packit 032894
  bool lastfile_matches = false;
Packit 032894
  const char *lastfile = NULL;
Packit 032894
Packit 032894
  /* Start with the innermost scope and move out.  */
Packit 032894
  for (int out = 0; out < nscopes; ++out)
Packit 032894
    if (INTUSE(dwarf_haschildren) (&scopes[out]))
Packit 032894
      {
Packit 032894
	if (INTUSE(dwarf_child) (&scopes[out], result) != 0)
Packit 032894
	  return -1;
Packit 032894
	do
Packit 032894
	  {
Packit 032894
	    switch (INTUSE(dwarf_tag) (result))
Packit 032894
	      {
Packit 032894
	      case DW_TAG_variable:
Packit 032894
	      case DW_TAG_formal_parameter:
Packit 032894
		break;
Packit 032894
Packit 032894
	      default:
Packit 032894
		continue;
Packit 032894
	      }
Packit 032894
Packit 032894
	    /* Only get here for a variable or parameter.  Check the name.  */
Packit 032894
	    const char *diename = INTUSE(dwarf_diename) (result);
Packit 032894
	    if (diename != NULL && !strcmp (name, diename))
Packit 032894
	      {
Packit 032894
		/* We have a matching name.  */
Packit 032894
Packit 032894
		if (skip_shadows > 0)
Packit 032894
		  {
Packit 032894
		    /* Punt this scope for the one it shadows.  */
Packit 032894
		    --skip_shadows;
Packit 032894
		    break;
Packit 032894
		  }
Packit 032894
Packit 032894
		if (match_file != NULL)
Packit 032894
		  {
Packit 032894
		    /* Check its decl_file.  */
Packit 032894
Packit 032894
		    Dwarf_Word i;
Packit 032894
		    Dwarf_Files *files;
Packit 032894
		    if (getattr (result, DW_AT_decl_file, &i) != 0
Packit 032894
			|| getfiles (&scopes[out], &files) != 0)
Packit 032894
		      break;
Packit 032894
Packit 032894
		    if (!file_matches (lastfile, match_file_len, match_file,
Packit 032894
		                       files, i, &lastfile_matches))
Packit 032894
		      break;
Packit 032894
Packit 032894
		    if (match_lineno > 0
Packit 032894
			&& (getattr (result, DW_AT_decl_line, &i) != 0
Packit 032894
			    || (int) i != match_lineno))
Packit 032894
		      break;
Packit 032894
		    if (match_linecol > 0
Packit 032894
			&& (getattr (result, DW_AT_decl_column, &i) != 0
Packit 032894
			    || (int) i != match_linecol))
Packit 032894
		      break;
Packit 032894
		  }
Packit 032894
Packit 032894
		/* We have a winner!  */
Packit 032894
		return out;
Packit 032894
	      }
Packit 032894
	  }
Packit 032894
	while (INTUSE(dwarf_siblingof) (result, result) == 0);
Packit 032894
      }
Packit 032894
Packit 032894
  return -2;
Packit 032894
}