gdb - 按预定义规则跳过某个文件的进一步步骤?

时间:2016-11-07 11:49:24

标签: c gdb step-into

假设我有这个文件:

xb@dnxb:/tmp/c$ cat helloworld.h
void hello();
xb@dnxb:/tmp/c$ cat helloworld.c
#include <stdio.h>
void hello() {
  printf("Hello world!\n");
  printf("Next line\n");
}

xb@dnxb:/tmp/c$ cat main.c
#include <stdio.h>
#include "helloworld.h"
int
main(void) {
        hello();
        return 0;
}

编译:

xb@dnxb:/tmp/c$ gcc -g3 -shared -o libhello.so -fPIC helloworld.c -std=c11
xb@dnxb:/tmp/c$ gcc -g3 main.c -o main -Wl,-rpath,"$PWD" -L. -lhello

然后用gdb调试:

xb@dnxb:/tmp/c$ gdb -q -n ./main
Reading symbols from ./main...done.
(gdb) b main
Breakpoint 1 at 0x40062a: file main.c, line 5.
(gdb) r
Starting program: /tmp/c/main 

Breakpoint 1, main () at main.c:5
5               hello();
(gdb) s
hello () at helloworld.c:3
3         printf("Hello world!\n");

此时,反复按 Enter (相当于类型s并反复按 Enter ):

(gdb) 
_IO_puts (str=0x7ffff7bd9689 "Hello world!") at ioputs.c:33
33      ioputs.c: No such file or directory.
(gdb) 
35      in ioputs.c
(gdb) 
strlen () at ../sysdeps/x86_64/strlen.S:66
66      ../sysdeps/x86_64/strlen.S: No such file or directory.
(gdb) 

如果我只关心helloworld.c而没有进一步进入printf() ioputs.c以上的xb@dnxb:/tmp/c$ gdb -q -n ./main Reading symbols from ./main...done. (gdb) b main Breakpoint 1 at 0x40062a: file main.c, line 5. (gdb) r Starting program: /tmp/c/main Breakpoint 1, main () at main.c:5 5 hello(); (gdb) s hello () at helloworld.c:3 3 printf("Hello world!\n"); (gdb) n Hello world! 4 printf("Next line\n"); (gdb) 该怎么办?

helloworld.c

这就是我想要的,但它需要我手动发现我在n,现在是时候相应地输入(gdb) s hello () at helloworld.c:3 3 printf("Hello world!\n"); 了。我想要的是:

helloworld.c

Enter 将跳过自定义文件名的步入,例如在这种情况下printf("Next line\n");,并直接跳至(gdb) Hello world! 4 printf("Next line\n"); (gdb)

s

好处是我不必发现我应该停在哪里n并更改为helloworld.c,特别是如果代码层次结构很大并且我可能会步入<table class="w3-table-all w3-small w3-responsive"> <thead> <tr class="w3-green"> <th style="padding:15px; font-weight:bold;">Departure Dates</th> <th style="padding:15px; font-weight:bold;">Departure Availablity</th> <th style="padding:15px; font-weight:bold;">Trip Cost</th> <th style="padding:15px; font-weight:bold;">Inquiry</th> </tr> </thead> <tr class="w3-hover-pale-green"> <td id="tripDate"><?=$ddate1='March, 21, 2017 - April, 06, 2017'?></td> <td class="available">Available</td> <td>USD$ 1250.00</td> <td><a class="w3-btn w3-small w3-green w3-hover-green fancybox fancybox.iframe" href="<?=ROOTDIR.$_PHPLIB['contact']?>index.php?trpName=<?=$tripName?>&trpDate=<?=$ddate1;?>&trpUrl=<?=$actual_link;?>">Inquiry</a></td> </tr> <tr class="w3-hover-pale-green"> <td id="tripDate"><?=$ddate1='March, 28, 2017 - April, 13, 2017'?></td> <td class="available">Available</td> <td>USD$ 1250.00</td> <td><a class="w3-btn w3-small w3-green w3-hover-green fancybox fancybox.iframe" href="<?=ROOTDIR.$_PHPLIB['contact']?>index.php?trpName=<?=$tripName?>&trpDate=<?=$ddate1;?>&trpUrl=<?=$actual_link;?>">Inquiry</a></td> </tr> <tr class="w3-hover-pale-green"> <td id="tripDate"><?=$ddate1='April, 04, 2017 - April, 20, 2017'?></td> <td class="available">Available</td> <td>USD$ 1250.00</td> <td><a class="w3-btn w3-small w3-green w3-hover-green fancybox fancybox.iframe" href="<?=ROOTDIR.$_PHPLIB['contact']?>index.php?trpName=<?=$tripName?>&trpDate=<?=$ddate1;?>&trpUrl=<?=$actual_link;?>">Inquiry</a></td> </tr> </table> 时间。我只需要反复按 Enter 并跳过不需要的深度/等级。

我该怎么做?

2 个答案:

答案 0 :(得分:1)

<强> [代码]

