14471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm/* libunwind - a platform-independent unwind library 24471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm Copyright (C) 2004 Hewlett-Packard Co 34471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm Contributed by David Mosberger-Tang <davidm@hpl.hp.com> 44471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm 54471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidmPermission is hereby granted, free of charge, to any person obtaining 64471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidma copy of this software and associated documentation files (the 74471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm"Software"), to deal in the Software without restriction, including 84471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidmwithout limitation the rights to use, copy, modify, merge, publish, 94471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidmdistribute, sublicense, and/or sell copies of the Software, and to 104471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidmpermit persons to whom the Software is furnished to do so, subject to 114471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidmthe following conditions: 124471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm 134471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidmThe above copyright notice and this permission notice shall be 144471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidmincluded in all copies or substantial portions of the Software. 154471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm 164471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidmTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 174471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidmEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 184471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidmMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 194471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidmNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 204471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidmLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 214471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidmOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 224471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidmWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 234471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm 244471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm/* Check whether basic unwinding truly is async-signal safe. */ 254471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm 26459b2a5ba89c3ae0002e741cadbc723e4b1dd0a6Konstantin Belousov#ifdef HAVE_CONFIG_H 27459b2a5ba89c3ae0002e741cadbc723e4b1dd0a6Konstantin Belousov#include "config.h" 28459b2a5ba89c3ae0002e741cadbc723e4b1dd0a6Konstantin Belousov#endif 29459b2a5ba89c3ae0002e741cadbc723e4b1dd0a6Konstantin Belousov 306b55e0ab51eee7dbea679fda2b37ecf61f0025e5Tommi Rantala#include "compiler.h" 316b55e0ab51eee7dbea679fda2b37ecf61f0025e5Tommi Rantala 32459b2a5ba89c3ae0002e741cadbc723e4b1dd0a6Konstantin Belousov#include <signal.h> 334471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm#include <stdio.h> 344471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm#include <stdlib.h> 354471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm#include <string.h> 364471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm#include <unistd.h> 374471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm 384471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm#include <sys/time.h> 394471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm 404471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm#define UNW_LOCAL_ONLY 414471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm#include <libunwind.h> 424471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm 435f3d29562d53b5e144787fbf1abe598c6822b20dDavid Mosberger-Tangstatic const int nerrors_max = 100; 445f3d29562d53b5e144787fbf1abe598c6822b20dDavid Mosberger-Tang 454471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidmstruct itimerval interval = 464471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm { 474471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm .it_interval = { .tv_sec = 0, .tv_usec = 0 }, 484471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm .it_value = { .tv_sec = 0, .tv_usec = 1000 } 494471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm }; 504471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm 514471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidmint verbose; 524471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidmint nerrors; 534471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidmint sigcount; 544471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm 55b7e3444fea7f19f05e1fe033b96efad394ab9b4aPaul Pluzhnikov#ifndef CONFIG_BLOCK_SIGNALS 56b7e3444fea7f19f05e1fe033b96efad394ab9b4aPaul Pluzhnikov/* When libunwind is configured with --enable-block-signals=no, the caller 57b7e3444fea7f19f05e1fe033b96efad394ab9b4aPaul Pluzhnikov is responsible for preventing recursion via signal handlers. 58b7e3444fea7f19f05e1fe033b96efad394ab9b4aPaul Pluzhnikov We use a simple global here. In a multithreaded program, one would use 59b7e3444fea7f19f05e1fe033b96efad394ab9b4aPaul Pluzhnikov a thread-local variable. */ 60b7e3444fea7f19f05e1fe033b96efad394ab9b4aPaul Pluzhnikovint recurcount; 61b7e3444fea7f19f05e1fe033b96efad394ab9b4aPaul Pluzhnikov#endif 62b7e3444fea7f19f05e1fe033b96efad394ab9b4aPaul Pluzhnikov 634471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm#define panic(args...) \ 644471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm { ++nerrors; fprintf (stderr, args); return; } 654471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm 664471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidmstatic void 674471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidmdo_backtrace (int may_print, int get_proc_name) 684471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm{ 694471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm char buf[512], name[256]; 704471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm unw_cursor_t cursor; 714471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm unw_word_t ip, sp, off; 724471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm unw_context_t uc; 734471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm int ret; 74a72abd4e46eb6e92747412fb036d0fb8279350acJan Kratochvil int depth = 0; 754471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm 76b7e3444fea7f19f05e1fe033b96efad394ab9b4aPaul Pluzhnikov#ifndef CONFIG_BLOCK_SIGNALS 77b7e3444fea7f19f05e1fe033b96efad394ab9b4aPaul Pluzhnikov if (recurcount > 0) 78b7e3444fea7f19f05e1fe033b96efad394ab9b4aPaul Pluzhnikov return; 79b7e3444fea7f19f05e1fe033b96efad394ab9b4aPaul Pluzhnikov recurcount += 1; 80b7e3444fea7f19f05e1fe033b96efad394ab9b4aPaul Pluzhnikov#endif 81b7e3444fea7f19f05e1fe033b96efad394ab9b4aPaul Pluzhnikov 824471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm unw_getcontext (&uc); 834471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm if (unw_init_local (&cursor, &uc) < 0) 844471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm panic ("unw_init_local failed!\n"); 854471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm 864471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm do 874471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm { 884471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm unw_get_reg (&cursor, UNW_REG_IP, &ip); 894471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm unw_get_reg (&cursor, UNW_REG_SP, &sp); 904471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm 914471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm buf[0] = '\0'; 924471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm if (get_proc_name || (may_print && verbose)) 934471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm { 94848ad53a47e8fbef24a6bf1b624d4ad9fb352fb8Tommi Rantala ret = unw_get_proc_name (&cursor, name, sizeof (name), &off); 95848ad53a47e8fbef24a6bf1b624d4ad9fb352fb8Tommi Rantala if (ret == 0 && (may_print && verbose)) 964471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm { 974471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm if (off) 984471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm snprintf (buf, sizeof (buf), "<%s+0x%lx>", name, (long) off); 994471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm else 1004471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm { 1014471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm size_t len = strlen (name); 1024471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm buf[0] = '<'; 1034471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm memcpy (buf + 1, name, len); 1044471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm buf[len + 1] = '>'; 1054471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm buf[len + 2] = '\0'; 1064471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm } 1074471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm } 1084471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm } 1094471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm 1104471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm if (may_print && verbose) 1114471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm printf ("%016lx %-32s (sp=%016lx)\n", (long) ip, buf, (long) sp); 1124471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm 1134471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm ret = unw_step (&cursor); 1144471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm if (ret < 0) 1154471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm { 1164471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm unw_get_reg (&cursor, UNW_REG_IP, &ip); 1174471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm panic ("FAILURE: unw_step() returned %d for ip=%lx\n", 1184471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm ret, (long) ip); 1194471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm } 120a72abd4e46eb6e92747412fb036d0fb8279350acJan Kratochvil if (depth++ > 100) 121a72abd4e46eb6e92747412fb036d0fb8279350acJan Kratochvil { 122a72abd4e46eb6e92747412fb036d0fb8279350acJan Kratochvil panic ("FAILURE: unw_step() looping over %d iterations\n", depth); 123a72abd4e46eb6e92747412fb036d0fb8279350acJan Kratochvil break; 124a72abd4e46eb6e92747412fb036d0fb8279350acJan Kratochvil } 1254471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm } 1264471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm while (ret > 0); 127b7e3444fea7f19f05e1fe033b96efad394ab9b4aPaul Pluzhnikov 128b7e3444fea7f19f05e1fe033b96efad394ab9b4aPaul Pluzhnikov#ifndef CONFIG_BLOCK_SIGNALS 129b7e3444fea7f19f05e1fe033b96efad394ab9b4aPaul Pluzhnikov recurcount -= 1; 130b7e3444fea7f19f05e1fe033b96efad394ab9b4aPaul Pluzhnikov#endif 1314471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm} 1324471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm 1334471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidmvoid 1344471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidmsighandler (int signal) 1354471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm{ 1364471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm if (verbose) 1374471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm printf ("sighandler(signal=%d, count=%d)\n", signal, sigcount); 1384471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm 1394471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm do_backtrace (1, 1); 1404471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm 1414471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm ++sigcount; 1424471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm 1434471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm if (sigcount == 100) 1444471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm unw_set_caching_policy (unw_local_addr_space, UNW_CACHE_GLOBAL); 1454471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm else if (sigcount == 200) 1464471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm unw_set_caching_policy (unw_local_addr_space, UNW_CACHE_PER_THREAD); 147a72abd4e46eb6e92747412fb036d0fb8279350acJan Kratochvil else if (sigcount == 300 || nerrors > nerrors_max) 1484471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm { 149a72abd4e46eb6e92747412fb036d0fb8279350acJan Kratochvil if (nerrors > nerrors_max) 150a72abd4e46eb6e92747412fb036d0fb8279350acJan Kratochvil panic ("Too many errors (%d)\n", nerrors); 1514471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm if (nerrors) 1524471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm { 1534471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm fprintf (stderr, "FAILURE: detected %d errors\n", nerrors); 1544471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm exit (-1); 1554471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm } 1564471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm if (verbose) 1574471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm printf ("SUCCESS.\n"); 1584471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm exit (0); 1594471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm } 1604471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm setitimer (ITIMER_VIRTUAL, &interval, NULL); 1614471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm} 1624471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm 1634471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidmint 1646b55e0ab51eee7dbea679fda2b37ecf61f0025e5Tommi Rantalamain (int argc, char **argv UNUSED) 1654471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm{ 1664471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm struct sigaction act; 1674471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm long i = 0; 1684471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm 1694471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm if (argc > 1) 1704471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm verbose = 1; 1714471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm 1724471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm unw_set_caching_policy (unw_local_addr_space, UNW_CACHE_NONE); 1734471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm 1744471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm memset (&act, 0, sizeof (act)); 1754471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm act.sa_handler = sighandler; 1764471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm act.sa_flags = SA_SIGINFO; 1774471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm sigaction (SIGVTALRM, &act, NULL); 1784471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm 1794471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm setitimer (ITIMER_VIRTUAL, &interval, NULL); 1804471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm 1814471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm while (1) 1824471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm { 1834471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm if (0 && verbose) 1844471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm printf ("%s: starting backtrace\n", __FUNCTION__); 1854471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm do_backtrace (0, (i++ % 100) == 0); 186a72abd4e46eb6e92747412fb036d0fb8279350acJan Kratochvil if (nerrors > nerrors_max) 187a72abd4e46eb6e92747412fb036d0fb8279350acJan Kratochvil { 1889a6d92123002c2a249777f5a252e8b82fd3e9a41Tommi Rantala fprintf (stderr, "Too many errors (%d)\n", nerrors); 189a72abd4e46eb6e92747412fb036d0fb8279350acJan Kratochvil exit (-1); 190a72abd4e46eb6e92747412fb036d0fb8279350acJan Kratochvil } 1914471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm } 192459b2a5ba89c3ae0002e741cadbc723e4b1dd0a6Konstantin Belousov return (0); 1934471c1e8c3958dc55e4abb0de5c5a8e69fe0a765mostang.com!davidm} 194