通过与程序陷阱标志和陷阱信号处理程序,在崩溃试图vsyscall单步执行 [英] Trying to single step through program with trap-flag and trap-signal-handler, crash on vsyscall

查看:1009
本文介绍了通过与程序陷阱标志和陷阱信号处理程序,在崩溃试图vsyscall单步执行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个程序的执行完整的指令跟踪,收集一些统计数据等。我第一次使用Linux的ptrace的功能步程序(使用教程的这里)。这产生两个过程,跟踪的一个和调试器,它们通过信号通信。我只得到大约每秒16K指令(在1.6GHz的凌动),所以这是太慢了什么不平凡的。

I'd like to create a complete instruction trace of the execution of a program, to collect some stats etc. I first tried using linux' ptrace functionality to step through a program (using the tutorial here). This creates two processes, the traced one and the debugger, and they communicate via signals. I only got around 16K instructions per second (on 1.6GHz Atom), so this is too slow for anything non-trivial.

我认为是通过信号的进程间通信速度太慢,所以我试图在同一个进程中执行设置调试:设置陷阱标志,并创建一个信号处理程序。当一个软件中断是用来做系统调用,陷阱标志应保存,内核会用它自己的标志 - 所以我想。但是我的程序以某种方式得到由信号SIGTRAP杀害。

I thought the interprocess communication via signals is too slow, so I tried setting up the debugging in the same process as the execution: Set the trap flag, and create a signal handler. When a software interrupt is used to make a syscall, the trap flag should be saved, the kernel would use it's own flags - so I thought. But my program somehow gets killed by signal SIGTRAP.

这是我设置:

#include <stdio.h>
#include <unistd.h>
#include <signal.h>

int cycle = 0;
void trapHandler(int signum) {
  if (cycle % 262144 == 0) {
    write(STDOUT_FILENO," trap\n",6);
  }
  cycle += 1;
}

void startTrace() {
  // set up signal handler                                                                                                         
  signal(SIGTRAP, trapHandler);

  // set trap flag                                                                                                                 
  asm volatile("pushfl\n"
               "orl $0x100, (%esp)\n"
               "popfl\n"
               );
}

void printRock() {
  char* s = "Rock\n";
  asm(
      "movl $5, %%edx\n" // message length                                                                                         
      "movl %0, %%ecx\n" // message to write                                                                                       
      "movl $1, %%ebx\n" // file descriptor (stdout)                                                                               
      "movl $4, %%eax\n" // system call number (sys_write)                                                                         
      "int  $0x80\n"   // sycall                                                                                                   
      : // no output regs                                                                                                          
      : "r"(s) // input text                                                                                                       
      : "edx","ecx","ebx","eax"
      );
}

int main() {
  startTrace();

  // some computation                                                                                                              
  int x = 0;
  int i;
  for (i = 0; i < 100000; i++) {
    x += i*2;
  }

  printRock();
  write(STDOUT_FILENO,"Paper\n",6);
  write(STDOUT_FILENO,"Scissors\n",9);
}

在运行时,这给:

When running, this gives:

 trap
 trap
 trap
Rock
Paper
 trap
Trace/breakpoint trap (core dumped)

所以,现在我们得到约每秒250K的指令,仍然缓慢,但不平凡的执行是可能的。但是,出现的两个写调用之间发生的核心转储。在GDB中,我们看到它发生:

So now we get about 250K instructions per second, still slow but non-trivial executions are possible. But there is that core dump that appears to happen between the two write calls. In GDB, we see where it happens:

Dump of assembler code for function __kernel_vsyscall:
   0xb76f3414 <+0>:  push   %ecx
   0xb76f3415 <+1>:  push   %edx
   0xb76f3416 <+2>:  push   %ebp
   0xb76f3417 <+3>:  mov    %esp,%ebp
   0xb76f3419 <+5>:  sysenter 
   0xb76f341b <+7>:  nop
   0xb76f341c <+8>:  nop
   0xb76f341d <+9>:  nop
   0xb76f341e <+10>: nop
   0xb76f341f <+11>: nop
   0xb76f3420 <+12>: nop
   0xb76f3421 <+13>: nop
   0xb76f3422 <+14>: int    $0x80
=> 0xb76f3424 <+16>: pop    %ebp
   0xb76f3425 <+17>: pop    %edx
   0xb76f3426 <+18>: pop    %ecx
   0xb76f3427 <+19>: ret 

和回溯:

Program terminated with signal SIGTRAP, Trace/breakpoint trap.
#0  0xb77c5424 in __kernel_vsyscall ()
#1  0xb76d0553 in __write_nocancel () at ../sysdeps/unix/syscall-template.S:81
#2  0x0804847d in trapHandler (signum=5) at count.c:8
#3  <signal handler called>
#4  0xb77c5424 in __kernel_vsyscall ()
#5  0xb76d0553 in __write_nocancel () at ../sysdeps/unix/syscall-template.S:81
#6  0x08048537 in main () at count.c:49

这似乎是通过 INT 80 所发生的罚款系统调用,但写入呼叫使用内核的VIDSO / vsyscall打破以某种方式(我不知道这个功能,更贴近这里描述 )。这可能与使用 SYSENTER ,而不是 80 INT ,也许步入内核的时候陷阱标志生存。我不太得到什么用递归去 __ kernel_vsyscall 来电。我也不明白为什么还有的 __ kernel_vsyscall 函数中的 80 INT 电话。

It appears syscalls that happen via int 80 are fine, but the write calls use the kernel's VIDSO/vsyscall break somehow (I didn't know about this functionality, closer described here). It may be related to using sysenter rather than int 80, maybe the trap flag survives when stepping into the kernel. I don't quite get what's going with the recursive __kernel_vsyscall calls. I also don't get why there's an int 80 call inside the __kernel_vsyscall function.

没有任何人有一个建议,这是怎么回事,如何解决这一问题?也许这是可以禁用VDSO / vsysicall?或者是有可能与一个使用覆盖 __ kernel_vsyscall 函数 INT 80 ,而不是 SYSENTER

Does anybody have a suggestion what's going on, and how to fix this? Maybe it's possible to disable the VDSO/vsysicall? Or is it possible to override the __kernel_vsyscall function with one that uses int 80 rather than sysenter?

推荐答案

回答自己的问题。
我没弄明白发生了什么事,或详细解释,但我找到了一个解决办法:禁用VDSO。这可以通过

Answering own question. I didn't figure out what was happening or explain it in detail, but I found a workaround: disable VDSO. That can be done via

sudo sysctl vm.vdso_enabled=0

通过这一点,通过程序这整个单步工作,包括跨系统调用步进。免责声明:如果事情坏就不要怪我。

With this, this whole single stepping through a program works, including stepping across system calls. Disclaimer: don't blame me if things go bad.

这篇关于通过与程序陷阱标志和陷阱信号处理程序,在崩溃试图vsyscall单步执行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