longjmp如何工作?

我需要了解如何longjmp函数工作; 我知道它做了什么,但我需要知道它是如何做到的。

我试图disas在gdb中的代码,但我不明白一些步骤。 代码是:

0xb7ead420 <siglongjmp+0>: push %ebp 0xb7ead421 <siglongjmp+1>: mov %esp,%ebp 0xb7ead423 <siglongjmp+3>: sub $0x18,%esp 0xb7ead426 <siglongjmp+6>: mov %ebx,-0xc(%ebp) 0xb7ead429 <siglongjmp+9>: call 0xb7e9828f <_Unwind_Find_FDE@plt+119> 0xb7ead42e <siglongjmp+14>: add $0x12bbc6,%ebx 0xb7ead434 <siglongjmp+20>: mov %esi,-0x8(%ebp) 0xb7ead437 <siglongjmp+23>: mov 0xc(%ebp),%esi 0xb7ead43a <siglongjmp+26>: mov %edi,-0x4(%ebp) 0xb7ead43d <siglongjmp+29>: mov 0x8(%ebp),%edi 0xb7ead440 <siglongjmp+32>: mov %esi,0x4(%esp) 0xb7ead444 <siglongjmp+36>: mov %edi,(%esp) 0xb7ead447 <siglongjmp+39>: call 0xb7ead4d0 0xb7ead44c <siglongjmp+44>: mov 0x18(%edi),%eax 0xb7ead44f <siglongjmp+47>: test %eax,%eax 0xb7ead451 <siglongjmp+49>: jne 0xb7ead470 <siglongjmp+80> 0xb7ead453 <siglongjmp+51>: test %esi,%esi 0xb7ead455 <siglongjmp+53>: mov $0x1,%eax 0xb7ead45a <siglongjmp+58>: cmove %eax,%esi 0xb7ead45d <siglongjmp+61>: mov %esi,0x4(%esp) 0xb7ead461 <siglongjmp+65>: mov %edi,(%esp) 0xb7ead464 <siglongjmp+68>: call 0xb7ead490 0xb7ead469 <siglongjmp+73>: lea 0x0(%esi,%eiz,1),%esi 0xb7ead470 <siglongjmp+80>: lea 0x1c(%edi),%eax 0xb7ead473 <siglongjmp+83>: movl $0x0,0x8(%esp) 0xb7ead47b <siglongjmp+91>: mov %eax,0x4(%esp) 0xb7ead47f <siglongjmp+95>: movl $0x2,(%esp) 0xb7ead486 <siglongjmp+102>: call 0xb7ead890 <sigprocmask> 0xb7ead48b <siglongjmp+107>: jmp 0xb7ead453 <siglongjmp+51> 

有人可以简单地解释我的代码,或者说明我在哪里可以find系统中的源代码?

下面是标准i386 ABI中的longjmp的i386代码,没有任何与C ++交互的异常扩展,例外,清除函数,信号掩码等。

  mov 4(%esp),%edx mov 8(%esp),%eax test %eax,%eax jnz 1f inc %eax 1: mov (%edx),%ebx mov 4(%edx),%esi mov 8(%edx),%edi mov 12(%edx),%ebp mov 16(%edx),%ecx mov %ecx,%esp mov 20(%edx),%ecx jmp *%ecx 

大多数情况下,它会恢复寄存器,并在相应的setjmp()时像堆栈一样堆栈。 还有一些额外的清理需要(固定信号处理和展开未决的栈处理程序),以及返回一个不同的值作为setjmp的明显的返回值,但恢复状态是操作的本质。

为了工作,堆栈不能低于调用setjmp的地方。 Longjmp是一种粗暴的方法,只是将所有在调用堆栈中调用的所有东西都忘记在调用堆栈(或函数调用嵌套序列)中,大部分情况下只需将堆栈指针设置为与调用setjmp时相同的帧即可。

为了使它干净地工作, longjmp()调用中间函数的所有出口处理程序,以便它们可以删除变量,以及函数返回时通常执行的任何其他清理。 将堆栈重置为较深点将释放所有auto变量,但是如果其中一个是FILE * ,则需要关闭文件并释放I / O缓冲区。

我想你需要看到程序激活记录和调用栈和Setjmp.h的jmp_buf的结构。

引用专家C编程:深C秘密:

Setjmp将程序计数器和当前指针的副本保存到堆栈顶部。 这可以节省一些初始值,如果你喜欢。 然后longjmp恢复这些值,有效地转移控制权并将状态重置回到您保存时的位置。 它被称为“展开堆栈”,因为您从堆栈中展开激活记录,直到找到保存的记录。

看看第153页也在这里。

堆栈框架将高度依赖于机器和可执行文件,但想法是一样的。

你传递setjmp()一个缓冲参数。 然后它将当前的注册信息等存储到这个缓冲区中。 对longjmp()的调用然后从缓冲区中恢复这些值。 此外,wallyk说。