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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With