如何在GDB的断点处打印当前的源代码行,而没有其他的东西? [英] How to print the current line of source at breakpoint in GDB and nothing else?

查看:90
本文介绍了如何在GDB的断点处打印当前的源代码行,而没有其他的东西?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在 gdb 中设置一个滚动断点。那里只是用一些信息打印当前源代码行;然后继续。

  break doSomething 
命令
继续
结束

这样就可以打印出来:

断点1,doSomething()at myprog.c:55 
55 void doSomething(){

我想删除Breakpoint X ... at ...消息,这可以通过 silent 来完成 - 并且然后打印输出源代码行;所以我试过:

  break doSomething 
命令
silent
列表
继续
end

结果为10行,如下所示

  50 //一些注释
...
55 void doSomething(){
...
59 //其他评论

问题在于,说 list 1 将再次提供10行,从第一行开始;在做 list + 0,+ 0 时确实只提供一行代码 - 但是错误的代码行(在我的情况下,代码行代码为50)。 b
$ b

因此,我意识到可以通过使用程序计数器 $ pc 来获取并打印当前的程序地址 - 还可以列出一个程序地址,我试过这个:

pre $ break doSomething
命令
silent
$ print $ pc
list * $ pc,+ 0
continue
end

这会产生正确的源代码行 - 但由于某些原因,再次带有额外的消息,这次ADDR在X ...中:

  0x8048fe0在doSomething(myprog.c:55)中。 
55 void doSomething(){

任何想法如何仅 源代码行打印?



作为一个子问题 - 是否有可能以某种方式捕获列表的输出命令,并将它用作gdb脚本方言中 printf 的参数? (我非常确定通过python gdb脚本来捕获 gdb 命令输出可以完成)...

解决方案

好吧,我认为我用gdb的Python获得了更好的地方;现在我可以看到输出如下所示(使用gdb 7.3.50.20110806-cvs):

  [56] 0x8048fe0 myprog。 c:55 void doSomething(){
[56] 0x8049058 myprog.c:63}

大多数情况下,我尝试使用 Symbol-Tables-In-Python 得到这个结果(原来还有一个关于这个问题的SO问题: gdb查找行号的内存地址)。

但是,出于某种原因,当我使用 Symtab_and_line.line 时,其中表示当前行这个对象的编号,它似乎没有改变?在上面的例子中,它是方括号中的第一个数字,并且始终位于56处(两种情况都是错误的)。人们希望API能够涵盖所有内容;虽然行号在那里(虽然错了?) - 我无法在任何地方找到相应源代码行的字符串内容作为对象属性。另一方面,当我使用 gdb.execute(list * $ pc,+ 0)来查询 gdb 直接关于当前行的每个OP,我得到正确的行号 - 但是,然后,我必须另外拆分和解析Python中的字符串:/



不过,总比没有好 - 这里是(嵌入在gdb脚本中的Python)代码;只需将它放入 .gdbinit 中:



pre $ py

#例子:这些断点停止 - 但不能改变它们的
#stop方法(它包含python断点的命令)
#ax = gdb.Breakpoint(doSomething)
#print(hello,ax)
#print(dir(ax))
#print(ax.expression,ax.condition,ax.commands)#not writeable!
#bx = gdb.Breakpoint(myprog.c:63)

#不止于此 - 需要子类:

class MyBreakpoint(gdb。断点):
def __init __(self,spec,command =):
super(MyBreakpoint,self).__ init __(spec,gdb.BP_BREAKPOINT,
internal = False)
self.command = command#未使用

def stop(self):
#gdb.write - like print
#gdb.decode_line() - 像gdb.find_pc_line pc)

current_line = gdb.decode_line()
symtline = current_line [1] [0]
#print(current_line,symtline.is_valid(),symtline.line,symtline .pc,symtline.symtab)

sysy = symtline.symtab
#print(sysy.filename,sysy.fullname(),sysy.is_valid())

sysyo = sysy.objfile
#print(sysyo.filename,sysyo.is_valid(),sysyo.pretty_printers)
### print(gdb.solib_name())#this break stuff stuff ??!

sourcefilename = sysy.filename
sourcefullpath = sysy.fullname()
sourcelinenum = symtline.line#它可能会偏移1,从list * $ pc说:

listingline = gdb.execute(list * $ pc,+ 0,to_string = True)
#print(BREAK at%s:%d - %s %(sourcefilename,sourcelinenum,listingline))

llsplit = listingline.split(\\\

listpreamble,gdbsourceline = llsplit [:2]
addr,noneed,没有使用funcname,fileloc = listpreamble.split()[:5]
#linenum,sourceline = gdbsourceline.split(\t)[:2]#not the these - put gdb line verbatim

outline =[%4s]%s%16s:%s%(sourcelinenum,addr,sourcefilename [-16:],gdbsourceline)
print(outline)
return False#继续(不要停下来)

ax = MyBreakpoint(doSomething)
bx = MyBreakpoint(myprog.c:63)
结束

运行


I want to set a "rolling" breakpoint in gdb; there just print the current source line with some info; and then continue. I start with something like this:

break doSomething
commands
  continue
end

This, on its own, prints out:

Breakpoint 1, doSomething () at myprog.c:55
55  void doSomething() {

I wanted to remove the "Breakpoint X ... at ..." message, which can be done with silent - and then printout just the source line; so I tried:

break doSomething
commands
  silent
  list 
  continue
end

This results with 10 lines of listing, like below

50  // some comments
...
55  void doSomething() {
...
59  // other comments

The problem is, saying list 1 will again give 10 lines, just starting from the first line; while doing list +0,+0 will indeed provide one line of source only - but the wrong line (in my case, it gives line 50).

So, then I realized that one can get and print the current program address by using the program counter $pc - and given that one can also list around a program address, I tried this:

break doSomething
commands
  silent
  #print $pc
  list *$pc,+0
  continue
end

This results with correct source line - but for some reason, again with an extra message, this time "ADDR is in X ..." :

0x8048fe0 is in doSomething (myprog.c:55).
55  void doSomething() {

Any ideas how to get only the source line to print?

As a sub-question - is it possible somehow to capture the output of the list command, and use it as an argument to printf in the gdb scripting dialect? (I'm pretty sure capturing gdb command output can be done through the python gdb scripting, though)...

解决方案

Well, I think I got somewhere better with gdb's Python; now I can get the output to look like this (using gdb 7.3.50.20110806-cvs):

[  56] 0x8048fe0         myprog.c:55    void doSomething() {
[  56] 0x8049058         myprog.c:63    }

For the most part, I tried to use Symbol-Tables-In-Python to get to this (turns out there was an SO question about this, too: gdb find memory address of line number).

But, for some reason, when I use Symtab_and_line.line, which "Indicates the current line number for this object", it doesn't seem to change? In the above example, it is the first number in square brackets, and sits constantly at 56 (and is wrong in both cases). One would have hoped that the API would have had all that covered; and while the line number is there (albeit wrong?) - I couldn't find the string content of the respective source code line, as an object attribute, anywhere. On the other hand, when I use gdb.execute("list *$pc,+0") to query gdb directly about the current line as per OP, I get correct line numbers - but then, I have to additionally split and parse strings in Python :/

Still, better than nothing - here's the (Python embedded in gdb script) code; just throw it in your .gdbinit:

python

# example: these breakpoints do stop - but cannot change their 
# stop method (which contains the "commands" for breakpoint in python)
#ax = gdb.Breakpoint("doSomething")
#print("hello", ax)
#print(dir(ax))
#print(ax.expression, ax.condition, ax.commands) # not writable!
#bx = gdb.Breakpoint("myprog.c:63")

# anything more than that - need to subclass:

class MyBreakpoint(gdb.Breakpoint):
  def __init__(self, spec, command=""):
    super(MyBreakpoint, self).__init__(spec, gdb.BP_BREAKPOINT,
                                             internal = False)
    self.command = command # not used

  def stop(self):
    # gdb.write - like print
    # gdb.decode_line() - like gdb.find_pc_line(pc)

    current_line = gdb.decode_line()
    symtline = current_line[1][0]
    #print(current_line, symtline.is_valid(), symtline.line , symtline.pc , symtline.symtab )

    sysy = symtline.symtab
    #print(sysy.filename, sysy.fullname(), sysy.is_valid() )

    sysyo = sysy.objfile
    #print(sysyo.filename, sysyo.is_valid(), sysyo.pretty_printers)
    ###print(gdb.solib_name()) # this breaks stuff??!

    sourcefilename = sysy.filename
    sourcefullpath = sysy.fullname()
    sourcelinenum = symtline.line   # somehow, it may be offset by 1, from what "list *$pc says"

    listingline = gdb.execute("list *$pc,+0", to_string=True)
    #print( "BREAK at %s:%d -- %s" % (sourcefilename, sourcelinenum, listingline) )

    llsplit = listingline.split("\n")
    listpreamble, gdbsourceline = llsplit[:2]
    addr, noneed, noneed, funcname, fileloc = listpreamble.split(" ")[:5]
    #linenum, sourceline = gdbsourceline.split("\t")[:2] # not using these - put gdb line verbatim

    outline = "[% 4s] %s % 16s:%s" % (sourcelinenum, addr, sourcefilename[-16:], gdbsourceline)
    print(outline)
    return False # continue (do not stop inferior)

ax = MyBreakpoint("doSomething")
bx = MyBreakpoint("myprog.c:63")
end

run

这篇关于如何在GDB的断点处打印当前的源代码行,而没有其他的东西?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