19e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura/* libunwind - a platform-independent unwind library
23b9fd99cb78383e0ce8cd1a31e3b824a30ef965eLassi Tuura   Copyright (C) 2010, 2011 by FERMI NATIONAL ACCELERATOR LABORATORY
39e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura
49e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi TuuraPermission is hereby granted, free of charge, to any person obtaining
59e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuuraa copy of this software and associated documentation files (the
69e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura"Software"), to deal in the Software without restriction, including
79e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuurawithout limitation the rights to use, copy, modify, merge, publish,
89e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuuradistribute, sublicense, and/or sell copies of the Software, and to
99e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuurapermit persons to whom the Software is furnished to do so, subject to
109e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuurathe following conditions:
119e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura
129e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi TuuraThe above copyright notice and this permission notice shall be
139e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuuraincluded in all copies or substantial portions of the Software.
149e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura
159e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi TuuraTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
169e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi TuuraEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
179e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi TuuraMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
189e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi TuuraNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
199e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi TuuraLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
209e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi TuuraOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
219e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi TuuraWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
229e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura
239e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura#ifdef HAVE_CONFIG_H
249e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura# include "config.h"
259e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura#endif
269e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura
277673df21ffea216bcdee9efc551cfc4462ea35e9Tommi Rantala#include "compiler.h"
287673df21ffea216bcdee9efc551cfc4462ea35e9Tommi Rantala
299e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura#include <errno.h>
309e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura#if HAVE_EXECINFO_H
319e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura# include <execinfo.h>
329e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura#else
339e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  extern int backtrace (void **, int);
349e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura#endif
359e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura#include <signal.h>
369e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura#include <stdio.h>
379e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura#include <stdlib.h>
389e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura#include <string.h>
399e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura#include <unistd.h>
409e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura#include <libunwind.h>
419e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura
429e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura#define panic(args...)				\
439e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura	{ fprintf (stderr, args); exit (-1); }
449e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura
45e4593e2493923f93dfa6c92ee5327b4ce577a818Ken Werner#define SIG_STACK_SIZE 0x100000
46e4593e2493923f93dfa6c92ee5327b4ce577a818Ken Werner
479e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuuraint verbose;
489e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuuraint num_errors;
499e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura
509e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura/* These variables are global because they
519e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura * cause the signal stack to overflow */
529e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuurachar buf[512], name[256];
535f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuuravoid *addresses[3][128];
549e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuuraunw_cursor_t cursor;
554bf1b7195223ea68c7ed6a24f4f826be02d8bec0Tommi Rantalaunw_context_t uc;
569e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura
579e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuurastatic void
589e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuurado_backtrace (void)
599e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura{
609e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  unw_word_t ip;
619e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  int ret = -UNW_ENOINFO;
625f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura  int depth = 0;
635f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura  int i, n, m;
649e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura
659e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  if (verbose)
665f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura    printf ("\tnormal trace:\n");
679e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura
689e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  unw_getcontext (&uc);
699e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  if (unw_init_local (&cursor, &uc) < 0)
709e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura    panic ("unw_init_local failed!\n");
719e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura
725f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura  do
739e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura    {
749e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura      unw_get_reg (&cursor, UNW_REG_IP, &ip);
755f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura      addresses[0][depth] = (void *) ip;
769e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura    }
775f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura  while ((ret = unw_step (&cursor)) > 0 && ++depth < 128);
789e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura
799e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  if (ret < 0)
809e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura    {
815f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura      unw_get_reg (&cursor, UNW_REG_IP, &ip);
825f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura      printf ("FAILURE: unw_step() returned %d for ip=%lx\n", ret, (long) ip);
835f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura      ++num_errors;
849e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura    }
859e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura
869e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  if (verbose)
879e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura    for (i = 0; i < depth; ++i)
889e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura      printf ("\t #%-3d ip=%p\n", i, addresses[0][i]);
899e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura
909e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  if (verbose)
919e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura    printf ("\n\tvia backtrace():\n");
929e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura
939e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  n = backtrace (addresses[1], 128);
949e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura
959e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  if (verbose)
969e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura    for (i = 0; i < n; ++i)
979e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura	printf ("\t #%-3d ip=%p\n", i, addresses[1][i]);
989e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura
995f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura  if (verbose)
1005f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura    printf ("\n\tvia unw_backtrace():\n");
1015f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura
1025f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura  m = unw_backtrace (addresses[2], 128);
1035f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura
1045f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura  if (verbose)
1055f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura    for (i = 0; i < m; ++i)
1065f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura	printf ("\t #%-3d ip=%p\n", i, addresses[2][i]);
1075f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura
1085f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura  if (m != depth+1)
1099e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura    {
1105f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura      printf ("FAILURE: unw_step() loop and unw_backtrace() depths differ: %d vs. %d\n", depth, m);
1119e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura      ++num_errors;
1129e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura    }
1135f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura
1145f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura  if (n != depth+1)
1155f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura    {
1165f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura      printf ("FAILURE: unw_step() loop and backtrace() depths differ: %d vs. %d\n", depth, n);
1175f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura      ++num_errors;
1185f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura    }
1195f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura
1205f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura  if (n == m)
1215f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura    for (i = 1; i < n; ++i)
1225f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura      /* Allow one in difference in comparison, trace returns adjusted addresses. */
1235f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura      if (labs((unw_word_t) addresses[1][i] - (unw_word_t) addresses[2][i]) > 1)
1245f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura	{
1255f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura          printf ("FAILURE: backtrace() and unw_backtrace() addresses differ at %d: %p vs. %p\n",
1265f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura		  i, addresses[1][n], addresses[2][n]);
1275f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura          ++num_errors;
1285f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura	}
1295f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura
1305f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura  if (n == depth+1)
1319e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura    for (i = 1; i < depth; ++i)
1329e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura      /* Allow one in difference in comparison, trace returns adjusted addresses. */
1339e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura      if (labs((unw_word_t) addresses[0][i] - (unw_word_t) addresses[1][i]) > 1)
1349e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura	{
1355f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura          printf ("FAILURE: unw_step() loop and backtrace() addresses differ at %d: %p vs. %p\n",
1369e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura		  i, addresses[0][n], addresses[1][n]);
1379e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura          ++num_errors;
1389e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura	}
1399e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura}
1409e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura
1419e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuuravoid
1426b55e0ab51eee7dbea679fda2b37ecf61f0025e5Tommi Rantalafoo (long val UNUSED)
1439e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura{
1449e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  do_backtrace ();
1459e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura}
1469e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura
1479e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuuravoid
1489e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuurabar (long v)
1499e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura{
1509e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  extern long f (long);
1519e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  int arr[v];
1529e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura
1539e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  /* This is a vain attempt to use up lots of registers to force
1549e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura     the frame-chain info to be saved on the memory stack on ia64.
1559e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura     It happens to work with gcc v3.3.4 and gcc v3.4.1 but perhaps
1569e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura     not with any other compiler.  */
1579e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  foo (f (arr[0]) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
1589e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura       + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
1599e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura       + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
1609e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura       + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
1619e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura       + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
1629e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura       + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
1639e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura       + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
1649e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura       + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
1659e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura       + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
1669e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura       + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
1679e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura       + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
1689e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura       + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
1699e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura       + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
1709e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura       + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
1719e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura       + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
1729e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura       + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v)
1739e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura       + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + (f (v) + f (v))
1749e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura       ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
1759e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura       )))))))))))))))))))))))))))))))))))))))))))))))))))))));
1769e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura}
1779e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura
1789e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuuravoid
1796b55e0ab51eee7dbea679fda2b37ecf61f0025e5Tommi Rantalasighandler (int signal, void *siginfo UNUSED, void *context)
1809e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura{
1817673df21ffea216bcdee9efc551cfc4462ea35e9Tommi Rantala  ucontext_t *uc UNUSED;
1829e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  int sp;
1839e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura
1847673df21ffea216bcdee9efc551cfc4462ea35e9Tommi Rantala  uc = context;
1857673df21ffea216bcdee9efc551cfc4462ea35e9Tommi Rantala
1869e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  if (verbose)
1879e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura    {
1889e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura      printf ("sighandler: got signal %d, sp=%p", signal, &sp);
1899e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura#if UNW_TARGET_IA64
1909e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura# if defined(__linux__)
1919e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura      printf (" @ %lx", uc->uc_mcontext.sc_ip);
1929e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura# else
1939e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura      {
1949e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura	uint16_t reason;
1959e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura	uint64_t ip;
1969e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura
1979e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura	__uc_get_reason (uc, &reason);
1989e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura	__uc_get_ip (uc, &ip);
1999e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura	printf (" @ %lx (reason=%d)", ip, reason);
2009e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura      }
2019e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura# endif
2029e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura#elif UNW_TARGET_X86
2039e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura#if defined __linux__
2049e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura      printf (" @ %lx", (unsigned long) uc->uc_mcontext.gregs[REG_EIP]);
2059e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura#elif defined __FreeBSD__
2069e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura      printf (" @ %lx", (unsigned long) uc->uc_mcontext.mc_eip);
2079e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura#endif
2089e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura#elif UNW_TARGET_X86_64
2099e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura#if defined __linux__
2109e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura      printf (" @ %lx", (unsigned long) uc->uc_mcontext.gregs[REG_RIP]);
2119e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura#elif defined __FreeBSD__
2129e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura      printf (" @ %lx", (unsigned long) uc->uc_mcontext.mc_rip);
2139e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura#endif
214a624812e2aef371b3901c44cc3201e5afdb01b60Ken Werner#elif defined UNW_TARGET_ARM
2159158e522db2f3d5675438b535000ce862259f14dTommi Rantala      printf (" @ %lx", (unsigned long) uc->uc_mcontext.arm_pc);
2169e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura#endif
2179e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura      printf ("\n");
2189e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura    }
2199e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  do_backtrace();
2209e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura}
2219e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura
2229e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuuraint
2236b55e0ab51eee7dbea679fda2b37ecf61f0025e5Tommi Rantalamain (int argc, char **argv UNUSED)
2249e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura{
2259e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  struct sigaction act;
2269e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  stack_t stk;
2279e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura
2289e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  verbose = (argc > 1);
2299e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura
2309e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  if (verbose)
2319e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura    printf ("Normal backtrace:\n");
2329e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura
2339e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  bar (1);
2349e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura
2359e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  memset (&act, 0, sizeof (act));
2369e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  act.sa_handler = (void (*)(int)) sighandler;
2379e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  act.sa_flags = SA_SIGINFO;
2389e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  if (sigaction (SIGTERM, &act, NULL) < 0)
2399e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura    panic ("sigaction: %s\n", strerror (errno));
2409e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura
2419e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  if (verbose)
2429e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura    printf ("\nBacktrace across signal handler:\n");
2439e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  kill (getpid (), SIGTERM);
2449e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura
2459e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  if (verbose)
2469e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura    printf ("\nBacktrace across signal handler on alternate stack:\n");
247e4593e2493923f93dfa6c92ee5327b4ce577a818Ken Werner  stk.ss_sp = malloc (SIG_STACK_SIZE);
2489e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  if (!stk.ss_sp)
249e4593e2493923f93dfa6c92ee5327b4ce577a818Ken Werner    panic ("failed to allocate %u bytes\n", SIG_STACK_SIZE);
250e4593e2493923f93dfa6c92ee5327b4ce577a818Ken Werner  stk.ss_size = SIG_STACK_SIZE;
2519e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  stk.ss_flags = 0;
2529e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  if (sigaltstack (&stk, NULL) < 0)
2539e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura    panic ("sigaltstack: %s\n", strerror (errno));
2549e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura
2559e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  memset (&act, 0, sizeof (act));
2569e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  act.sa_handler = (void (*)(int)) sighandler;
2579e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  act.sa_flags = SA_ONSTACK | SA_SIGINFO;
2589e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  if (sigaction (SIGTERM, &act, NULL) < 0)
2599e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura    panic ("sigaction: %s\n", strerror (errno));
2609e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  kill (getpid (), SIGTERM);
2619e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura
2629e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  if (num_errors > 0)
2639e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura    {
2649e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura      fprintf (stderr, "FAILURE: detected %d errors\n", num_errors);
2659e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura      exit (-1);
2669e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura    }
2679e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura
2689e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  if (verbose)
2699e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura    printf ("SUCCESS.\n");
2700d7738ed4f7dae1b6b77d1a4dd25c5ea765de81fTommi Rantala
2710d7738ed4f7dae1b6b77d1a4dd25c5ea765de81fTommi Rantala  signal (SIGTERM, SIG_DFL);
2720d7738ed4f7dae1b6b77d1a4dd25c5ea765de81fTommi Rantala  stk.ss_flags = SS_DISABLE;
2730d7738ed4f7dae1b6b77d1a4dd25c5ea765de81fTommi Rantala  sigaltstack (&stk, NULL);
2740d7738ed4f7dae1b6b77d1a4dd25c5ea765de81fTommi Rantala  free (stk.ss_sp);
2750d7738ed4f7dae1b6b77d1a4dd25c5ea765de81fTommi Rantala
2769e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  return 0;
2779e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura}
278