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