Skip to content

Instantly share code, notes, and snippets.

@bczhc
Created March 6, 2026 12:52
Show Gist options
  • Select an option

  • Save bczhc/fcd9eb01a29f1bfbd228708f19eeeead to your computer and use it in GitHub Desktop.

Select an option

Save bczhc/fcd9eb01a29f1bfbd228708f19eeeead to your computer and use it in GitHub Desktop.
从除零错误中断中恢复
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <ucontext.h>
void handle_fpe(int sig, siginfo_t *info, void *ucontext) {
printf("Caught SIGFPE! Attempting to skip the broken instruction...\n");
// 强制转换为 ucontext_t 结构体指针
ucontext_t *context = (ucontext_t *) ucontext;
// REG_RIP 是 x86_64 的指令指针寄存器
// 注意:2 字节只是一个猜测,具体取决于编译器生成的指令
// 如果你的编译器生成的是 3 字节指令,这里需要 +3
context->uc_mcontext.gregs[REG_RAX] = 666;
context->uc_mcontext.gregs[REG_RIP] += 2;
}
int main(int argc, char **argv) {
struct sigaction sa;
sa.sa_sigaction = handle_fpe;
sa.sa_flags = SA_SIGINFO; // 必须开启这个标志才能拿到 ucontext
sigemptyset(&sa.sa_mask);
sigaction(SIGFPE, &sa, NULL);
int d = 0;
printf("Before division...\n");
// 这里故意制造除零
// 使用 asm 锁定指令长度,确保 idivl 占用 2 字节 (f7 f1)
int r;
int a = 10;
asm volatile(
"movl %1, %%eax\n\t"
"cltd\n\t"
"idivl %2\n\t"
"movl %%eax, %0"
: "=r"(r)
: "r"(a), "r"(d)
: "%eax", "%edx"
);
printf("After division! We survived.\n");
printf("r = %d\n", r);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment