kin*_*er1 2 c linux segmentation-fault
我编写了一个分段错误处理程序,但问题是,发生错误的指令在转到处理程序后重新启动,这导致处理程序进入无限循环.
我希望处理程序工作,使得在到达处理程序之后,应该执行错误指令之后的指令,使得它不会进入无限循环.有人可以帮我一些代码片段吗?
我正在使用C和Linux.
我还想重复Henning Makholms的警告,它将极其特定于架构和非便携式.这将是维护地狱,你将不得不手动处理许多不同的指令,除非它是你正在寻找的一个特定指令序列(如下例所示).
如果您仍然希望这样做,可以通过以下方式完成:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <time.h>
#define __USE_GNU
#include <signal.h>
void action(int sig, siginfo_t* siginfo, void* context)
{
sig=sig; siginfo=siginfo;// ignore warning
// get execution context
mcontext_t* mcontext = &((ucontext_t*)context)->uc_mcontext;
// find out what instruction faulted
#if defined(__x86_64)
uint8_t* code = (uint8_t*)mcontext->gregs[REG_RIP];
if (code[0] == 0x88 && code[1] == 0x10) { // mov %dl,(%rax)
mcontext->gregs[REG_RIP] += 2; // skip it!
return;
}
#elif defined(__i386)
uint8_t* code = (uint8_t*)mcontext->gregs[REG_EIP];
if (code[0] == 0x88 && code[1] == 0x10) { // mov %dl,(%eax)
mcontext->gregs[REG_EIP] += 2; // skip it!
return;
}
#else
#error "Unsupported system"
#endif
// unknown/unhandled instruction failed...
// only for debugging, shouldn't print stuff in a signal handler
int i = 0;
for (i = 0; i < 16; i++) {
fprintf(stderr, "%2.2X ", code[i]);
}
fprintf(stderr, "\n");
exit(1);
}
int main(void)
{
// install SIGSEGV handler
struct sigaction act;
memset(&act, 0, sizeof(act));
act.sa_sigaction = action;
act.sa_flags = SA_SIGINFO;
if (sigaction(SIGSEGV, &act, NULL) < 0) {
perror("sigaction");
return 1;
}
// cause fault
int i;
for (i = 0; i < 10; i++) {
((unsigned char*)0)[i] = i;
}
return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)
在这里,我只处理了x86 32位和64位的一个特定指令序列,尽管它应该是微不足道的(如果单调乏味)以支持更多的体系结构和指令.
更新:您(现在)提到您使用的是ARM计算机.这实际上应该更容易,因为如果我没有弄错的话,指令总是32位(拇指模式除外).我没有ARM机器来测试这个,所以你必须深入研究sys/ucontext.h以检查我的名字是否正确.当然,你也应该以类似的方式检查断层指令.我对ARM的最佳猜测如下(与其他#if defined(...)语句并列:
#elif defined(__arm) // or use what your GCC defines, also check for 32-bit arm mode or whatever...
uint8_t* code = (uint8_t*)mcontext->arm_pc;
if (*(uint32_t*)code == /*some instruction*/) {
mcontext->arm_pc += 4; // skip it!
return;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2336 次 |
| 最近记录: |