简体   繁体   中英

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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