我在我的gdb启动文件~/.gdbinit中编写了这段代码(在我编写此代码之前,前6行是我现有的行):

set environment HISTSIZE 10000000
set history filename ~/.gdb_history
set history save on
set history size 10000000
set history expansion on
show history

#compile/make gdb failed 
#rf: http://stackoverflow.com/a/33663513/1074998 #use `make install`

#rf: http://stackoverflow.com/a/15306144/1074998 #for step into strcpy(), memcpy()
#gcc -fno-builtin -g foo.c
#other rf: https://ubuntuforums.org/showthread.php?t=1572766

#rf: https://codywu2010.wordpress.com/2014/09/13/why-is-my-gdb-step-command-behavior-changed/
# printf step into 1st instruction is: _IO_puts (kali default gdb) vs puts (self-compile gdb)

#rf: http://stackoverflow.com/a/31076131/1074998
#nosharedlibrary, sharedlibrary

#rf: http://www.sourceware.org/gdb/onlinedocs/gdb/Source-Path.html #dir
#rf2: https://www.chemie.fu-berlin.de/chemnet/use/info/gdb/gdb_8.html #dir
#rf: http://stackoverflow.com/a/20116541/1074998
#`apt-get source libc6` and put the path of stdio-common (use `find . -name '*stdio-common*'` to find out)
dir '/home/xiaobai/note/src/gdb-7.11.1/glibc-2.24/stdio-common'
#rf: http://stackoverflow.com/a/29956038/1074998
dir '/usr/src/glibc/glibc-2.24/malloc'
set step-mode on

#rf: https://sourceware.org/gdb/onlinedocs/gdb/Define.html
#set max-user-call-depth 100000000

#type alias 'my' enough, nod ni type `mystart`
define mystart
  #reset to fix "Value can't be converted to integer."
  #initialized with enough buffer to fix "Too many array elements"
  #`set {char [4096]}$fpath = 0` failed
  #rf1: http://reverseengineering.stackexchange.com/a/2216/15176
  #rf2: http://stackoverflow.com/a/30955291/1074998
  #rf3: http://serverfault.com/a/306726/210566 ,and http://stackoverflow.com/a/14508945/1074998 #max file fullpath is 4096
  set $fpath = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
  set $dindex = 0
  set $excludeFile="/tmp/c c/helloworld2.c"
  set $excludeFile2="/home/xiaobai/note/src/gdb-7.11.1/glibc-2.24/sysdeps/x86_64/strchr.S" 
  #to ensure `set $fpath = $mallocFile` later will not truncate buffer
  set $mallocFile = $fpath
  #set it to "mallo.c" if not do `sudo apt-get install glibc-source`, `cd /usr/src/glibc`, `sudo tar xvf glibc-N.NN.tar.xz`, and put `dir '/usr/src/glibc/glibc-N.NN/malloc'` on top of this file, rf: http://stackoverflow.com/a/29956038/1074998 
  set $mallocFile = "/usr/src/glibc/glibc-2.24/malloc/malloc.c"
  b main
  r
end
#rf: http://stackoverflow.com/a/1530774/1074998
define pFullPathTitle
    printf "\n******************** %s ********************\n", $fpath
end
define pFilePathTitle
    printf "\n******************** <%s> ********************\n", $fpath
end
define sn
  set $dindex += 1
  echo \n[customStepping]\n\n

  #rf: https://sourceware.org/gdb/onlinedocs/gdb/Logging-Output.html
  set logging off
  set logging file /tmp/gdbFile
  set logging redirect on
  set logging on
  #ensure put this after `set logging on` otherwise will not work
  set logging overwrite
  #http://stackoverflow.com/a/1907066/1074998 #info source
  #Bcareful might got extra headline "warning: Currently logging to /tmp/gdbFile.  Turn the logging off and on to make the new setting effective."
  #and line "^Located in " will not exist at all if no full filepath which was so common
  info source
  set logging off
  #rf1: http://stackoverflow.com/a/6889615/1074998 #shell var to gdb
  #rf2: http://unix.stackexchange.com/a/151609/64403 #eval
  #rf3: http://www.delorie.com/gnu/docs/gdb/gdb_118.html #set var
  #rf4: https://sourceware.org/gdb/download/onlinedocs/gdb/Convenience-Vars.html
  #rf5: http://unix.stackexchange.com/a/320342/64403 #sed
  shell echo 'set $fpath = "'`cat /tmp/gdbFile | grep '^Located' | sed 's/^Located in //g'`'"' > /tmp/gdbFile.sources
  source /tmp/gdbFile.sources

  #rf: https://sourceware.org/gdb/onlinedocs/gdb/Command-Files.html #if-else
  #rf2: https://blogs.oracle.com/ksplice/entry/8_gdb_tricks_you_should #if
  #rf: http://stackoverflow.com/a/7424716/1074998 #strcmp
  if strcmp($fpath, $excludeFile) == 0
    pFullPathTitle
    echo File #1 [Stepping] Disabled \n
    n
  else
    if strcmp($fpath, $excludeFile2) == 0
            pFullPathTitle
            echo File #2 [Stepping] Disabled \n
            n
    else
        if strcmp($fpath, $mallocFile) == 0
            #due to gdb freeze at this point, so i disable it #manually run no such problem, weird
            #       #2925      victim = _int_malloc (ar_ptr, bytes);
            set $fpath = $mallocFile
            pFullPathTitle
            echo [mallo.c] freeze and should come here [Stepping] N/A\n\n
            info source
            #rf1: http://stackoverflow.com/a/9220953/1074998
            #rf2: http://stackoverflow.com/questions/39124817/gdb-freezes-in-malloc
            finish
            #n
        else
            if strcmp($fpath, "") == 0
                #`info source`'s "Located in " line not even exist !
                #get single filename and set it to $fpath, source it, then print the title with this filename
                shell echo 'set $fpath = "'`cat /tmp/gdbFile | grep '^Current source file is ' | sed 's/^Current source file is //g'`'"' > /tmp/gdbFile.sources
                source /tmp/gdbFile.sources
                pFilePathTitle
                s
            else
                pFullPathTitle
                s
            end
        end
    end
  end
