简体   繁体   English

如何在GDB的断点处打印当前的源代码行?

[英]How to print the current line of source at breakpoint in GDB and nothing else?

I want to set a "rolling" breakpoint in gdb ; 我想在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; 我想删除“Breakpoint X ... at ...”消息,这可以通过silent完成 - 然后打印出源代码行; so I tried: 所以我试过了:

break doSomething
commands
  silent
  list 
  continue
end

This results with 10 lines of listing, like below 这导致10行列表,如下所示

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; 问题是, list 1将再次给出10行,只是从第一行开始; while doing list +0,+0 will indeed provide one line of source only - but the wrong line (in my case, it gives line 50). 当做list +0,+0确实只提供一行源 - 但是错误的行(在我的例子中,它给出了第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: 所以,然后我意识到可以使用程序计数器$pc来获取并打印当前程序地址 - 并且考虑到也可以列出程序地址,我试过这个:

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 ..." : 这会产生正确的源代码行 - 但由于某种原因,再次使用额外的消息,这次“ADDR在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? 作为一个子问题 - 是否有可能以某种方式捕获list命令的输出,并将其用作gdb脚本方言中printf的参数? (I'm pretty sure capturing gdb command output can be done through the python gdb scripting, though)... (我很确定捕获gdb命令输出可以通过python gdb脚本完成)...

Well, I think I got somewhere better with gdb's Python; 好吧,我想我用gdb的Python可以更好地处理它; now I can get the output to look like this (using gdb 7.3.50.20110806-cvs): 现在我可以让输出看起来像这样(使用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 ). 在大多数情况下,我尝试使用Symbol-Tables-In-Python来实现这一点(原来还有一个关于这个的问题: gdb找到行号的内存地址 )。

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? 但是,出于某种原因,当我使用Symtab_and_line.line ,“ 表示此对象的当前行号 ”时,它似乎没有改变? In the above example, it is the first number in square brackets, and sits constantly at 56 (and is wrong in both cases). 在上面的例子中,它是方括号中的第一个数字,并且始终位于56(在两种情况下都是错误的)。 One would have hoped that the API would have had all that covered; 人们原本希望API能涵盖所有这些内容; 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 :/ 另一方面,当我使用gdb.execute("list *$pc,+0")直接查询gdb关于OP的当前行时,我得到正确的行号 - 但是,我必须另外拆分并解析Python中的字符串:/

Still, better than nothing - here's the (Python embedded in gdb script) code; 仍然,总比没有好 - 这是(嵌入在gdb脚本中的Python)代码; just throw it in your .gdbinit : 把它扔进你的.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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM