1d4e76214Sopenharmony_ci/* libunwind - a platform-independent unwind library
2d4e76214Sopenharmony_ci   Copyright (C) 2003-2004 Hewlett-Packard Co
3d4e76214Sopenharmony_ci	Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
4d4e76214Sopenharmony_ci
5d4e76214Sopenharmony_ciThis file is part of libunwind.
6d4e76214Sopenharmony_ci
7d4e76214Sopenharmony_ciCopyright (c) 2003 Hewlett-Packard Co.
8d4e76214Sopenharmony_ci
9d4e76214Sopenharmony_ciPermission is hereby granted, free of charge, to any person obtaining
10d4e76214Sopenharmony_cia copy of this software and associated documentation files (the
11d4e76214Sopenharmony_ci"Software"), to deal in the Software without restriction, including
12d4e76214Sopenharmony_ciwithout limitation the rights to use, copy, modify, merge, publish,
13d4e76214Sopenharmony_cidistribute, sublicense, and/or sell copies of the Software, and to
14d4e76214Sopenharmony_cipermit persons to whom the Software is furnished to do so, subject to
15d4e76214Sopenharmony_cithe following conditions:
16d4e76214Sopenharmony_ci
17d4e76214Sopenharmony_ciThe above copyright notice and this permission notice shall be
18d4e76214Sopenharmony_ciincluded in all copies or substantial portions of the Software.
19d4e76214Sopenharmony_ci
20d4e76214Sopenharmony_ciTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21d4e76214Sopenharmony_ciEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22d4e76214Sopenharmony_ciMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23d4e76214Sopenharmony_ciNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24d4e76214Sopenharmony_ciLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25d4e76214Sopenharmony_ciOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26d4e76214Sopenharmony_ciWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
27d4e76214Sopenharmony_ci
28d4e76214Sopenharmony_ci#include "compiler.h"
29d4e76214Sopenharmony_ci
30d4e76214Sopenharmony_ci#include <libunwind.h>
31d4e76214Sopenharmony_ci#include <stdio.h>
32d4e76214Sopenharmony_ci#include <stdlib.h>
33d4e76214Sopenharmony_ci#include <string.h>
34d4e76214Sopenharmony_ci#include <unistd.h>
35d4e76214Sopenharmony_ci
36d4e76214Sopenharmony_ci#include <sys/resource.h>
37d4e76214Sopenharmony_ci#include <sys/mman.h>
38d4e76214Sopenharmony_ci#include <sys/types.h>
39d4e76214Sopenharmony_ci#include <sys/wait.h>
40d4e76214Sopenharmony_ci
41d4e76214Sopenharmony_ci#define panic(args...)				\
42d4e76214Sopenharmony_ci	{ fprintf (stderr, args); exit (-1); }
43d4e76214Sopenharmony_ci
44d4e76214Sopenharmony_civoid * stack_start;
45d4e76214Sopenharmony_ci
46d4e76214Sopenharmony_ci#define PAGE_SIZE 4096
47d4e76214Sopenharmony_ci
48d4e76214Sopenharmony_civoid do_backtrace (void)
49d4e76214Sopenharmony_ci{
50d4e76214Sopenharmony_ci  /*
51d4e76214Sopenharmony_ci    We make the assumption that we are able to rewind far enough
52d4e76214Sopenharmony_ci    (steps > 5) before touching the forbidden region in the stack,
53d4e76214Sopenharmony_ci    at which point the unwinding should stop gracefully.
54d4e76214Sopenharmony_ci  */
55d4e76214Sopenharmony_ci  mprotect((void*)((uintptr_t)stack_start & ~(PAGE_SIZE - 1)),
56d4e76214Sopenharmony_ci           PAGE_SIZE, PROT_NONE);
57d4e76214Sopenharmony_ci
58d4e76214Sopenharmony_ci  unw_cursor_t cursor;
59d4e76214Sopenharmony_ci  unw_word_t ip, sp;
60d4e76214Sopenharmony_ci  unw_context_t uc;
61d4e76214Sopenharmony_ci  int ret;
62d4e76214Sopenharmony_ci  int steps = 0;
63d4e76214Sopenharmony_ci
64d4e76214Sopenharmony_ci  unw_getcontext (&uc);
65d4e76214Sopenharmony_ci  if (unw_init_local (&cursor, &uc) < 0)
66d4e76214Sopenharmony_ci    panic ("unw_init_local failed!\n");
67d4e76214Sopenharmony_ci
68d4e76214Sopenharmony_ci  do
69d4e76214Sopenharmony_ci    {
70d4e76214Sopenharmony_ci      unw_get_reg (&cursor, UNW_REG_IP, &ip);
71d4e76214Sopenharmony_ci      unw_get_reg (&cursor, UNW_REG_SP, &sp);
72d4e76214Sopenharmony_ci
73d4e76214Sopenharmony_ci      ret = unw_step (&cursor);
74d4e76214Sopenharmony_ci	  printf("ip=%lx, sp=%lx -> %d\n", ip, sp, ret);
75d4e76214Sopenharmony_ci      if (ret < 0)
76d4e76214Sopenharmony_ci	{
77d4e76214Sopenharmony_ci	  unw_get_reg (&cursor, UNW_REG_IP, &ip);
78d4e76214Sopenharmony_ci	}
79d4e76214Sopenharmony_ci      steps ++;
80d4e76214Sopenharmony_ci    }
81d4e76214Sopenharmony_ci  while (ret > 0);
82d4e76214Sopenharmony_ci
83d4e76214Sopenharmony_ci  if (steps < 5)
84d4e76214Sopenharmony_ci    {
85d4e76214Sopenharmony_ci      printf("not enough steps: %d, need 5\n", steps);
86d4e76214Sopenharmony_ci      exit(-1);
87d4e76214Sopenharmony_ci    }
88d4e76214Sopenharmony_ci  printf("success, steps: %d\n", steps);
89d4e76214Sopenharmony_ci
90d4e76214Sopenharmony_ci  mprotect((void*)((uintptr_t)stack_start & ~(PAGE_SIZE - 1)),
91d4e76214Sopenharmony_ci           PAGE_SIZE, PROT_READ|PROT_WRITE);
92d4e76214Sopenharmony_ci}
93d4e76214Sopenharmony_ci
94d4e76214Sopenharmony_civoid NOINLINE consume_and_run (int depth)
95d4e76214Sopenharmony_ci{
96d4e76214Sopenharmony_ci  unw_cursor_t cursor;
97d4e76214Sopenharmony_ci  unw_context_t uc;
98d4e76214Sopenharmony_ci  char string[1024];
99d4e76214Sopenharmony_ci
100d4e76214Sopenharmony_ci  sprintf (string, "hello %p %p\n", &cursor, &uc);
101d4e76214Sopenharmony_ci  if (depth == 0) {
102d4e76214Sopenharmony_ci    do_backtrace();
103d4e76214Sopenharmony_ci  } else {
104d4e76214Sopenharmony_ci    consume_and_run(depth - 1);
105d4e76214Sopenharmony_ci  }
106d4e76214Sopenharmony_ci}
107d4e76214Sopenharmony_ci
108d4e76214Sopenharmony_ciint
109d4e76214Sopenharmony_cimain (int argc, char **argv UNUSED)
110d4e76214Sopenharmony_ci{
111d4e76214Sopenharmony_ci  int start;
112d4e76214Sopenharmony_ci  unw_context_t uc;
113d4e76214Sopenharmony_ci  unw_cursor_t cursor;
114d4e76214Sopenharmony_ci
115d4e76214Sopenharmony_ci  stack_start = &start;
116d4e76214Sopenharmony_ci
117d4e76214Sopenharmony_ci  /*
118d4e76214Sopenharmony_ci    We need to make the frame at least the size protected by
119d4e76214Sopenharmony_ci    the mprotect call so we are not forbidding access to
120d4e76214Sopenharmony_ci    unrelated regions.
121d4e76214Sopenharmony_ci  */
122d4e76214Sopenharmony_ci  char string[PAGE_SIZE];
123d4e76214Sopenharmony_ci  sprintf (string, "hello\n");
124d4e76214Sopenharmony_ci
125d4e76214Sopenharmony_ci  // Initialize pipe mem validate check, opens file descriptors
126d4e76214Sopenharmony_ci  unw_getcontext(&uc);
127d4e76214Sopenharmony_ci  if (unw_init_local (&cursor, &uc) < 0)
128d4e76214Sopenharmony_ci    panic ("unw_init_local failed!\n");
129d4e76214Sopenharmony_ci
130d4e76214Sopenharmony_ci  int i;
131d4e76214Sopenharmony_ci  for (i = 3; i < 10; i++)
132d4e76214Sopenharmony_ci    {
133d4e76214Sopenharmony_ci
134d4e76214Sopenharmony_ci      pid_t childpid = fork();
135d4e76214Sopenharmony_ci      if (!childpid)
136d4e76214Sopenharmony_ci        {
137d4e76214Sopenharmony_ci          /* Close fds and make sure we still work */
138d4e76214Sopenharmony_ci          close(i);
139d4e76214Sopenharmony_ci        }
140d4e76214Sopenharmony_ci
141d4e76214Sopenharmony_ci      int status;
142d4e76214Sopenharmony_ci      if (childpid)
143d4e76214Sopenharmony_ci        {
144d4e76214Sopenharmony_ci          wait(&status);
145d4e76214Sopenharmony_ci          if (WIFEXITED(status))
146d4e76214Sopenharmony_ci              return WEXITSTATUS(status);
147d4e76214Sopenharmony_ci          else
148d4e76214Sopenharmony_ci            return -1;
149d4e76214Sopenharmony_ci        }
150d4e76214Sopenharmony_ci      else
151d4e76214Sopenharmony_ci        {
152d4e76214Sopenharmony_ci          consume_and_run (10);
153d4e76214Sopenharmony_ci
154d4e76214Sopenharmony_ci          return 0;
155d4e76214Sopenharmony_ci        }
156d4e76214Sopenharmony_ci    }
157d4e76214Sopenharmony_ci
158d4e76214Sopenharmony_ci  return 0;
159d4e76214Sopenharmony_ci}
160