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