Blame tests/dwflmodtest.c

Packit Service 97d2fb
/* Test program for libdwfl basic module tracking, relocation.
Packit Service 97d2fb
   Copyright (C) 2005, 2007 Red Hat, Inc.
Packit Service 97d2fb
   This file is part of elfutils.
Packit Service 97d2fb
Packit Service 97d2fb
   This file is free software; you can redistribute it and/or modify
Packit Service 97d2fb
   it under the terms of the GNU General Public License as published by
Packit Service 97d2fb
   the Free Software Foundation; either version 3 of the License, or
Packit Service 97d2fb
   (at your option) any later version.
Packit Service 97d2fb
Packit Service 97d2fb
   elfutils is distributed in the hope that it will be useful, but
Packit Service 97d2fb
   WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 97d2fb
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 97d2fb
   GNU General Public License for more details.
Packit Service 97d2fb
Packit Service 97d2fb
   You should have received a copy of the GNU General Public License
Packit Service 97d2fb
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
Packit Service 97d2fb
Packit Service 97d2fb
#include <config.h>
Packit Service 97d2fb
#include <assert.h>
Packit Service 97d2fb
#include <inttypes.h>
Packit Service 97d2fb
#include <sys/types.h>
Packit Service 97d2fb
#include <stdio.h>
Packit Service 97d2fb
#include <stdio_ext.h>
Packit Service 97d2fb
#include <stdlib.h>
Packit Service 97d2fb
#include <string.h>
Packit Service 97d2fb
#include <locale.h>
Packit Service 97d2fb
#include <argp.h>
Packit Service 97d2fb
#include ELFUTILS_HEADER(dwfl)
Packit Service 97d2fb
#include <dwarf.h>
Packit Service 97d2fb
#include "system.h"
Packit Service 97d2fb
Packit Service 97d2fb
static bool show_inlines;
Packit Service 97d2fb
Packit Service 97d2fb
struct info
Packit Service 97d2fb
{
Packit Service 97d2fb
  Dwarf_Die *cudie;
Packit Service 97d2fb
  Dwarf_Addr dwbias;
Packit Service 97d2fb
};
Packit Service 97d2fb
Packit Service 97d2fb
static int
Packit Service 97d2fb
print_instance (Dwarf_Die *instance, void *arg)
Packit Service 97d2fb
{
Packit Service 97d2fb
  const struct info *info = arg;
Packit Service 97d2fb
Packit Service 97d2fb
  printf ("    inlined");
Packit Service 97d2fb
Packit Service 97d2fb
  Dwarf_Files *files;
Packit Service 97d2fb
  if (dwarf_getsrcfiles (info->cudie, &files, NULL) == 0)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      Dwarf_Attribute attr_mem;
Packit Service 97d2fb
      Dwarf_Word val;
Packit Service 97d2fb
      if (dwarf_formudata (dwarf_attr (instance, DW_AT_call_file,
Packit Service 97d2fb
				       &attr_mem), &val) == 0)
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  const char *file = dwarf_filesrc (files, val, NULL, NULL);
Packit Service 97d2fb
	  int lineno = 0, colno = 0;
Packit Service 97d2fb
	  if (dwarf_formudata (dwarf_attr (instance, DW_AT_call_line,
Packit Service 97d2fb
					   &attr_mem), &val) == 0)
Packit Service 97d2fb
	    lineno = val;
Packit Service 97d2fb
	  if (dwarf_formudata (dwarf_attr (instance, DW_AT_call_column,
Packit Service 97d2fb
					   &attr_mem), &val) == 0)
Packit Service 97d2fb
	    colno = val;
Packit Service 97d2fb
	  if (lineno == 0)
Packit Service 97d2fb
	    {
Packit Service 97d2fb
	      if (file != NULL)
Packit Service 97d2fb
		printf (" from %s", file);
Packit Service 97d2fb
	    }
Packit Service 97d2fb
	  else if (colno == 0)
Packit Service 97d2fb
	    printf (" at %s:%u", file, lineno);
Packit Service 97d2fb
	  else
Packit Service 97d2fb
	    printf (" at %s:%u:%u", file, lineno, colno);
Packit Service 97d2fb
	}
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  Dwarf_Addr lo = -1, hi = -1, entry = -1;
Packit Service 97d2fb
  if (dwarf_lowpc (instance, &lo) == 0)
Packit Service 97d2fb
    lo += info->dwbias;
Packit Service 97d2fb
  else
Packit Service 97d2fb
    printf (" (lowpc => %s)", dwarf_errmsg (-1));
Packit Service 97d2fb
  if (dwarf_highpc (instance, &hi) == 0)
Packit Service 97d2fb
    hi += info->dwbias;
Packit Service 97d2fb
  else
Packit Service 97d2fb
    printf (" (highpc => %s)", dwarf_errmsg (-1));
Packit Service 97d2fb
Packit Service 97d2fb
  Dwarf_Attribute attr_mem;
Packit Service 97d2fb
  Dwarf_Attribute *attr = dwarf_attr (instance, DW_AT_entry_pc, &attr_mem);
Packit Service 97d2fb
  if (attr != NULL)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      if (dwarf_formaddr (attr, &entry) == 0)
Packit Service 97d2fb
	entry += info->dwbias;
Packit Service 97d2fb
      else
Packit Service 97d2fb
	printf (" (entrypc => %s)", dwarf_errmsg (-1));
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  if (lo != (Dwarf_Addr) -1 || hi != (Dwarf_Addr) -1)
Packit Service 97d2fb
    printf (" %#" PRIx64 "..%#" PRIx64, lo, hi);
Packit Service 97d2fb
  if (entry != (Dwarf_Addr) -1)
Packit Service 97d2fb
    printf (" => %#" PRIx64 "\n", entry);
Packit Service 97d2fb
  else
Packit Service 97d2fb
    puts ("");
Packit Service 97d2fb
Packit Service 97d2fb
  return DWARF_CB_OK;
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
static void
Packit Service 97d2fb
print_inline (Dwarf_Die *func, void *arg)
Packit Service 97d2fb
{
Packit Service 97d2fb
  if (dwarf_func_inline_instances (func, &print_instance, arg) != 0)
Packit Service 97d2fb
    printf ("  error finding instances: %s\n", dwarf_errmsg (-1));
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
static int
Packit Service 97d2fb
print_func (Dwarf_Die *func, void *arg)
Packit Service 97d2fb
{
Packit Service 97d2fb
  const struct info *info = arg;
Packit Service 97d2fb
Packit Service 97d2fb
  const char *file = dwarf_decl_file (func);
Packit Service 97d2fb
  int line = -1;
Packit Service 97d2fb
  dwarf_decl_line (func, &line);
Packit Service 97d2fb
  const char *fct = dwarf_diename (func);
Packit Service 97d2fb
Packit Service 97d2fb
  printf ("  %s:%d: %s:", file, line, fct);
Packit Service 97d2fb
Packit Service 97d2fb
  if (dwarf_func_inline (func))
Packit Service 97d2fb
    {
Packit Service 97d2fb
      puts (" inline function");
Packit Service 97d2fb
      if (show_inlines)
Packit Service 97d2fb
	print_inline (func, arg);
Packit Service 97d2fb
    }
Packit Service 97d2fb
  else
Packit Service 97d2fb
    {
Packit Service 97d2fb
      Dwarf_Addr lo = -1, hi = -1, entry = -1;
Packit Service 97d2fb
      if (dwarf_lowpc (func, &lo) == 0)
Packit Service 97d2fb
	lo += info->dwbias;
Packit Service 97d2fb
      else
Packit Service 97d2fb
	printf (" (lowpc => %s)", dwarf_errmsg (-1));
Packit Service 97d2fb
      if (dwarf_highpc (func, &hi) == 0)
Packit Service 97d2fb
	hi += info->dwbias;
Packit Service 97d2fb
      else
Packit Service 97d2fb
	printf (" (highpc => %s)", dwarf_errmsg (-1));
Packit Service 97d2fb
      if (dwarf_entrypc (func, &entry) == 0)
Packit Service 97d2fb
	entry += info->dwbias;
Packit Service 97d2fb
      else
Packit Service 97d2fb
	printf (" (entrypc => %s)", dwarf_errmsg (-1));
Packit Service 97d2fb
Packit Service 97d2fb
      if (lo != (Dwarf_Addr) -1 || hi != (Dwarf_Addr) -1
Packit Service 97d2fb
	  || entry != (Dwarf_Addr) -1)
Packit Service 97d2fb
	printf (" %#" PRIx64 "..%#" PRIx64 " => %#" PRIx64 "\n",
Packit Service 97d2fb
		lo, hi, entry);
Packit Service 97d2fb
      else
Packit Service 97d2fb
	puts ("");
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  return DWARF_CB_OK;
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
static int
Packit Service 97d2fb
list_module (Dwfl_Module *mod __attribute__ ((unused)),
Packit Service 97d2fb
	     void **userdata __attribute__ ((unused)),
Packit Service 97d2fb
	     const char *name, Dwarf_Addr base,
Packit Service 97d2fb
	     void *arg __attribute__ ((unused)))
Packit Service 97d2fb
{
Packit Service 97d2fb
  Dwarf_Addr start;
Packit Service 97d2fb
  Dwarf_Addr end;
Packit Service 97d2fb
  const char *file;
Packit Service 97d2fb
  const char *debug;
Packit Service 97d2fb
  if (dwfl_module_info (mod, NULL, &start, &end,
Packit Service 97d2fb
			NULL, NULL, &file, &debug) != name
Packit Service 97d2fb
      || start != base)
Packit Service 97d2fb
    abort ();
Packit Service 97d2fb
  printf ("module: %30s %08" PRIx64 "..%08" PRIx64 " %s %s\n",
Packit Service 97d2fb
	  name, start, end, file, debug);
Packit Service 97d2fb
  return DWARF_CB_OK;
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
static int
Packit Service 97d2fb
print_module (Dwfl_Module *mod __attribute__ ((unused)),
Packit Service 97d2fb
	      void **userdata __attribute__ ((unused)),
Packit Service 97d2fb
	      const char *name, Dwarf_Addr base,
Packit Service 97d2fb
	      Dwarf *dw, Dwarf_Addr bias,
Packit Service 97d2fb
	      void *arg)
Packit Service 97d2fb
{
Packit Service 97d2fb
  printf ("module: %30s %08" PRIx64 " %s %" PRIx64 " (%s)\n",
Packit Service 97d2fb
	  name, base, dw == NULL ? "no" : "DWARF", bias, dwfl_errmsg (-1));
Packit Service 97d2fb
Packit Service 97d2fb
  if (dw != NULL && *(const bool *) arg)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      Dwarf_Off off = 0;
Packit Service 97d2fb
      size_t cuhl;
Packit Service 97d2fb
      Dwarf_Off noff;
Packit Service 97d2fb
Packit Service 97d2fb
      while (dwarf_nextcu (dw, off, &noff, &cuhl, NULL, NULL, NULL) == 0)
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  Dwarf_Die die_mem;
Packit Service 97d2fb
	  struct info info = { dwarf_offdie (dw, off + cuhl, &die_mem), bias };
Packit Service 97d2fb
	  (void) dwarf_getfuncs (info.cudie, print_func, &info, 0);
Packit Service 97d2fb
Packit Service 97d2fb
	  off = noff;
Packit Service 97d2fb
	}
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  return DWARF_CB_OK;
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
static bool show_functions;
Packit Service 97d2fb
Packit Service 97d2fb
/* gettext helper macro.  */
Packit Service 97d2fb
#undef	N_
Packit Service 97d2fb
#define N_(Str) Str
Packit Service 97d2fb
Packit Service 97d2fb
static const struct argp_option options[] =
Packit Service 97d2fb
  {
Packit Service 97d2fb
    { "functions", 'f', NULL, 0, N_("Additionally show function names"), 0 },
Packit Service 97d2fb
    { "inlines", 'i', NULL, 0, N_("Show instances of inlined functions"), 0 },
Packit Service 97d2fb
    { NULL, 0, NULL, 0, NULL, 0 }
Packit Service 97d2fb
  };
