首页 > 解决方案 > 自定义 setjmp/longjmp 实现分段错误

问题描述

我正在尝试为 x64 窗口实现自定义setjmp/longjmp。我有以下代码:

contextSave:
xorq %rdx,%rdx  
movq %rdx,(%rcx)  
movq %rbx,0x8(%rcx)  
leaq 0x8(%rsp),%rax  
movq %rax,0x10(%rcx)  
movq %rbp,0x18(%rcx)  
movq %rsi,0x20(%rcx)  
movq %rdi,0x28(%rcx)  
movq %r12,0x30(%rcx)  
movq %r13,0x38(%rcx)    
movq %r14,0x40(%rcx)   
movq %r15,0x48(%rcx)  
movq (%rsp),%rax  
movq %rax,0x50(%rcx)  
movdqa %xmm6,0x60(%rcx)  
movdqa %xmm7,0x70(%rcx)  
movdqa %xmm8,0x80(%rcx)  
movdqa %xmm9,0x90(%rcx)  
movdqa %xmm10,0xa0(%rcx)  
movdqa %xmm11,0xb0(%rcx)  
movdqa %xmm12,0xc0(%rcx)  
movdqa %xmm13,0xd0(%rcx)  
movdqa %xmm14,0xe0(%rcx)  
movdqa %xmm15,0xf0(%rcx)  
xorq %rax,%rax  
retq   
contextRestore:  
movq $1,%rax  
movq 0x8(%rcx),%rbx  
movq 0x18(%rcx),%rbp  
movq 0x20(%rcx),%rsi  
movq 0x28(%rcx),%rdi  
movq 0x30(%rcx),%r12  
movq 0x38(%rcx),%r13  
movq 0x40(%rcx),%r14  
movq 0x48(%rcx),%r15  
movdqa 0x60(%rcx),%xmm6  
movdqa 0x70(%rcx),%xmm7  
movdqa 0x80(%rcx),%xmm8  
movdqa 0x90(%rcx),%xmm9  
movdqa 0xa0(%rcx),%xmm10  
movdqa 0xb0(%rcx),%xmm11  
movdqa 0xc0(%rcx),%xmm12  
movdqa 0xd0(%rcx),%xmm13  
movdqa 0xe0(%rcx),%xmm14  
movdqa 0xf0(%rcx),%xmm15  
movq 0x50(%rcx),%rdx    
movq 0x10(%rcx),%rsp  
jmp *%rdx  

执行上下文保存在以下结构中:

typedef struct Float128{
   unsigned long part[2];
  }Float128 __attribute__((aligned(16)));
  typedef struct ContextData{
   long frame;
   long rbx;
   long rsp;
   long rbp;
   long rsi;
   long rdi;
   long r12;
   long r13;
   long r14;
   long r15;
   long rip;
   long spare;
   Float128 Xmm6;
   Float128 Xmm7;
   Float128 Xmm8;
   Float128 Xmm9;
   Float128 Xmm10;
   Float128 Xmm11;
   Float128 Xmm12;
   Float128 Xmm13;
   Float128 Xmm14;
   Float128 Xmm15;
   }ContextData;

代码是this , thisthis的修改版本

gdb显示以下错误消息:

#0 0x000000000040231e in contextRestore () 回溯停止:无法访问地址 0xbaadf00dbaadf00d 处的内存

Info registers 显示0xbaadf00dbaadf00d存储在许多寄存器中。contextSave未按预期工作。
更新:
似乎问题不在显示的代码范围内。我用函数创建了一个简单的代码来隔离问题。它导致以下错误。

回溯停止:前一帧与此帧相同(损坏的堆栈?)

寄存器似乎没问题。

ContextData context;
if(contextSave(context)==1){
 puts("context restored");
 exit(0);
}
contextRestore(context);

更新 2
调试显示 rsp、rpb 和 rip 在 ContextData 结构中为零。所以它们没有被 contextSave 正确保存。

标签: assemblysegmentation-faultsetjmp

解决方案


好的,似乎结构是问题所在。我没有正确实现这些功能。我决定现在只使用结构并使用标准库。

正确类型:

typedef struct Float128{
   unsigned long long data[2]
}Float128 __attribute__((aligned(16)));
typedef Float128 Context[16];

推荐阅读