Blame tests/backtrace-dwarf.c

Packit Service 97d2fb
/* Test program for unwinding of complicated DWARF expressions.
Packit Service 97d2fb
   Copyright (C) 2013, 2015, 2018 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 <inttypes.h>
Packit Service 97d2fb
#include <stdio_ext.h>
Packit Service 97d2fb
#include <locale.h>
Packit Service 97d2fb
#include <errno.h>
Packit Service 97d2fb
#include <unistd.h>
Packit Service 97d2fb
#include <sys/types.h>
Packit Service 97d2fb
#include ELFUTILS_HEADER(dwfl)
Packit Service 97d2fb
#include "system.h"
Packit Service 97d2fb
Packit Service 97d2fb
#ifndef __linux__
Packit Service 97d2fb
Packit Service 97d2fb
int
Packit Service 97d2fb
main (int argc __attribute__ ((unused)), char **argv)
Packit Service 97d2fb
{
Packit Service 97d2fb
  fprintf (stderr, "%s: Unwinding not supported for this architecture\n",
Packit Service 97d2fb
           argv[0]);
Packit Service 97d2fb
  return 77;
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
#else /* __linux__ */
Packit Service 97d2fb
#include <sys/ptrace.h>
Packit Service 97d2fb
#include <sys/wait.h>
Packit Service 97d2fb
#include <signal.h>
Packit Service 97d2fb
Packit Service 97d2fb
#define main cleanup_13_main
Packit Service 97d2fb
#include "cleanup-13.c"
Packit Service 97d2fb
#undef main
Packit Service 97d2fb
Packit Service 97d2fb
static void
Packit Service 97d2fb
report_pid (Dwfl *dwfl, pid_t pid)
Packit Service 97d2fb
{
Packit Service 97d2fb
  int result = dwfl_linux_proc_report (dwfl, pid);
Packit Service 97d2fb
  if (result < 0)
Packit Service 97d2fb
    error (2, 0, "dwfl_linux_proc_report: %s", dwfl_errmsg (-1));
Packit Service 97d2fb
  else if (result > 0)
Packit Service 97d2fb
    error (2, result, "dwfl_linux_proc_report");
Packit Service 97d2fb
Packit Service 97d2fb
  if (dwfl_report_end (dwfl, NULL, NULL) != 0)
Packit Service 97d2fb
    error (2, 0, "dwfl_report_end: %s", dwfl_errmsg (-1));
Packit Service 97d2fb
Packit Service 97d2fb
  result = dwfl_linux_proc_attach (dwfl, pid, true);
Packit Service 97d2fb
  if (result < 0)
Packit Service 97d2fb
    error (2, 0, "dwfl_linux_proc_attach: %s", dwfl_errmsg (-1));
Packit Service 97d2fb
  else if (result > 0)
Packit Service 97d2fb
    error (2, result, "dwfl_linux_proc_attach");
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
static Dwfl *
Packit Service 97d2fb
pid_to_dwfl (pid_t pid)
Packit Service 97d2fb
{
Packit Service 97d2fb
  static char *debuginfo_path;
Packit Service 97d2fb
  static const Dwfl_Callbacks proc_callbacks =
Packit Service 97d2fb
    {
Packit Service 97d2fb
      .find_debuginfo = dwfl_standard_find_debuginfo,
Packit Service 97d2fb
      .debuginfo_path = &debuginfo_path,
Packit Service 97d2fb
Packit Service 97d2fb
      .find_elf = dwfl_linux_proc_find_elf,
Packit Service 97d2fb
    };
Packit Service 97d2fb
  Dwfl *dwfl = dwfl_begin (&proc_callbacks);
Packit Service 97d2fb
  if (dwfl == NULL)
Packit Service 97d2fb
    error (2, 0, "dwfl_begin: %s", dwfl_errmsg (-1));
Packit Service 97d2fb
  report_pid (dwfl, pid);
Packit Service 97d2fb
  return dwfl;
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
static int
Packit Service 97d2fb
frame_callback (Dwfl_Frame *state, void *frame_arg)
Packit Service 97d2fb
{
Packit Service 97d2fb
  Dwarf_Addr pc;
Packit Service 97d2fb
  bool isactivation;
Packit Service 97d2fb
  if (! dwfl_frame_pc (state, &pc, &isactivation))
Packit Service 97d2fb
    {
Packit Service 97d2fb
      error (0, 0, "%s", dwfl_errmsg (-1));
Packit Service 97d2fb
      return DWARF_CB_ABORT;
Packit Service 97d2fb
    }
Packit Service 97d2fb
  Dwarf_Addr pc_adjusted = pc - (isactivation ? 0 : 1);
Packit Service 97d2fb
Packit Service 97d2fb
  /* Get PC->SYMNAME.  */
Packit Service 97d2fb
  Dwfl_Thread *thread = dwfl_frame_thread (state);
Packit Service 97d2fb
  Dwfl *dwfl = dwfl_thread_dwfl (thread);
Packit Service 97d2fb
  Dwfl_Module *mod = dwfl_addrmodule (dwfl, pc_adjusted);
Packit Service 97d2fb
  const char *symname = NULL;
Packit Service 97d2fb
  if (mod)
Packit Service 97d2fb
    symname = dwfl_module_addrname (mod, pc_adjusted);
Packit Service 97d2fb
Packit Service 97d2fb
  printf ("%#" PRIx64 "\t%s\n", (uint64_t) pc, symname ?: "<null>");
Packit Service 97d2fb
Packit Service 97d2fb
  if (symname && (strcmp (symname, "main") == 0
Packit Service 97d2fb
		  || strcmp (symname, ".main") == 0))
Packit Service 97d2fb
    {
Packit Service 97d2fb
      kill (dwfl_pid (dwfl), SIGKILL);
Packit Service 97d2fb
      exit (0);
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
thread_callback (Dwfl_Thread *thread, void *thread_arg)
Packit Service 97d2fb
{
Packit Service 97d2fb
  if (dwfl_thread_getframes (thread, frame_callback, NULL) == -1)
Packit Service 97d2fb
    error (1, 0, "dwfl_thread_getframes: %s", dwfl_errmsg (-1));
Packit Service 97d2fb
Packit Service 97d2fb
  /* frame_callback shall exit (0) on success.  */
Packit Service 97d2fb
  printf ("dwfl_thread_getframes returned, main not found\n");
Packit Service 97d2fb
  return DWARF_CB_ABORT;
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
int
Packit Service 97d2fb
__attribute__((section(".main"))) /* Defeat -freorder-blocks-and-partition  */
Packit Service 97d2fb
main (int argc __attribute__ ((unused)), char **argv)
Packit Service 97d2fb
{
Packit Service 97d2fb
  /* We use no threads here which can interfere with handling a stream.  */
Packit Service 97d2fb
  __fsetlocking (stdin, FSETLOCKING_BYCALLER);
Packit Service 97d2fb
  __fsetlocking (stdout, FSETLOCKING_BYCALLER);
Packit Service 97d2fb
  __fsetlocking (stderr, FSETLOCKING_BYCALLER);
Packit Service 97d2fb
Packit Service 97d2fb
  /* Set locale.  */
Packit Service 97d2fb
  (void) setlocale (LC_ALL, "");
Packit Service 97d2fb
Packit Service 97d2fb
  elf_version (EV_CURRENT);
Packit Service 97d2fb
Packit Service 97d2fb
  pid_t pid = fork ();
Packit Service 97d2fb
  switch (pid)
Packit Service 97d2fb
  {
Packit Service 97d2fb
    case -1:
Packit Service 97d2fb
      perror ("fork failed");
Packit Service 97d2fb
      exit (-1);
Packit Service 97d2fb
    case 0:;
Packit Service 97d2fb
      long l = ptrace (PTRACE_TRACEME, 0, NULL, NULL);
Packit Service 97d2fb
      if (l != 0)
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  perror ("PTRACE_TRACEME failed");
Packit Service 97d2fb
	  exit (-1);
Packit Service 97d2fb
	}
Packit Service 97d2fb
      cleanup_13_main ();
Packit Service 97d2fb
      printf ("cleanup_13_main returned, impossible...\n");
Packit Service 97d2fb
      exit (-1);
Packit Service 97d2fb
    default:
Packit Service 97d2fb
      break;
Packit Service 97d2fb
  }
Packit Service 97d2fb
Packit Service 97d2fb
  errno = 0;
Packit Service 97d2fb
  int status;
Packit Service 97d2fb
  pid_t got = waitpid (pid, &status, 0);
Packit Service 97d2fb
  if (got != pid)
Packit Service 97d2fb
    error (1, errno, "waitpid returned %d", got);
Packit Service 97d2fb
  if (!WIFSTOPPED (status))
Packit Service 97d2fb
    error (1, 0, "unexpected wait status %u", status);
Packit Service 97d2fb
  if (WSTOPSIG (status) != SIGABRT)
Packit Service 97d2fb
    error (1, 0, "unexpected signal %u", WSTOPSIG (status));
Packit Service 97d2fb
Packit Service 97d2fb
  Dwfl *dwfl = pid_to_dwfl (pid);
Packit Service 97d2fb
  if (dwfl_getthreads (dwfl, thread_callback, NULL) == -1)
Packit Service 97d2fb
    error (1, 0, "dwfl_getthreads: %s", dwfl_errmsg (-1));
Packit Service 97d2fb
Packit Service 97d2fb
  /* There is an exit (0) call if we find the "main" frame,  */
Packit Service 97d2fb
  printf ("dwfl_getthreads returned, main not found\n");
Packit Service 97d2fb
  exit (-1);
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
#endif /* ! __linux__ */
Packit Service 97d2fb