如何在gdb中使用信号处理程序调试C程序? [英] How to debug a C program with signal handler in gdb?
问题描述
我编写了一个简单的程序来了解信号处理程序的控制流传输.以下程序将使孩子重复写入.text区域并触发处理程序.
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;
}
但是,我想使用gdb进行验证.拆卸主电源得到下面的组件.我在下面使用命令创建了一个断点,因此gdb可以在将其写入.text区域之前在该点处断开.
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
(gdb) b *0x00000000004006fb
然后我在gdb中运行该程序.但是gdb不会停止并继续执行信号处理程序.
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
问题: 1.为什么gdb不会在我指定的地址处中断?
Questions: 1.Why gdb wont break at the address I specify?
2.如何使用gdb,以便知道指令指针从信号处理程序返回时指向的确切地址?
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?
推荐答案
为什么gdb不会在我指定的地址处中断?
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.
要调试子级,请使用set follow-fork-mode child
.
如何使用gdb,以便知道指令指针从信号处理程序返回时指向的确切地址?
How can I use gdb so that I know the exact address the instruction pointer points to when it returns from the signal handler?
在信号处理程序的ret
指令上放置一个断点,并在击中该断点时执行x/a $rsp
.
Put a breakpoint on the ret
instruction in the signal handler, and do x/a $rsp
when that breakpoint is hit.
这篇关于如何在gdb中使用信号处理程序调试C程序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!