国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 操作系統(tǒng) > 正文

我的日常工具——gdb篇

2024-06-28 13:26:51
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友
我的日常工具——gdb篇我的日常工具——gdb篇

03 APR 2014


1.gdb的原理

熟悉linux的同學(xué)面試官會(huì)問(wèn)你用過(guò)gdb么?那好用過(guò),知道gdb是怎么工作的么?然后直接傻眼。。。 gdb是怎么接管一個(gè)進(jìn)程?并且能獲取這個(gè)進(jìn)程的變量、堆棧、寄存器、內(nèi)存映像等信息的呢?還可以打斷點(diǎn)執(zhí)行?這些都是gdb一些基本的功能。 很簡(jiǎn)單,ptrace,好來(lái)看看manual上這個(gè)系統(tǒng)調(diào)用的定義。

#include <sys/ptrace.h>long ptrace(enum __ptrace_request request, pid_t pid,void *addr,                     void *data);

簡(jiǎn)單描述:ptrace系統(tǒng)調(diào)用提供一種方法使某一父進(jìn)程(叫做"tracer")可以觀察并控制另外一個(gè)進(jìn)程(叫做"tracee")的執(zhí)行,而且還可以檢查并改變執(zhí)行tracee進(jìn)程時(shí)的內(nèi)存映像和寄存器。這個(gè)系統(tǒng)調(diào)用主要用來(lái)實(shí)現(xiàn)斷點(diǎn)調(diào)試和函數(shù)調(diào)用跟蹤( It is primarily used to implement breakpoint debugging and system call tracing)。

2.gdb將高級(jí)語(yǔ)言轉(zhuǎn)成匯編

對(duì)于c、c++這樣的語(yǔ)言,如果不注意內(nèi)存釋放經(jīng)常會(huì)出現(xiàn)“野指針”、“空指針”等,程序dump掉的時(shí)候要找清楚那地方crash了,匯編指令顯的非常重要。 比如:

程序1:

#include <stdio.h>struct foo{    int i;    char a[0];};struct fool{    struct foo *henry;};int main(){    struct fool test={0};    if(test.henry->a)        printf("%x/n",test.henry->a);    return 0;}

程序2:

#include <stdio.h>struct foo{    int i;    char *a;};struct fool{    struct foo *henry;};int main(){    struct fool test={0};    if(test.henry->a)        printf("%x/n",test.henry->a);    return 0;}

第一個(gè)程序不會(huì)core dump,而第二個(gè)程序core dump掉了。原因在第12行程序1訪問(wèn)的a是數(shù)組的地址,而程序2訪問(wèn)的時(shí)指針a的內(nèi)容,a為NULL指針,訪問(wèn)其內(nèi)容當(dāng)然時(shí)非法的。你可能要問(wèn)了,你為什么知道程序1訪問(wèn)的是地址而程序2訪問(wèn)的是內(nèi)容呢? 那就需要匯編指令幫忙了。

題外話:程序2dump會(huì)產(chǎn)生core文件,如果沒(méi)有出現(xiàn)core文件,用ulimit -c unlimited命令產(chǎn)生。
[henry@localhost core]$ gdb -c core.4340 GNU gdb (GDB) Fedora 7.6.50.20130731-19.fc20Copyright (C) 2013 Free Software Foundation, Inc.License GPLv3+: GNU GPL version 3 or later <http://gnu.org/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".Type "show configuration" for configuration details.For bug reporting instructions, please see:<http://www.gnu.org/software/gdb/bugs/>.Find the GDB manual and other documentation resources online at:<http://www.gnu.org/software/gdb/documentation/>.For help, type "help".Type "apropos Word" to search for commands related to "word".[New LWP 4340]Missing separate debuginfo for the main executable fileTry: yum --enablerepo='*debug*' install /usr/lib/debug/.build-id/73/a4410588cf88e43ecdfa6825cd15160aa6ddc7Core was generated by `./struct_dump1'.Program terminated with signal SIGSEGV, Segmentation fault.#0  0x0000000000400544 in ?? ()(gdb) file struct_dump1Reading symbols from /home/henry/code/core/struct_dump1...done.(gdb) bt#0  0x0000000000400544 in main () at struct_dump1.c:12(gdb) disassemble mainDump of assembler code for function main:   0x0000000000400530 <+0>:    push   %rbp   0x0000000000400531 <+1>:    mov    %rsp,%rbp   0x0000000000400534 <+4>:    sub    $0x10,%rsp   0x0000000000400538 <+8>:    movq   $0x0,-0x10(%rbp)   0x0000000000400540 <+16>:    mov    -0x10(%rbp),%rax=> 0x0000000000400544 <+20>:    mov    0x8(%rax),%rax   0x0000000000400548 <+24>:    test   %rax,%rax   0x000000000040054b <+27>:    je     0x400567 <main+55>   0x000000000040054d <+29>:    mov    -0x10(%rbp),%rax   0x0000000000400551 <+33>:    mov    0x8(%rax),%rax   0x0000000000400555 <+37>:    mov    %rax,%rsi   0x0000000000400558 <+40>:    mov    $0x400600,%edi   0x000000000040055d <+45>:    mov    $0x0,%eax   0x0000000000400562 <+50>:    callq  0x400410 <printf@plt>   0x0000000000400567 <+55>:    mov    $0x0,%eax   0x000000000040056c <+60>:    leaveq    0x000000000040056d <+61>:    retq End of assembler dump.