end

<强> [说明]

<强> [1]

当遇到我想跳过踩踏的文件全路径时,基本的想法是n而不是s

<强> [2]

“AAAAA ...”(4096个字符串)字符串是我能找到的唯一可以保留内存$fpath的完整文件路径的方法,它需要在程序运行之前进行动态更新。它可能有更好的方法来处理它,如果你知道更好的方式,请发表评论。

<强> [3]

我的第一个问题是解析在info source内混合的完整文件路径。我修改了gdb源代码(gdb/source.c的{​​{1}}的{​​{1}}是完整的文件路径)并编译它。但是失败了,它在source_info的第一个步进中显示s->filename而不是puts,我不记得我做了什么,现在只更改为_IO_puts:< / p>

printf

但之后我意识到我可以先将libc.so.6的输出保存到(gdb) s hello () at helloworld.c:3 3 printf("Hello world!\n"); (gdb) 0x00007ffff788a160 in printf () from /lib/x86_64-linux-gnu/libc.so.6 (gdb) 0x00007ffff788a167 in printf () from /lib/x86_64-linux-gnu/libc.so.6 ... `s->filename` still give me /tmp/c c/helloworld.c which is not what i want. 中(使用info source hack)。现在使用gdb命令/tmp/gdbFile使用常规Unix工具(set logging / shell)解析文件,并将其重新格式化为grep,然后使用gdb命令sed设置变量:

/tmp/gdbFile.sources

<强> [4]

source是一个示例,显示它可以禁用多个+任何文件名。如果我启用步入$ cat /tmp/gdbFile warning: Currently logging to /tmp/gdbFile. Turn the logging off and on to make the new setting effective. Current source file is main.c Compilation directory is /tmp/c c Located in /tmp/c c/main.c Contains 7 lines. Source language is c. Producer is GNU C11 6.1.1 20160802 -mtune=generic -march=x86-64 -g3 -fno-builtin. Compiled with DWARF 2 debugging format. Includes preprocessor macro info. $ cat /tmp/gdbFile.sources set $fpath = "/usr/src/glibc/glibc-2.24/sysdeps/unix/sysv/linux/_exit.c" $ ,则会调用此文件。 (只需在我的问题中将文件名/home/xiaobai/note/src/gdb-7.11.1/glibc-2.24/sysdeps/x86_64/strchr.S更改为printf以进行测试)

<强> [5]

此代码使用文件路径中的空白空间进行测试,例如helloworld.c

<强> [6]

如果我想排除大量文件路径,我很难扩展,因为我必须手动插入helloworld2.c。如果您知道更好的方式,请发表评论。我也有点担心/tmp/c\ c/main深度的递归可能会导致问题(我不确定gdb如何在内部处理它),所以我确保if-else-endif-esle-end是最后一条指令条件。

<强> [7]

幸运的是,在我运行n后, Enter 不会更改为s / sn的最后一条指令),即重复按 Enter 将保持行为sn),否则我不知道如何分配它。

<强> [结果]

sn Enter 进入sn会自动将printf更改为helloworld.c,然后在返回后更改回s从这个文件。请注意,我的自定义函数名为n(如果没有其他命令名称以“my”开头,则s应该正常工作)和mystartup(不替换my,因此您可以在sn中间调用s来执行:):

s

答案 1 :(得分:1)

GDB的skip命令可以让您跳过踩到不感兴趣的函数或文件。它的语法是跳过uninteresting_function 跳过文件uninteresting.file 。 (完整文档here

在您的情况下,您应该尝试跳过文件ioputs.c

Gdb 7.12在文件和函数名称上引入了模式,因此如果需要,您应该构建/安装该版本。此版本允许您(例如)跳过文件-gfi / lib / * ,它会跳过/ lib /...中的任何源文件。