如何在GDB中打印当前断点处的源代码行而不显示其他内容?

5
我想在中设置一个“滚动”断点; 只需打印当前源代码行及相关信息,然后继续执行。我从以下内容开始:
break doSomething
commands
  continue
end

仅此,将会打印出:

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

我希望能去掉“Breakpoint X ... at ...”这个消息,可以通过使用 silent 来实现,并且只打印源代码行;因此我尝试了以下方法:

break doSomething
commands
  silent
  list 
  continue
end

这将导致10行清单,如下所示。
50  // some comments
...
55  void doSomething() {
...
59  // other comments

问题在于,输入list 1将再次给出10行,从第一行开始;而使用list +0,+0确实只提供了一行源代码 - 但是是错误的那一行(在我的情况下,它给出了第50行)。
所以,我意识到可以通过使用程序计数器$pc来获取和打印当前程序地址 - 鉴于可以围绕程序地址进行列表操作,因此我尝试了这个方法:
break doSomething
commands
  silent
  #print $pc
  list *$pc,+0
  continue
end

这会导致正确的源代码行输出,但出现了额外的信息,这次是“ADDR 在 X 中…”:

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

有什么想法可以只打印源代码行吗?

作为一个子问题,是否有可能以某种方式捕获list命令的输出,并将其用作gdb脚本方言中printf的参数?(我相当确定通过python gdb脚本可以捕获gdb命令输出,但是)...

1个回答

4

我认为使用gdb的Python工具可以更好地实现目标;现在我可以让输出结果看起来像这样(使用gdb 7.3.50.20110806-cvs版本):

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

大部分情况下,我试图使用 Python中的符号表 来实现这一目的(结果发现也有一个关于此的SO问题: gdb查找行号内存地址)。
但是,由于某种原因,当我使用“Symtab_and_line.line”时,它指示了该对象的当前行号,但似乎并没有变化?在上面的示例中,它是方括号中的第一个数字,并且始终为56(且两种情况下都是错误的)。人们本应该希望API已经覆盖了所有内容;虽然行号存在(尽管错误),但我无法在任何地方找到相应源代码行的字符串内容作为对象属性。另一方面,当我使用gdb.execute("list *$pc,+0")直接查询gdb关于当前行的信息时,我可以得到正确的行号——但是,我还需要在Python中额外地对字符串进行分割和解析。
尽管如此,这总比没有强——这里是嵌入GDB脚本的Python代码。只需将其放入您的.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

另外,Python 打印 ( gdb.execute("list *$pc,+0", False, True).splitlines()[1] )。 - sdaau

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接