上面看到程序執(zhí)行時(shí)用bt提示程序在12行dump掉了,然后轉(zhuǎn)換成匯編代碼可以看到12行執(zhí)行的時(shí)mov指令。

  • 對(duì)于char a[0]來(lái)說(shuō),匯編代碼用了lea指令,lea 0×8(%rax), %rax
  • 對(duì)于char *a來(lái)說(shuō),匯編代碼用了mov指令,mov 0×8(%rax), %rax

lea指令是把地址放進(jìn)去,而mov是把內(nèi)容放進(jìn)去,而NULL指針的內(nèi)容是不能訪問(wèn)的。這就是前面提到的*a 和a[0]的不同。1

nisi是單步執(zhí)行匯編命令,和nextstep一樣,n表示在當(dāng)前函數(shù)一步步執(zhí)行,s代表跟蹤函數(shù),可以從當(dāng)前函數(shù)跳到另一個(gè)函數(shù)。display可以顯示一些寄存器內(nèi)容,如display /x $pc顯示程序計(jì)數(shù)器。info reg顯示所有寄存器內(nèi)容。

tips——關(guān)于NULL指針:

如果程序里有NULL指針,NULL指針會(huì)指向系統(tǒng)為程序分配的段地址的開始,系統(tǒng)為段開頭64k做苛刻的規(guī)定。程序中(低訪問(wèn)權(quán)限)訪問(wèn)要求高訪問(wèn)權(quán)限的這64K內(nèi)存被視作是不容許的,會(huì)引發(fā)access Volitation 錯(cuò)誤。64K內(nèi)存是一塊保留內(nèi)存(即不能被程序動(dòng)態(tài)內(nèi)存分配器分配,不能被訪問(wèn),也不能被使用),就是簡(jiǎn)單的保留,不作任何使用。2

下面的代碼是對(duì)空指針的測(cè)試:

#define NULL (void*)0int main(){  int *p1 = NULL;  int *p2 = NULL;  int *p3 = NULL;  return 0;} 下面是用gdb測(cè)試:[henry@localhost core]$ gcc -g null_point_test.c -o null_point_test[henry@localhost core]$ gdb null_point_test GNU gdb (GDB) Fedora 7.6.50.20130731-19.fc20Copyright (C) 2013 Free Software Foundation, Inc.License GPLv3+: GNU GPL version 3 or later <http://gnu.org/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".Type "show configuration" for configuration details.For bug reporting instructions, please see:<http://www.gnu.org/software/gdb/bugs/>.Find the GDB manual and other documentation resources online at:<http://www.gnu.org/software/gdb/documentation/>.For help, type "help".Type "apropos word" to search for commands related to "word"...Reading symbols from /home/henry/code/core/null_point_test...done.(gdb) list1    #define NULL (void*)02    int main()3    {4      int *p1 = NULL;5      int *p2 = NULL;6      int *p3 = NULL;7      return 0;8    }(gdb) b 7Breakpoint 1 at 0x40050c: file null_point_test.c, line 7.(gdb) rStarting program: /home/henry/code/core/null_point_test Breakpoint 1, main () at null_point_test.c:77      return 0;Missing separate debuginfos, use: debuginfo-install glibc-2.18-12.fc20.x86_64(gdb) p &p1$1 = (int **) 0x7fffffffdf08(gdb) p &p2$2 = (int **) 0x7fffffffdf00(gdb) p &p3$3 = (int **) 0x7fffffffdef8(gdb) p &p1$4 = (int *) 0x0(gdb) p &p2$5 = (int *) 0x0(gdb) p &p3$6 = (int *) 0x0(gdb) bt#0  main () at null_point_test.c:7(gdb) p main$4 = {int ()} 0x4004f0 <main>(gdb) 

可以看出gdb測(cè)試結(jié)果p1 p2 p3的內(nèi)容即null指針的地址都是

(int *) 0x0

正如上面多說(shuō)空指針指向段首,并且都指向一個(gè)內(nèi)存單元,null指針只有一個(gè)。

3.gdb調(diào)試core文件

gdb -c core文件命令調(diào)試core文件,調(diào)試過(guò)程種可能會(huì)總是一堆問(wèn)號(hào)的問(wèn)題,用symbol-file core文件對(duì)應(yīng)的bin文件命令添加字符集即可。

4.gdb條件斷點(diǎn)

已經(jīng)有了斷點(diǎn)break_num將其轉(zhuǎn)化成條件斷點(diǎn):condition break_num(斷點(diǎn)編號(hào)) cond(條件),當(dāng)滿足條件cond時(shí),GDB才會(huì)在斷點(diǎn)break_num處暫停程序的執(zhí)行。

break break_num if cond(條件)定義一個(gè)斷點(diǎn)并使之成為條件斷點(diǎn)。

tbreak break_num臨時(shí)斷點(diǎn),斷點(diǎn)執(zhí)行一次后此段點(diǎn)無(wú)效。

commands breakpoint_number可以設(shè)置執(zhí)行斷點(diǎn)breakpoint_number時(shí)執(zhí)行一段程序,有點(diǎn)批量執(zhí)行的意思,以end結(jié)束。

引用:

  1. 指針和數(shù)組的差別?

  2. 空指針保護(hù)政策?


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 吕梁市| 桐庐县| 隆德县| 合水县| 安义县| 泽库县| 杂多县| 阿瓦提县| 共和县| 辽宁省| 龙陵县| 尼勒克县| 阿克陶县| 乳源| 化隆| 滦南县| 双城市| 松溪县| 湖口县| 葫芦岛市| 泸溪县| 瑞安市| 浦县| 房产| 望谟县| 缙云县| 六盘水市| 仪陇县| 米脂县| 盘山县| 中方县| 永丰县| 临安市| 公主岭市| 宾阳县| 垫江县| 许昌市| 辽宁省| 高邮市| 马尔康县| 盐城市|