介绍
boost-1.61 版本之后协程库 context 的接口改变了,汇编代码里的参数、返回值和语义都发生了改变,另外还增加了新的接口和汇编实现 ontop_fcontext。
旧版本接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| namespace boost { namespace context {
typedef void* fcontext_t;
extern "C" BOOST_CONTEXT_DECL fcontext_t BOOST_CONTEXT_CALLDECL make_fcontext( void * sp, std::size_t size, void (* fn)( intptr_t) );
extern "C" BOOST_CONTEXT_DECL intptr_t BOOST_CONTEXT_CALLDECL jump_fcontext( fcontext_t * ofc, fcontext_t nfc, intptr_t vp, bool preserve_fpu = false);
}}
|
新版本接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| namespace boost { namespace context { namespace detail {
typedef void* fcontext_t;
struct transfer_t { fcontext_t fctx; void * data; };
extern "C" BOOST_CONTEXT_DECL fcontext_t BOOST_CONTEXT_CALLDECL make_fcontext( void * sp, std::size_t size, void (* fn)( transfer_t) );
extern "C" BOOST_CONTEXT_DECL transfer_t BOOST_CONTEXT_CALLDECL jump_fcontext( fcontext_t const to, void * vp);
extern "C" BOOST_CONTEXT_DECL transfer_t BOOST_CONTEXT_CALLDECL ontop_fcontext( fcontext_t const to, void * vp, transfer_t (* fn)( transfer_t) );
}}}
|
修改总结
命名空间从 boost 变成了 boost::detail
首先重要的是多一个 transfer_t,这个里面的有两个对象,第一个 fctx 是来源的执行上下文,第二个 data 是各种接口传入的自定义的指针 (上面接口里的 vp)。 来源的上下文指的是从什么位置跳转过来的。无论在回调参数还是各项返回值中都是这个含义。
对于 make_fcontext 这个接口,原先的入口函数是 void (* fn)( intptr_t),参数是透传自定义指针。现在是 void (* fn)( transfer_t),里面包含了来源执行栈的上下文和透传的自定义指针。
对于 jump_fcontext 这个接口,原先需要传入把当前执行上下文保存到哪里,跳转目标的新的上下文,自定义数据和是否复制 FPU。 现在的版本不再需要指定是否需要复制 FPU 了,同时也去除了自动保存当前上下文的功能,并且改成了跳到新的上下文后,新的上下文可以知道自己是从哪跳转过来的。
另外,这次的 boost.context 新增了一个比较有意思的接口,transfer_t ontop_fcontext (fcontext_t const to, void * vp, transfer_t ( fn)( transfer_t) )。 这个接口的功能是在跳转目标 (to 指向的上下文) 上模拟函数调用,并且返回值作为 jump_fcontext * 的返回值,相当于可以给执行上下文接口打 hook。
举个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| transfer_t jump_res = jump_fcontext(fctx2, NULL);
ontop_fcontext(fctx1, 0x01, ontop_callback);
transfer_t ontop_callback( transfer_t from) { from.data = 0x02; return from; }
transfer_t jump_res = jump_fcontext(fctx2, NULL);
|