Packit Service 97d2fb
Packit Service 97d2fb
static error_t
Packit Service 97d2fb
parse_opt (int key, char *arg __attribute__ ((unused)),
Packit Service 97d2fb
	   struct argp_state *state __attribute__ ((unused)))
Packit Service 97d2fb
{
Packit Service 97d2fb
  switch (key)
Packit Service 97d2fb
    {
Packit Service 97d2fb
    case ARGP_KEY_INIT:
Packit Service 97d2fb
      state->child_inputs[0] = state->input;
Packit Service 97d2fb
      break;
Packit Service 97d2fb
Packit Service 97d2fb
    case 'f':
Packit Service 97d2fb
      show_functions = true;
Packit Service 97d2fb
      break;
Packit Service 97d2fb
Packit Service 97d2fb
    case 'i':
Packit Service 97d2fb
      show_inlines = show_functions = true;
Packit Service 97d2fb
      break;
Packit Service 97d2fb
Packit Service 97d2fb
    default:
Packit Service 97d2fb
      return ARGP_ERR_UNKNOWN;
Packit Service 97d2fb
    }
Packit Service 97d2fb
  return 0;
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
int
Packit Service 97d2fb
main (int argc, char **argv)
Packit Service 97d2fb
{
Packit Service 97d2fb
  /* We use no threads here which can interfere with handling a stream.  */
Packit Service 97d2fb
  (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER);
Packit Service 97d2fb
Packit Service 97d2fb
  /* Set locale.  */
Packit Service 97d2fb
  (void) setlocale (LC_ALL, "");
Packit Service 97d2fb
Packit Service 97d2fb
  Dwfl *dwfl = NULL;
Packit Service 97d2fb
  const struct argp_child argp_children[] =
Packit Service 97d2fb
    {
Packit Service 97d2fb
      { .argp = dwfl_standard_argp () },
Packit Service 97d2fb
      { .argp = NULL }
Packit Service 97d2fb
    };
Packit Service 97d2fb
  const struct argp argp =
Packit Service 97d2fb
    {
Packit Service 97d2fb
      options, parse_opt, NULL, NULL, argp_children, NULL, NULL
Packit Service 97d2fb
    };
Packit Service 97d2fb
  (void) argp_parse (&argp, argc, argv, 0, NULL, &dwfl);
Packit Service 97d2fb
  assert (dwfl != NULL);
Packit Service 97d2fb
Packit Service 97d2fb
  ptrdiff_t p = 0;
Packit Service 97d2fb
  do
Packit Service 97d2fb
    p = dwfl_getmodules (dwfl, &list_module, NULL, p);
Packit Service 97d2fb
  while (p > 0);
Packit Service 97d2fb
  if (p < 0)
Packit Service 97d2fb
    error (2, 0, "dwfl_getmodules: %s", dwfl_errmsg (-1));
Packit Service 97d2fb
Packit Service 97d2fb
  do
Packit Service 97d2fb
    p = dwfl_getdwarf (dwfl, &print_module, &show_functions, p);
Packit Service 97d2fb
  while (p > 0);
Packit Service 97d2fb
  if (p < 0)
Packit Service 97d2fb
    error (2, 0, "dwfl_getdwarf: %s", dwfl_errmsg (-1));
Packit Service 97d2fb
Packit Service 97d2fb
  p = 0;
Packit Service 97d2fb
  do
Packit Service 97d2fb
    p = dwfl_getmodules (dwfl, &list_module, NULL, p);
Packit Service 97d2fb
  while (p > 0);
Packit Service 97d2fb
  if (p < 0)
Packit Service 97d2fb
    error (2, 0, "dwfl_getmodules: %s", dwfl_errmsg (-1));
Packit Service 97d2fb
Packit Service 97d2fb
  dwfl_end (dwfl);
Packit Service 97d2fb
Packit Service 97d2fb
  return 0;
Packit Service 97d2fb
}