c - Linux 信号处理。如何获取中断指令的地址?

标签 c linux signals

<分区>

有没有办法找出被某些信号中断的机器指令的地址?假设我们在 sigaction() 建立的处理程序中,并且可以访问传递的 siginfo_tucontext_t。 据我所知,手册页对此只字不提。

最佳答案

让我们看看下面的 linux 和 x86 架构示例

#include<stdio.h>
#define __USE_GNU
#include<signal.h>
#include<ucontext.h>

void myhandle(int mysignal, siginfo_t *si, void* arg)
{    
  ucontext_t *context = (ucontext_t *)arg;
  printf("Address from where crash happen is %x \n",context->uc_mcontext.gregs[REG_RIP]);
  context->uc_mcontext.gregs[REG_RIP] = context->uc_mcontext.gregs[REG_RIP] + 0x04 ;

}

int main(int argc, char *argv[])
{
  struct sigaction action;
  action.sa_sigaction = &myhandle;
  action.sa_flags = SA_SIGINFO;
  sigaction(11,&action,NULL);

  printf("Before segfault\n");

  int *a=NULL;
  int b;
  b =*a; // Here crash will hapen

  printf("I am still alive\n");

  return 0;
}

现在编译运行,看看反编译的指令集。

jeegar@jeegar:~/stackoverflow$ gcc -g test1.c  -o test1.o
jeegar@jeegar:~/stackoverflow$ ./test1.o 
Before segfault
Signal is 11
Address from where crash happen is 40065b 
I am still alive
jeegar@jeegar:~/stackoverflow$ objdump -S test1.o 

在对象转储中

  printf("Before segfault\n");
  400645:   bf a8 07 40 00          mov    $0x4007a8,%edi
  40064a:   e8 21 fe ff ff          callq  400470 <puts@plt>

  int *a=NULL;
  40064f:   48 c7 45 f0 00 00 00    movq   $0x0,-0x10(%rbp)
  400656:   00 
  int b;
  b =*a; // Here crash will hapen
  400657:   48 8b 45 f0             mov    -0x10(%rbp),%rax
  40065b:   8b 00                   mov    (%rax),%eax
  40065d:   89 45 fc                mov    %eax,-0x4(%rbp)

  printf("I am still alive\n");
  400660:   bf b8 07 40 00          mov    $0x4007b8,%edi
  400665:   e8 06 fe ff ff          callq  400470 <puts@plt>

在 40065b 地址处有哪个机器代码以及您的代码的哪一行完成了此操作。


这里我给了你和示例代码,在发生分段的地方和系统的段故障信号上将调用一个处理程序,并且我已经获取了最后执行的机器周期的地址并打印该地址。为了验证该地址,我还显示了该代码的对象转储和段错误行的机器指令匹配。

我想这就是你想要的。

关于c - Linux 信号处理。如何获取中断指令的地址?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34989829/

相关文章:

c - 流打印和重定向

c - 验证用户输入时如何处理缓冲区错误

将字符串转换为 unsigned long int

linux - 为什么 pstack 比仅附加、保存堆栈和退出的 gdb 快得多?

linux - 没有更新以反射(reflect)新文件吗?

linux - 如何在 Linux 中使用 sig*set 函数?

qt - Qt中事件和信号有什么区别

c - Visual C++ 2010 Express 代码中的灰色(禁用)文本。这是什么意思?我该如何解决?

linux - 无法通过 HTTPS 在 Linux 上克隆 github 存储库

c++ - 用户空间和内核空间进程中的一组信号处理程序