6

getcontext(3)背景: / makecontext(3)/ setcontext(3)( ucontext.h; SUSv2, POSIX.1-2001) ファミリの関数を使用して、独自のマシン コンテキストとスタックを割り当てています。

スレッドが割り当てたこれらのコンテキストのいずれかにあるときに、gdb (バージョン 6.1.1) を使用してスタックを調べると、gdb はスタックの最後 (論理的な底) がどこにあるかを認識していないようです。たとえば、x86 FreeBSD のスタックは次のとおりです。

#0  0x2872d79f in poll () from /lib/libc.so.7
#1  0x28646e23 in poll () from /lib/libthr.so.3
#2  0x2869b267 in fdtask (task=0x28a3dc40, v=0x0) at fd.c:58
#3  0x2869c8dc in taskstart (y=681827392, x=0) at task.c:58
#4  0x00000000 in ?? ()
#5  0x28a3dc40 in ?? ()
#6  0x00000000 in ?? ()
#7  0x00000000 in ?? ()
…
#65 0x00000000 in ?? ()
…

(はい、これはRuss Cox の libtask ライブラリの上に構築されています。)

このコンテキストの実行はtaskstart関数で始まりますが、そのフレームで NULL の戻りアドレスにヒットしたにもかかわらず、GDB はスタックの読み取りを停止する必要があることを理解できないようです。

私の質問は: GDB がスタックのトップがどこにあるかを理解するのを助けるために (何らかの方法でスタックをフォーマットしたり、レジスタを設定したりすることによって) できることはありますか? ありがとう。

編集:結論: gdb 6.1.1 がスタックの終わりを検出する 1 つの方法は、格納されたフレーム ポインターが NULL であることを確認することです。makecontext(2)新しいコンテキストを初期化するときに、x86 および amd64 関数を変更して ebp または rbp をゼロにリセットすることで、ユース ケースの問題を修正しました。(この場合、他のアーキテクチャは気にしません。) この問題は gdb 7.1 で解消されました。おそらく gdb 7.1 は、debuginfo などの他の手段でスタックの終わりを検出できます。

4

2 に答える 2

2

GDBがフレームポインタを使用してスタックを巻き戻す場合(DWARF2以前の方法)、nullフレームポインタに到達すると停止すると思います。DWARF2 では、"フレーム ポインター" は、現在の命令の命令ポインターおよび DWARF2 フレーム オフセット情報と組み合わされたスタック ポインターによって暗黙的に決定されるため、はるかに複雑ですが、基本的に効果は同じです。最近、どの FreeBSD が使用されているかわかりません。

于 2012-04-05T16:32:56.630 に答える
0

gdbドキュメントによると、バックトレース フレームのリストを停止する方法の 1 つは、 のリターン アドレスの後ですmain()

gdb/doc/gdb.textinfo の ftp://sourceware.org/pub/gdb/snapshots/current/gdb-7.4.50.20120405.tar.bz2 の6251行を参照してください@cindex backtrace beyond @code{main} function

于 2012-04-05T19:05:51.020 に答える