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.