2017-06-04 4 views
0

Ich schrieb ein einfaches Programm, um die Kontrolle Flussübertragung eines Signal-Handler zu verstehen. Das folgende Programm lässt das Kind wiederholt in die .text-Region schreiben und den Handler auslösen.Wie Debuggen eines C-Programms mit Signalhandler in Gdb?

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

Allerdings möchte ich dies mit gdb überprüfen. Das Zerlegen des Hauptteils ergibt die folgende Montage. Ich habe einen Breakpoint mit dem folgenden Befehl erstellt, so dass GDB an dem Punkt brechen kann, direkt bevor es in die .text-Region schreibt.

(GDB) b * 0x00000000004006fb

Dann laufe ich das Programm in gdb. Aber der gdb stoppt nicht und führt den Signalhandler weiter aus.

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 

Fragen: 1.Why gdb gewohnt an der Adresse breche ich angeben?

2.Wie kann ich gdb verwenden, damit ich die genaue Adresse kenne, auf die der Befehlszeiger zeigt, wenn er vom Signalhandler zurückkehrt?

+1

Sie sollten printf nicht im Signalhandler verwenden –

+0

@SeekAddo, OK. Ich kann es ändern, um Informationen in eine Datei zu protokollieren. Aber wie löse ich die Hauptfrage? – drdot

+0

Mögliches Duplikat von [Wie kann ich GDB dazu bringen, mir mitzuteilen, welche Adresse einen Fehler verursacht hat?] (Https://stackoverflow.com/questions/3003339/how-can-i-get-gdb-to-tell-me-what -address-aded-a-segfault) –

Antwort

1

Warum gdb bricht nicht an der von mir angegebenen Adresse?

Weil Sie den falschen (übergeordneten) Prozess debuggen.

Die Anweisung, die Sie anhalten möchten, wird nur im untergeordneten Code ausgeführt, und Sie debuggen das untergeordnete Element nicht.

Um das Kind zu debuggen, verwenden Sie set follow-fork-mode child.

Wie kann ich gdb verwenden, damit ich die genaue Adresse weiß, auf die der Befehlszeiger zeigt, wenn er vom Signalhandler zurückkehrt?

Setzen Sie einen Haltepunkt auf der ret Anweisung in den Signal-Handler und x/a $rsp tun, wenn das Haltepunkt erreicht wird.

Verwandte Themen