gpt4 book ai didi

assembly - 需要帮助验证汇编代码

转载 作者:行者123 更新时间:2023-12-02 21:33:03 25 4
gpt4 key购买 nike

我有这个程序集,它编译得很好,但在恢复时出现段错误。有人可以验证一下吗?这是针对 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

拆卸 save_context

  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)

有关上下文的更多信息

保存上下文(上下文)上下文 = {4243415, 0, 0, 4242944, 140737488348624, 0, 0, 140737488348368, 140737488348312, 0}

恢复上下文(新上下文)new_context= {4249788, 0, 0, 0, 0, 0, 6719200, 6719184, 0, 0}

恢复上下文后失败。我尝试了保存上下文,然后恢复上下文。这样可行。只是检查 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

知道如何解决这个问题吗?

最佳答案

首先,我将保存和恢复并排放置(并打乱恢复指令),以便我可以查看偏移量是否有误。从这个角度来看,它看起来不错。

save_context:                restore_context:

mov %rdi,%rax mov %rdi,%rax

mov %rbx, 16(%rax) mov 16(%rax),%rbx
mov %r12, 24(%rax) mov 24(%rax), %r12
mov %r13, 32(%rax) mov 32(%rax), %r13
mov %r14, 64(%rax) mov 64(%rax), %r14
mov %r15, 48(%rax) mov 48(%rax), %r15

mov %rbp, 56(%rax) mov 56(%rax), %rbp
mov %rsp, 64(%rax) mov 64(%rax), %rsp

mov %rdx, (%rsp) mov (%rsp), %rdx
mov %rdx, (%rax) mov (%rax), %rdx

xor %rax,%rax xor %rax,%rax
inc %rax

ret ret

到目前为止一切顺利。

但是,现在我想看看上述偏移量:

16
24
32
64 <-- why 64 here?
48
56
64 <-- Oops 64 again?

我认为这就是罪魁祸首。您将两个寄存器保存在同一地址。

现在奇怪的是,在 gdb 输出中它看起来是正确的。所以我猜你没有向我们展示你的原始来源。

为了避免此类问题,通常最好使用定义不同偏移量的定义指令来定义结构。

否则,您能多描述一下您的背景吗?这看起来不像是可以在操作系统上运行的代码,但您提到了 gdb,所以听起来您将在 Linux 中运行。我能想到两种可能性:您的上下文在恢复发生之前被覆盖,保存后的堆栈发生很大变化(我想),当您恢复时,您最终会得到一个完全不同的堆栈,但您恢复了 %esp 现在就堆栈而言是“随机数据”。所以 ret 应该可以工作(你可以恢复那么多),但在那之后......谁知道呢!

<小时/>

评论中问题的更新:

1) Yes i am running on linux because the 32version of this was working fine and I guessed so will this .. Am i wrong to assume that ??

啊。堆栈的管理方式可能不同,但如果您自己调用函数,那么这在这里应该不重要。你还修改了rdx,这可能是不允许的?

2) I see what you mean by context getting overwritten in the code somewhere. So I tried placing save and restore immediately after each other. Still it gives me segmentation fault which means something is wrong in my assembly code.

实际上,您的代码看起来像这样:

  MOV ..., %rdi
CALL save
TEST %rax
JNE done
[...do things, but no RET...]
MOV ..., %rdi
CALL restore
---not reached---
done:
RET

当您从保存函数返回时,您保存的返回地址就在CALL save之后,这就是为什么您将%rax设置为0或1,以便您了解您是从保存还是恢复中返回。到目前为止,我没有发现任何问题。

我能想到的一件事是 %rdi 在保存和恢复调用之间发生变化,但如果您更改代码以仅执行这两个调用,我想情况并非如此。您的问题中指出的 => 是否是 SEGV?还是SEGV之前就上线了?

3) How to debug such errors ?

我将使用 stepi 进行跟踪并验证每条指令是否完全符合您的预期。查看保存的堆栈指针是您在恢复中返回的堆栈指针,并查看返回地址是否正确。

GDB 可用于在每次运行命令时打印一组条目。因此,如果您这样做,然后 stepi + 输入任意数量的时间,您应该会看到每个步骤的信息并查看何时出错。 (即打印 %rdi 处的寄存器和数据?)

关于assembly - 需要帮助验证汇编代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23795016/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com