This is the mail archive of the elfutils-devel@sourceware.org mailing list for the elfutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch v6 4/5] x86* unwinder: src/


src/
2013-06-23  Jan Kratochvil  <jan.kratochvil@redhat.com>
	    Mark Wielaard  <mjw@redhat.com>

	* Makefile.am (bin_PROGRAMS): Add stack.
	(stack_LDADD): New.
	* stack.c: New file.

Signed-off-by: Jan Kratochvil <jan.kratochvil@redhat.com>

--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,6 +1,6 @@
 ## Process this file with automake to create Makefile.in
 ##
-## Copyright (C) 1996-2012 Red Hat, Inc.
+## Copyright (C) 1996-2013 Red Hat, Inc.
 ## This file is part of elfutils.
 ##
 ## This file is free software; you can redistribute it and/or modify
@@ -37,7 +37,7 @@ native_ld = @native_ld@
 base_cpu = @base_cpu@
 
 bin_PROGRAMS = readelf nm size strip ld elflint findtextrel addr2line \
-	       elfcmp objdump ranlib strings ar unstrip
+	       elfcmp objdump ranlib strings ar unstrip stack
 
 
 ld_dsos = libld_elf_i386_pic.a
@@ -115,6 +115,7 @@ ranlib_LDADD = libar.a $(libelf) $(libeu) $(libmudflap)
 strings_LDADD = $(libelf) $(libeu) $(libmudflap)
 ar_LDADD = libar.a $(libelf) $(libeu) $(libmudflap)
 unstrip_LDADD = $(libebl) $(libelf) $(libdw) $(libeu) $(libmudflap) -ldl
+stack_LDADD = $(libebl) $(libelf) $(libdw) $(libeu) $(libmudflap) -ldl
 
 ldlex.o: ldscript.c
 ldlex_no_Werror = yes
--- /dev/null
+++ b/src/stack.c
@@ -0,0 +1,180 @@
+/* Unwinding of frames like gstack/pstack.
+   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 <argp.h>
+#include <error.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <locale.h>
+#include <fcntl.h>
+#include ELFUTILS_HEADER(dwfl)
+
+/* libdwfl/argp-std.c */
+#define OPT_COREFILE    0x101
+
+static void
+report_pid (Dwfl *dwfl, pid_t pid)
+{
+  int result = dwfl_linux_proc_report (dwfl, pid);
+  if (result < 0)
+    error (2, 0, "dwfl_linux_proc_report: %s", dwfl_errmsg (-1));
+  else if (result > 0)
+    error (2, result, "dwfl_linux_proc_report");
+
+  if (dwfl_report_end (dwfl, NULL, NULL) != 0)
+    error (2, 0, "dwfl_report_end: %s", dwfl_errmsg (-1));
+}
+
+static Dwfl *
+report_corefile (Dwfl *dwfl, const char *corefile)
+{
+  int fd = open64 (corefile, O_RDONLY);
+  if (fd == -1)
+    error (2, 0, "open64: %m");
+  Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
+  if (elf == NULL)
+    error (2, 0, "elf_begin: %s", elf_errmsg (-1));
+  if (dwfl_core_file_report (dwfl, elf) < 0)
+    error (2, 0, "dwfl_core_file_report: %s", dwfl_errmsg (-1));
+  if (dwfl_report_end (dwfl, NULL, NULL) != 0)
+    error (2, 0, "dwfl_report_end: %s", dwfl_errmsg (-1));
+  /* ELF and CORE are leaked.  */
+  return dwfl;
+}
+
+static int
+frame_callback (Dwfl_Frame *state, void *arg)
+{
+  unsigned *framenop = arg;
+  Dwarf_Addr pc;
+  bool isactivation;
+  if (! dwfl_frame_pc (state, &pc, &isactivation))
+    {
+      error (0, 0, "%s", dwfl_errmsg (-1));
+      return 1;
+    }
+  Dwarf_Addr pc_adjusted = pc - (isactivation ? 0 : 1);
+
+  /* Get PC->SYMNAME.  */
+  Dwfl *dwfl = dwfl_thread_dwfl (dwfl_frame_thread (state));
+  Dwfl_Module *mod = dwfl_addrmodule (dwfl, pc_adjusted);
+  const char *symname = NULL;
+  if (mod)
+    symname = dwfl_module_addrname (mod, pc_adjusted);
+
+  printf ("#%2u %#" PRIx64 "%4s\t%s\n", (*framenop)++, (uint64_t) pc,
+	  ! isactivation ? "- 1" : "", symname);
+  return DWARF_CB_OK;
+}
+
+static void
+dump (Dwfl *dwfl, pid_t pid, const char *corefile)
+{
+  if (pid)
+    report_pid (dwfl, pid);
+  else if (corefile)
+    report_corefile (dwfl, corefile);
+  else
+    abort ();
+  Dwfl_Thread *thread = NULL;
+  for (;;)
+    {
+      thread = dwfl_next_thread (dwfl, thread);
+      if (thread == NULL)
+	{
+	  const char *msg = dwfl_errmsg (0);
+	  if (msg == NULL)
+	    break;
+	  error (2, 0, "dwfl_next_thread: %s", msg);
+	}
+      printf ("TID %ld:\n", (long) dwfl_thread_tid (thread));
+      unsigned frameno = 0;
+      switch (dwfl_thread_getframes (thread, frame_callback, &frameno))
+	{
+	case 0:
+	case 1:
+	  break;
+	case -1:
+	  error (0, 0, "dwfl_thread_getframes: %s", dwfl_errmsg (-1));
+	  break;
+	default:
+	  abort ();
+	}
+    }
+  dwfl_end (dwfl);
+}
+
+static argp_parser_t parse_opt_orig;
+static pid_t pid;
+static const char *corefile;
+
+static error_t
+parse_opt (int key, char *arg, struct argp_state *state)
+{
+  switch (key)
+    {
+    case 'p':
+      pid = atoi (arg);
+      break;
+    case OPT_COREFILE:
+      corefile = arg;
+      break;
+    }
+  return parse_opt_orig (key, arg, state);
+}
+
+static void
+usage (void)
+{
+  error (2, 0, "eu-stack [--debuginfo-path=<path>] {-p <process id>|"
+               "--core=<file> [--executable=<file>]|--help}");
+}
+
+int
+main (int argc, char **argv)
+{
+  /* We use no threads here which can interfere with handling a stream.  */
+  __fsetlocking (stdin, FSETLOCKING_BYCALLER);
+  __fsetlocking (stdout, FSETLOCKING_BYCALLER);
+  __fsetlocking (stderr, FSETLOCKING_BYCALLER);
+
+  /* Set locale.  */
+  (void) setlocale (LC_ALL, "");
+
+  struct argp argp = *dwfl_standard_argp ();
+  parse_opt_orig = argp.parser;
+  argp.parser = parse_opt;
+  int remaining;
+  Dwfl *dwfl = NULL;
+  argp_parse (&argp, argc, argv, 0, &remaining, &dwfl);
+  assert (dwfl != NULL);
+  if (remaining != argc)
+    usage ();
+
+  if (pid && !corefile)
+    dump (dwfl, pid, NULL);
+  else if (corefile && !pid)
+    dump (dwfl, 0, corefile);
+  else
+    usage ();
+
+  return 0;
+}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]