简体   繁体   中英

How to debug a C program with signal handler in gdb?

I wrote a simple program to understand the control flow transfer of a signal handler. The following program will let the child to repetitively write to .text region and trigger the handler.

#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;                                                          
}             

However, I want to verify this using gdb. Disassembling the main gives the assembly below. I created a break point using command below so gdb can break at the point right before it write to the .text region.

(gdb) b *0x00000000004006fb

Then I run the program in gdb. But the gdb wont stop and keeps executing the signal handler.

   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 <signal@plt>
   0x00000000004006d8 <+30>:    cmp    $0xffffffffffffffff,%rax
   0x00000000004006dc <+34>:    jne    0x4006e8 <main+46>
   0x00000000004006de <+36>:    mov    $0x4007ba,%edi
   0x00000000004006e3 <+41>:    callq  0x400590 <perror@plt>
   0x00000000004006e8 <+46>:    callq  0x4005a0 <fork@plt>
   0x00000000004006ed <+51>:    test   %eax,%eax
   0x00000000004006ef <+53>:    jne    0x40070c <main+82>
   0x00000000004006f1 <+55>:    mov    $0x4007c7,%edi
   0x00000000004006f6 <+60>:    callq  0x400530 <puts@plt>
   0x00000000004006fb <+65>:    movb   $0x61,0x9b(%rip)        # 0x40079d
   0x0000000000400702 <+72>:    mov    $0x4007d9,%edi
   0x0000000000400707 <+77>:    callq  0x400530 <puts@plt>
   0x000000000040070c <+82>:    mov    $0x0,%eax
   0x0000000000400711 <+87>:    leaveq 
   0x0000000000400712 <+88>:    retq   

Questions: 1.Why gdb wont break at the address I specify?

2.How can I use gdb so that I know the exact address the instruction pointer points to when it returns from the signal handler?

Why gdb wont break at the address I specify?

Because you are debugging the wrong (parent) process.

The instruction you want to stop on is only executed in the child, and you aren't debugging the child.

To debug the child, use set follow-fork-mode child .

How can I use gdb so that I know the exact address the instruction pointer points to when it returns from the signal handler?

Put a breakpoint on the ret instruction in the signal handler, and do x/a $rsp when that breakpoint is hit.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM