voidprint(int xx, int *xxptr){ printf('In print():\n'); printf(' xx is %d and is stored at %p.\n', xx, &xx); printf(' ptr points to %p which holds %d.\n', xxptr, *xxptr); }
intmain(void){ int x = 10; int *ptr = &x; printf('In main():\n'); printf(' x is %d and is stored at %p.\n', x, &x); printf(' ptr points to %p which holds %d.\n', ptr, *ptr); print(x, ptr); return0; }
这个代码比较简单,下面我们开始进入调试:
gdb ./test_main GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-114.el7 Copyright (C) 2013 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http:///licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type 'show copying' and 'show warranty' for details. This GDB was configured as 'x86_64-redhat-linux-gnu'. For bug reporting instructions, please see: <http://www./software/gdb/bugs/>... Reading symbols from /root/test_main...done. (gdb) r Starting program: /root/./test_main In main(): x is 10 and is stored at 0x7fffffffe424. ptr points to 0x7fffffffe424 which holds 10. In print(): xx is 10 and is stored at 0x7fffffffe40c. xxptr points to 0x7fffffffe424 which holds 10. [Inferior 1 (process 31518) exited normally] Missing separate debuginfos, use: debuginfo-install glibc-2.17-260.el7.x86_64
(gdb) b 15 Breakpoint 1 at 0x400601: file test_main.cc, line 15. (gdb) info b Num Type Disp Enb Address What 1 breakpoint keep y 0x0000000000400601in main() at test_main.cc:15 (gdb) r Starting program: /root/./test_main In main(): x is 10 and is stored at 0x7fffffffe424. ptr points to 0x7fffffffe424 which holds 10.
Breakpoint 1, main() at test_main.cc:15 15 print(xx, xxptr); Missing separate debuginfos, use: debuginfo-install glibc-2.17-260.el7.x86_64 (gdb)
backtrace
(gdb) backtrace #0 main () at test_main.cc:15 (gdb)
(gdb) b 27 Breakpoint 1 at 0x4013d5: file test.cc, line 27. (gdb) b test.cc:32 Breakpoint 2 at 0x40142d: file test.cc, line 32. (gdb) info b Num Type Disp Enb Address What 1 breakpoint keep y 0x00000000004013d5in main() at test.cc:27 2 breakpoint keep y 0x000000000040142d in main() at test.cc:32 (gdb) r Starting program: /root/test [Thread debugging using libthread_db enabled] Using host libthread_db library '/lib64/libthread_db.so.1'.
Breakpoint 1, main() at test.cc:27 (gdb) c Continuing. 3 [New Thread 0x7ffff6fd2700(LWP 44996)] in fun_int n = 1 [New Thread 0x7ffff67d1700 (LWP 44997)]
Breakpoint 2, main () at test.cc:32 32std::cout << 'after thread create' << std::endl; (gdb) info threads Id Target Id Frame 3 Thread 0x7ffff67d1700 (LWP 44997) 'test'0x00007ffff7051fc3in new_heap() from /lib64/libc.so.6 2 Thread 0x7ffff6fd2700(LWP 44996) 'test' 0x00007ffff7097e2d in nanosleep() from /lib64/libc.so.6 * 1 Thread 0x7ffff7fe7740(LWP 44987) 'test' main() at test.cc:32 (gdb) thread 2 [Switching to thread 2 (Thread 0x7ffff6fd2700 (LWP 44996))] #0 0x00007ffff7097e2d in nanosleep() from /lib64/libc.so.6 (gdb) bt #0 0x00007ffff7097e2d in nanosleep() from /lib64/libc.so.6 #1 0x00007ffff7097cc4 in sleep() from /lib64/libc.so.6 #2 0x00007ffff796ceb9 in std::this_thread::__sleep_for(std::chrono::duration<long, std::ratio<1l, 1l> >, std::chrono::duration<long, std::ratio<1l, 1000000000l> >)() from /lib64/libstdc++.so.6 #3 0x00000000004018cc in std::this_thread::sleep_for<long, std::ratio<1l, 1l> > (__rtime=...) at /usr/include/c++/4.8.2/thread:281 #4 0x0000000000401307 in fun_int(n=1) at test.cc:9 #5 0x0000000000404696 in std::_Bind_simple<int(*(int))(int)>::_M_invoke<0ul>(std::_Index_tuple<0ul>)(this=0x609080) at /usr/include/c++/4.8.2/functional:1732 #6 0x000000000040443d in std::_Bind_simple<int(*(int))(int)>::operator()()(this=0x609080) at /usr/include/c++/4.8.2/functional:1720 #7 0x000000000040436e in std::thread::_Impl<std::_Bind_simple<int(*(int))(int)> >::_M_run()(this=0x609068) at /usr/include/c++/4.8.2/thread:115 #8 0x00007ffff796d070 in ?? () from /lib64/libstdc++.so.6 #9 0x00007ffff7bc6dd5 in start_thread() from /lib64/libpthread.so.0 #10 0x00007ffff70d0ead in clone() from /lib64/libc.so.6 (gdb) c Continuing. after thread create in fun_int n = 1 [Thread 0x7ffff6fd2700 (LWP 45234) exited] in fun_string s = test [Thread 0x7ffff67d1700 (LWP 45235) exited] [Inferior 1 (process 45230) exited normally] (gdb) q
在上述调试过程中:
b 27 在第27行加上断点
b test.cc:32 在第32行加上断点(效果与b 32一致)
info b 输出所有的断点信息
r 程序开始运行,并在第一个断点处暂停
c 执行c命令,在第二个断点处暂停,在第一个断点和第二个断点之间,创建了两个线程t1和t2
info threads 输出所有的线程信息,从输出上可以看出,总共有3个线程,分别为main线程、t1和t2
gdb -q ./test_process Reading symbols from /root/test_process...done. (gdb)
这里需要说明下,之所以加-q选项,是想去掉其他不必要的输出,q为quite的缩写。
(gdb) r Starting program: /root/./test_process Detaching after fork from child process 37482. this is parent,pid = 37478 [Inferior 1 (process 37478) exited normally] Missing separate debuginfos, use: debuginfo-install glibc-2.17-260.el7.x86_64 libgcc-4.8.5-36.el7.x86_64 libstdc++-4.8.5-36.el7.x86_64 (gdb) attach 37482 //符号类输出,此处略去 (gdb) n Single stepping until exit from function __nanosleep_nocancel, which has no line number information. 0x00007ffff72b3cc4 in sleep () from /lib64/libc.so.6 (gdb) Single stepping until exit from function sleep, which has no line number information. main () at test_process.cc:8 8 while(num==10){ (gdb)
在上述命令中,我们执行了n(next的缩写),使其重新对while循环的判断体进行判断。
(gdb) set num = 1 (gdb) n 12 printf('this is child,pid = %d\n',getpid()); (gdb) c Continuing. this is child,pid = 37482 [Inferior 1 (process 37482) exited normally] (gdb)
(gdb) show follow-fork-mode Debugger response to a program call of fork or vfork is 'parent'. (gdb) set follow-fork-mode child (gdb) r Starting program: /root/./test_process [New process 37830] this is parent,pid = 37826
^C Program received signal SIGINT, Interrupt. [Switching to process 37830] 0x00007ffff72b3e10 in __nanosleep_nocancel () from /lib64/libc.so.6 Missing separate debuginfos, use: debuginfo-install glibc-2.17-260.el7.x86_64 libgcc-4.8.5-36.el7.x86_64 libstdc++-4.8.5-36.el7.x86_64 (gdb) n Single stepping until exit from function __nanosleep_nocancel, which has no line number information. 0x00007ffff72b3cc4 in sleep () from /lib64/libc.so.6 (gdb) n Single stepping until exit from function sleep, which has no line number information. main () at test_process.cc:8 8 while(num==10){ (gdb) show follow-fork-mode Debugger response to a program call of fork or vfork is 'child'. (gdb)
在上述命令中,我们做了如下操作:
show follow-fork-mode:通过该命令来查看当前处于什么模式下,通过输出可以看出,处于parent即父进程模式
set follow-fork-mode child:指定调试子进程模式
r:运行程序,直接运行程序,此时会进入子进程,然后执行while循环
ctrl + c:通过该命令,可以使得GDB收到SIGINT命令,从而暂停执行while循环
n(next):继续执行,进而进入到while循环的条件判断处
show follow-fork-mode:再次执行该命令,通过输出可以看出,当前处于child模式下
在断点处恢复指令后,增加了一个条件判断。如果表达式为真,则触发断点。由于需要判断一次,添加条件断点后,是否触发条件断点,都会影响性能。在 x86 平台上,部分硬件支持硬件断点。不是在条件断点处插入 int 3,而是插入另一条指令。当程序到达这个地址时,不是发出int 3信号,而是进行比较。特定寄存器的内容和某个地址,然后决定是否发送int 3。因此,当你的断点位置被程序频繁“通过”时,尽量使用硬件断点,这将有助于提高性能。
Thread 3 (Thread 0x7f07aaa69700 (LWP 45708)): #00x00007f07aab2ee2din nanosleep() from /lib64/libc.so.6 #1 0x00007f07aab2ecc4 in sleep() from /lib64/libc.so.6 #2 0x00007f07ab403eb9 in std::this_thread::__sleep_for(std::chrono::duration<long, std::ratio<1l, 1l> >, std::chrono::duration<long, std::ratio<1l, 1000000000l> >)() from /lib64/libstdc++.so.6 #3 0x00000000004018cc in voidstd::this_thread::sleep_for<long, std::ratio<1l, 1l> >(std::chrono::duration<long, std::ratio<1l, 1l> > const&)() #4 0x00000000004012de in fun_int(int)() #5 0x0000000000404696 in intstd::_Bind_simple<int(*(int))(int)>::_M_invoke<0ul>(std::_Index_tuple<0ul>)() #6 0x000000000040443d in std::_Bind_simple<int(*(int))(int)>::operator()()() #7 0x000000000040436e in std::thread::_Impl<std::_Bind_simple<int(*(int))(int)> >::_M_run()() #8 0x00007f07ab404070 in ?? () from /lib64/libstdc++.so.6 #9 0x00007f07ab65ddd5 in start_thread() from /lib64/libpthread.so.0 #10 0x00007f07aab67ead in clone() from /lib64/libc.so.6 Thread 2 (Thread 0x7f07aa268700 (LWP 45709)): #0 0x00007f07aab2ee2d in nanosleep() from /lib64/libc.so.6 #1 0x00007f07aab2ecc4 in sleep() from /lib64/libc.so.6 #2 0x00007f07ab403eb9 in std::this_thread::__sleep_for(std::chrono::duration<long, std::ratio<1l, 1l> >, std::chrono::duration<long, std::ratio<1l, 1000000000l> >)() from /lib64/libstdc++.so.6 #3 0x00000000004018cc in voidstd::this_thread::sleep_for<long, std::ratio<1l, 1l> >(std::chrono::duration<long, std::ratio<1l, 1l> > const&)() #4 0x0000000000401340 in fun_string(std::stringconst&)() #5 0x000000000040459f in intstd::_Bind_simple<int(*(charconst*))(std::stringconst&)>::_M_invoke<0ul>(std::_Index_tuple<0ul>)() #6 0x000000000040441f in std::_Bind_simple<int(*(charconst*))(std::stringconst&)>::operator()()() #7 0x0000000000404350 in std::thread::_Impl<std::_Bind_simple<int(*(charconst*))(std::stringconst&)> >::_M_run()() #8 0x00007f07ab404070 in ?? () from /lib64/libstdc++.so.6 #9 0x00007f07ab65ddd5 in start_thread() from /lib64/libpthread.so.0 #10 0x00007f07aab67ead in clone() from /lib64/libc.so.6 Thread 1 (Thread 0x7f07aba80740 (LWP 45707)): #0 0x00007f07ab65ef47 in pthread_join() from /lib64/libpthread.so.0 #1 0x00007f07ab403e37 in std::thread::join()() from /lib64/libstdc++.so.6 #2 0x0000000000401455 in main()