作者nith (skyl)
看板LinuxDev
标题Re: [问题]swapcontext
时间Sun Jan 23 20:15:30 2011
※ 引述《yueayase (scrya)》之铭言:
: static ucontext_t uctx_main, uctx_func1, uctx_func2;
static int exit_addr;
: static void
: func1(void)
: {
: printf("func1: started\n");
: printf("func1: swapcontext(&uctx_func1, &uctx_func2)\n");
: if (swapcontext(&uctx_func1, &uctx_func2) == -1)
: die("swapcontext");
: /* 有趣的地方 */
: printf("test...\n");
((int *)uctx_func2.uc_stack.ss_sp)[16384-5] = exit_addr;
: if (swapcontext(&uctx_func1, &uctx_func2) == -1)
: die("swapcontext");
: printf("func1: returning\n");
: }
: static void
: func2(void)
: {
: printf("func2: started\n");
: printf("func2: swapcontext(&uctx_func2, &uctx_func1)\n");
: if (swapcontext(&uctx_func2, &uctx_func1) == -1)
: die("swapcontext");
exit_addr = ((int *)uctx_func2.uc_stack.ss_sp)[16384-5];
: printf("func2: returning\n");
: }
: int
: main(int argc, char *argv[])
: {
: char func1_stack[16384];
: char func2_stack[16384];
/* 配合stack_t的型态宣告成int, 上面两行的char宣告要拿掉 */
int func1_stack[16384];
int func2_stack[16384];
: if (getcontext(&uctx_func1) == -1)
: die("getcontext");
: 我很好奇,怎麽把这种"func2()已用完"的状态抓出来?
: 希望有一些强者可以帮我解答
稍微trace了一下, 把上面的修改加到原本的code里的话, 就可以return到f1和main
原因是函式return时会去呼叫一个exitcode func, exitcode func的address会被放
在stack[stacksize-5] (不同架构的机器可能会不一样, 我的exitcode func address
是7243995 )
当函式return时, exitcode address会被修改成另一个位置(7244021), 所以之後切换
回f2时就不会return到f1, 而是直接终止程式
把glibc makecontext的source code挖出来看, 可以知道7243995就是下面L(exitcode)这
个label的位置, 7244021应该是 'call HIDDEN_JUMPTARGET(exit)' 的上一个指令的位置
, 当f2结束时, exitcode func address会被改写成7244021, 所以之後切回f2, 当f2结束
时程式就会终止
回到原po的问题, 要侦测f2是否结束, 理论上是可以从f2 stack里面的
exitcode func address来判断, 但比较好的做法应该是f2结束时要把
uctx_func2的flag设成代表结束的值(define by yourself)
ENTRY(__makecontext)
.
.
.
/* 把exitcode address放到context的stack上 */
movl $L(exitcode), (%edx)
.
.
.
/* This is the helper code which gets called if a function which
is registered with 'makecontext' returns. In this case we
have to install the context listed in the uc_link element of
the context 'makecontext' manipulated at the time of the
'makecontext' call. If the pointer is NULL the process must
terminate. */
cfi_endproc
L(exitcode):
/* This removes the parameters passed to the function given to
'makecontext' from the stack. EBX contains the number of
parameters (see above). */
leal (%esp,%ebx,4), %esp
#ifdef PIC
call 1f
1: popl %ebx
addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx
#endif
cmpl $0, (%esp) /* Check the next context. */
je 2f /* If it is zero exit. */
call JUMPTARGET(__setcontext)
/* If this returns (which can happen if the syscall fails) we'll
exit the program with the return error value (-1). */
movl %eax, (%esp)
2: call HIDDEN_JUMPTARGET(exit)
/* The 'exit' call should never return. In case it does cause
the process to terminate. */
hlt
cfi_startproc
END(__makecontext)
--
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 118.166.226.207
※ 编辑: nith 来自: 118.166.226.207 (01/23 20:16)
※ 编辑: nith 来自: 118.166.226.207 (01/23 20:25)
1F:推 yueayase:真的是太厉害了,要碰到assembly等级的 01/26 01:53