1c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov/* 2c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov * Copyright (C) 2013 The Android Open Source Project 3c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov * 4c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov * Licensed under the Apache License, Version 2.0 (the "License"); 5c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov * you may not use this file except in compliance with the License. 6c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov * You may obtain a copy of the License at 7c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov * 8c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov * http://www.apache.org/licenses/LICENSE-2.0 9c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov * 10c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov * Unless required by applicable law or agreed to in writing, software 11c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov * distributed under the License is distributed on an "AS IS" BASIS, 12c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov * See the License for the specific language governing permissions and 14c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov * limitations under the License. 15c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov */ 16c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov 17c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov/* 18c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov * Contributed by: Intel Corporation 19c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov */ 20c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov 21c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov#include <stdio.h> 22c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov#include <signal.h> 23c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov#include <stdlib.h> 24c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov#include <string.h> 25c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov#include <unwind.h> 26c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov 27c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov#define noinline __attribute__((__noinline__)) 28c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov#define unused __attribute__((__unused__)) 29c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov 30c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikovstatic noinline _Unwind_Reason_Code stop_fn(int a unused, 31c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov _Unwind_Action action, 32c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov _Unwind_Exception_Class b unused, struct _Unwind_Exception* c unused, 33c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov struct _Unwind_Context* d unused, void* e unused) { 34c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov if ((action & _UA_END_OF_STACK) != 0) { 35c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov // We reached the end of the stack without executing foo_cleanup. Test failed. 36c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov abort(); 37c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov } 38c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov return _URC_NO_REASON; 39c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov} 40c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov 41c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikovstatic void noinline foo_cleanup(char* param unused) { 42c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov exit(42); 43c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov} 44c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov 45c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikovstatic void noinline do_crash() { 46c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov char* ptr = NULL; 47c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov *ptr = 0; // Deliberately cause a SIGSEGV. 48c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov} 49c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov 50c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikovstatic void noinline foo() { 51c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov char c1 __attribute__((cleanup(foo_cleanup))); 52c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov do_crash(); 53c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov} 54c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov 55c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov// It's SEGSEGV handler. We start forced stack unwinding here. 56c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov// If libgcc don't find dso for signal frame stack unwinding will be finished. 57c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov// libgcc pass to stop_fn _UA_END_OF_STACK flag. 58c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov// Test pass condition: stack unwinding through signal frame and foo1_handler execution. 59c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikovstatic void noinline sigsegv_handler(int param unused) { 60c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov struct _Unwind_Exception* exception = (struct _Unwind_Exception*) malloc(sizeof(*exception)); 61c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov memset(&exception->exception_class, 0, sizeof(exception->exception_class)); 62c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov exception->exception_cleanup = 0; 63c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov _Unwind_ForcedUnwind(exception, stop_fn, 0); 64c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov} 65c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov 66c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikovvoid do_test() { 67c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov signal(SIGSEGV, &sigsegv_handler); 68c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov foo(); 69c45087bffa528c0809f0df2e0a3708eba7018b33Sergey Melnikov} 70