我想设置一个"滚动"断点gdb; 只打印当前的源代码行,并提供一些信息; 然后继续 我从这样的事情开始:
break doSomething
commands
continue
end
Run Code Online (Sandbox Code Playgroud)
这本身打印出:
Breakpoint 1, doSomething () at myprog.c:55
55 void doSomething() {
Run Code Online (Sandbox Code Playgroud)
我想删除"Breakpoint X ... at ..."消息,可以使用silent- 然后打印出源代码行; 所以我试过了:
break doSomething
commands
silent
list
continue
end
Run Code Online (Sandbox Code Playgroud)
这导致10行列表,如下所示
50 // some comments
...
55 void doSomething() {
...
59 // other comments
Run Code Online (Sandbox Code Playgroud)
问题是,说list 1再次给出10行,只是从第一行开始; 虽然做的list +0,+0确实只提供一行来源 - 但错误的行(在我的情况下,它给出了第50行).
那么,我意识到可以通过使用程序计数器获取并打印当前程序地址$pc- 并且考虑到也可以列出程序地址,我试过这个:
break doSomething
commands
silent
#print $pc
list *$pc,+0
continue
end
Run Code Online (Sandbox Code Playgroud)
这会产生正确的源代码行 - 但由于某种原因,再次使用额外的消息,这次"ADDR在X ...":
0x8048fe0 is in doSomething (myprog.c:55).
55 void doSomething() {
Run Code Online (Sandbox Code Playgroud)
任何想法如何只打印源线?
作为一个子问题 - 是否可能以某种方式捕获list命令的输出,并将其用作printfgdb脚本方言中的参数?(我很确定捕获gdb命令输出可以通过python gdb脚本完成)...
嗯,我想我用 gdb 的 Python 得到了更好的结果;现在我可以得到如下所示的输出(使用 gdb 7.3.50.20110806-cvs):
[ 56] 0x8048fe0 myprog.c:55 void doSomething() {
[ 56] 0x8049058 myprog.c:63 }
Run Code Online (Sandbox Code Playgroud)
在大多数情况下,我尝试使用Symbol-Tables-In-Python来实现这一点(事实证明也有一个关于此的问题:gdb find memory address of line number)。
但是,由于某种原因,当我使用Symtab_and_line.line“指示该对象的当前行号”时,它似乎没有改变?在上面的示例中,它是方括号中的第一个数字,并且始终为 56(在这两种情况下都是错误的)。人们本来希望 API 能够涵盖所有内容;但事实并非如此。虽然行号在那里(尽管是错误的?) - 我在任何地方都找不到相应源代码行的字符串内容作为对象属性。另一方面,当我根据 OP 直接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
Run Code Online (Sandbox Code Playgroud)