【发布时间】:2014-07-10 19:03:09
【问题描述】:
我有这个程序集,它编译得很好,但在恢复时会出现分段错误。有人可以验证吗?这是针对 x86_64 架构的
save_context:
mov %rdi,%rax /* Get our context pointer */
/* Don't need to save A */
mov %rbx, 16(%rax) /* Save B */
mov %r12, 24(%rax) /* Save r12 */
mov %r13, 32(%rax) /* Save r13 (8*3+16)*/
mov %r14, 40(%rax) /* Save r13 */
mov %r15, 48(%rax) /* Save r13 */
mov %rbp, 56(%rax) /* Save frame pointer */
mov %rsp, 64(%rax) /* Save stack pointer */
mov (%rsp), %rdx /* Fetch our return address */
mov %rdx, (%rax) /* Save our return address */
xor %rax,%rax /* Construct return code of 1 */
inc %rax
ret
恢复是这样的
restore_context:
mov %rdi,%rax /* Get our context pointer */
mov 64(%rax), %rsp /* Restore stack pointer */
mov (%rax), %rdx /* Fetch our return address */
mov %rdx, (%rsp)
mov 16(%rax),%rbx /* Restore B */
mov 24(%rax), %r12 /* Restore r12 */
mov 32(%rax), %r13 /* Restore r13 */
mov 40(%rax), %r14 /* Restore r14 */
mov 48(%rax), %r15 /* Restore r15 */
mov 56(%rax), %rbp /* Restore frame pointer */
xor %rax,%rax /* Return 0 */
ret
当我使用 gdb 调试函数时,我得到了这个。在分段错误之后。
0x0000000000424c4c <+0>: mov %rdi,%rax
0x0000000000424c4f <+3>: mov 0x18(%rax),%rsp
0x0000000000424c53 <+7>: mov (%rax),%rbx
=> 0x0000000000424c56 <+10>: mov %rbx,(%rsp)
0x0000000000424c5a <+14>: mov 0x10(%rax),%rbx
0x0000000000424c5e <+18>: mov 0x20(%rax),%rbp
0x0000000000424c62 <+22>: mov 0x28(%rax),%r12
0x0000000000424c66 <+26>: mov 0x30(%rax),%r13
0x0000000000424c6a <+30>: mov 0x38(%rax),%r14
0x0000000000424c6e <+34>: mov 0x40(%rax),%r15
0x0000000000424c72 <+38>: xor %rax,%rax
0x0000000000424c75 <+41>: retq
0x0000000000424c76 <+42>: nop
0x0000000000424c77 <+43>: nop
解除保存上下文
0x0000000000424c1c <+0>: mov %rdi,%rax
0x0000000000424c1f <+3>: mov %rbx,0x10(%rax)
0x0000000000424c23 <+7>: mov %rsp,0x18(%rax)
0x0000000000424c27 <+11>: mov %rbp,0x20(%rax)
0x0000000000424c2b <+15>: mov %r12,0x28(%rax)
0x0000000000424c2f <+19>: mov %r13,0x30(%rax)
0x0000000000424c33 <+23>: mov %r14,0x38(%rax)
0x0000000000424c37 <+27>: mov %r15,0x40(%rax)
0x0000000000424c3b <+31>: mov (%rsp),%rdx
0x0000000000424c3f <+35>: mov %rdx,(%rax)
0x0000000000424c42 <+38>: xor %rax,%rax
0x0000000000424c45 <+41>: inc %rax
0x0000000000424c48 <+44>: retq
0x0000000000424c49 <+45>: nopl (%rax)
关于上下文的更多信息
save_context(上下文) 上下文 = {4243415, 0, 0, 4242944, 140737488348624, 0, 0, 140737488348368, 140737488348312, 0}
restore_context(new_context) new_context= {4249788, 0, 0, 0, 0, 0, 6719200, 6719184, 0, 0}
恢复上下文后失败。我尝试了 save_context 然后 restore_context。这样可行。只是检查 64 位的上下文和新上下文是否有问题?!?!
这里是 32 位版本
save_context:
movl 4(%esp),%eax /* Get our context pointer */
/* Don't need to save A */
movl %ebx, 12(%eax) /* Save B */
movl %esi, 16(%eax) /* Save SI */
movl %edi, 20(%eax) /* Save DI */
movl %ebp, 24(%eax) /* Save frame pointer */
movl %esp, 28(%eax) /* Save stack pointer */
movl 0(%esp), %edx /* Fetch our return address */
movl %edx, 0(%eax) /* Save our return address */
xorl %eax,%eax /* Construct return code of 1 */
incl %eax
ret
恢复上下文:
restore_context:
movl 4(%esp),%eax /* Get our context pointer */
movl 28(%eax), %esp /* Restore stack pointer */
movl 0(%eax),%edx /* Get our return address */
movl %edx, 0(%esp) /* Put it on the stack in the right
spot. */
movl 12(%eax),%ebx /* Restore B */
movl 16(%eax), %esi /* Restore SI */
movl 20(%eax), %edi /* Restore DI */
movl 24(%eax), %ebp /* Restore frame pointer */
xorl %eax,%eax /* Return 0 */
ret
知道如何解决这个问题吗?
【问题讨论】:
-
返回地址不在
8(%rbp),你还没有设置rbp指向任何地方(除非它是由调用者隐式设置的)。 -
返回地址为
(%rsp)。如果您使用push %rbp; mov %rsp, %rbp的遗留函数序言,那么同样的位置确实也可以作为8(%rbp)寻址。 -
是的,看起来应该可以了。
-
还有
rax;) 来吧,你在评论中做得对了一点...... -
反汇编与源不匹配,您从
0x18(%rdx)加载rsp。确保这是正确的。
标签: assembly gdb segmentation-fault x86-64 cpu-registers