5

「ローリング」ブレークポイントを設定したいgdb; 現在のソース行に情報を出力するだけです。続けます。私は次のようなことから始めます:

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 行を与えると言うことです。実際にはソースの1行のみを提供しlist +0,+0ますが、間違った行を提供します(私の場合、50行目を提供します)。

そのため、プログラムカウンターを使用して現在のプログラムアドレスを取得および出力できることに気付きました$pc-プログラムアドレスの周りをリストすることもできるので、これを試しました:

break doSomething
commands
  silent
  #print $pc
  list *$pc,+0
  continue
end

これにより、正しいソース行が得られますが、何らかの理由で、今回は「ADDR is in X ...」という追加のメッセージが表示されます。

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

ソース行のみを印刷する方法はありますか?

サブ質問として - どうにかしてlistコマンドの出力をキャプチャし、それをprintfgdb スクリプトの方言で引数として使用することは可能ですか? gdb(ただし、コマンド出力のキャプチャは、python gdb スクリプトを使用して実行できると確信しています)...

4

1 に答える 1

4

まあ、私は gdb の Python でどこか良くなったと思います。出力を次のように表示できるようになりました (gdb 7.3.50.20110806-cvs を使用):

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

ほとんどの場合、Symbol-Tables-In-Pythonを使用してこれに到達しようとしました (これについても SO の質問がありました: gdb find memory address of line number )。

しかし、どういうわけか、 「このオブジェクトの現在の行番号を示しますSymtab_and_line.line」を使用すると、変更されないように見えますか? 上記の例では、それは角括弧内の最初の数字であり、常に 56 にあります (どちらの場合も間違っています)。API がすべてをカバーしてくれることを望んでいたでしょう。行番号が表示されている間 (間違っていますか?) - オブジェクト属性として、それぞれのソース コード行の文字列コンテンツがどこにも見つかりませんでした。一方、 OPに従って現在の行について直接クエリを実行すると、正しい行番号が得られますが、Pythonで文字列をさらに分割して解析する必要がありますgdb.execute("list *$pc,+0")gdb:/

それでも、何もないよりはましです - これが (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
于 2013-07-27T05:46:14.690 に答える