2
0
mirror of https://github.com/boostorg/context.git synced 2026-01-19 04:02:17 +00:00
Files
context/example/unwind_ucontext.cpp
2019-04-10 09:26:10 +02:00

77 lines
2.0 KiB
C++

// Copyright Oliver Kowalke 2019.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <cassert>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <ucontext.h>
#include <unwind.h>
struct context_t {
ucontext_t ucf;
ucontext_t ucm;
};
struct X {
int i;
X( int i_) : i{ i_ } { std::printf("X(%d)\n", i); }
~X() { std::printf("~X(%d)\n", i); }
};
_Unwind_Reason_Code stop_fn( int version,
_Unwind_Action actions,
_Unwind_Exception_Class exc_class,
_Unwind_Exception *exc,
_Unwind_Context *context,
void * param) {
context_t * ctx = ( context_t *) param;
if ( actions & _UA_END_OF_STACK) {
std::printf("end of stack, jump back\n");
_Unwind_DeleteException( exc);
if ( -1 == ::swapcontext( & ctx->ucf, & ctx->ucm) ) {
std::abort();
}
}
return _URC_NO_REASON;
}
void foo( int i, context_t * ctx) {
if ( 0 < i) {
X x{ i };
foo( --i, ctx);
} else {
_Unwind_Exception * exc = ( _Unwind_Exception *) std::malloc( sizeof( _Unwind_Exception) );
std::memset( exc, 0, sizeof( * exc) );
_Unwind_ForcedUnwind( exc, stop_fn, ctx);
//ctx::detail::unwind( stop_fn, ctx);
}
std::printf("return from foo()\n");
}
int main( int argc, char * argv[]) {
context_t ctx;
std::vector< char > buffer(16384, '\0');
void * fn_stack = & buffer[0];
std::printf("buffer : %p\n", fn_stack);
fn_stack = ( char * )( ( ( ( ( uintptr_t) fn_stack) - 16) >> 4) << 4);
std::printf("aligned : %p\n", fn_stack);
if ( -1 == ::getcontext( & ctx.ucf) ) {
std::abort();
}
ctx.ucf.uc_stack.ss_sp = fn_stack;
ctx.ucf.uc_stack.ss_size = buffer.size();
::makecontext( & ctx.ucf, (void(*)())( foo), 2, 5, & ctx);
if ( -1 == ::swapcontext( & ctx.ucm, & ctx.ucf) ) {
std::abort();
}
std::printf("main: done\n");
return EXIT_SUCCESS;
}