2017-06-04 17 views
0

シグナルハンドラの制御フロー転送を理解するための簡単なプログラムを書きました。次のプログラムは、子プロセスが.text領域に繰り返し書き込むようにし、ハンドラをトリガします。gdbでシグナルハンドラを使ってCプログラムをデバッグする方法は?

#include "csapp.h" // just include standard headers        

extern char etext;                

void handler() {                 
    printf("pid = %d, in handler\n", getpid());         
    return;                  
}                    

int main(int argc, char **argv) {            
    if (signal(SIGSEGV, handler) == SIG_ERR) {          
    perror("signal error");              
    }                    

    if (fork() == 0) {                
    printf("from Child before\n");            
    etext = 'a';                 
    printf("from Child after\n");            
    }                    

    return EXIT_SUCCESS;               
}    

ただし、これをgdbで確認したいと思います。メインを分解すると下のアセンブリが得られます。以下のコマンドを使用してブレークポイントを作成したので、gdbは.text領域に書き込む前の時点でブレークできます。

(GDB)のb * 0x00000000004006fb

それから私は、GDBでプログラムを実行します。しかしgdbは止まりませんし、シグナルハンドラを実行し続けます。

0x00000000004006ba <+0>: push %rbp 
    0x00000000004006bb <+1>: mov %rsp,%rbp 
    0x00000000004006be <+4>: sub $0x10,%rsp 
    0x00000000004006c2 <+8>: mov %edi,-0x4(%rbp) 
    0x00000000004006c5 <+11>: mov %rsi,-0x10(%rbp) 
    0x00000000004006c9 <+15>: mov $0x40069d,%esi 
    0x00000000004006ce <+20>: mov $0xb,%edi 
    0x00000000004006d3 <+25>: callq 0x400570 <[email protected]> 
    0x00000000004006d8 <+30>: cmp $0xffffffffffffffff,%rax 
    0x00000000004006dc <+34>: jne 0x4006e8 <main+46> 
    0x00000000004006de <+36>: mov $0x4007ba,%edi 
    0x00000000004006e3 <+41>: callq 0x400590 <[email protected]> 
    0x00000000004006e8 <+46>: callq 0x4005a0 <[email protected]> 
    0x00000000004006ed <+51>: test %eax,%eax 
    0x00000000004006ef <+53>: jne 0x40070c <main+82> 
    0x00000000004006f1 <+55>: mov $0x4007c7,%edi 
    0x00000000004006f6 <+60>: callq 0x400530 <[email protected]> 
    0x00000000004006fb <+65>: movb $0x61,0x9b(%rip)  # 0x40079d 
    0x0000000000400702 <+72>: mov $0x4007d9,%edi 
    0x0000000000400707 <+77>: callq 0x400530 <[email protected]> 
    0x000000000040070c <+82>: mov $0x0,%eax 
    0x0000000000400711 <+87>: leaveq 
    0x0000000000400712 <+88>: retq 

質問: 1.WhyのGDBが文句を言わない私が指定したアドレスで破りますか?

2.シグナルハンドラから戻ったときに命令ポインタが指している正確なアドレスを知るためにgdbを使う方法はありますか?

+1

シグナルハンドラでprintfを使用しないでください。 –

+0

@SeekAddo、OK。私は情報をファイルに記録するように変更することができます。しかし、どのように私は主な問題を解決するのですか? – drdot

+0

[GDBにセグメンテーションの原因となったアドレスを教えてもらうにはどうすればいいですか?](https://stackoverflow.com/questions/3003339/how-can-i-get-gdb-to-tell-me-what -address-initiated-a-segfault) –

答えて

1

私が指定したアドレスでgdbが破損しないのはなぜですか?

間違った(親)プロセスをデバッグしているためです。

停止したい命令は、子プロセスでのみ実行され、子プログラムはデバッグされません。

子をデバッグするには、set follow-fork-mode childを使用してください。

シグナルハンドラから戻ったときに命令ポインタが指している正確なアドレスを知るためにgdbを使用するにはどうすればよいですか?

シグナルハンドラ内でret命令にブレークポイントを置いて、そのブレークポイントにヒットしたときにx/a $rspを行います。

関連する問題