4

私は、ある時点で、私が開発したライブラリによって管理される別のスタックを使用する必要があるアプリケーションを開発しています。そこで、このライブラリの初期化関数を呼び出すと、スタックポインタ($ sp)が必要なメモリアドレスに設定されます。

GDBを介してこのコードを実行する場合、他のスタックの初期化が完了し、実行が呼び出し元の関数に戻った後、GDBは次の警告を表示します。

warning: GDB can't find the start of the function at 0x12.

    GDB is unable to find the start of the function at 0x12
and thus can't determine the size of that function's stack frame.
This means that GDB may be unable to access that stack frame, or
the frames below it.
    This problem is most likely caused by an invalid program counter or
stack pointer.
    However, if you think GDB should simply search farther back
from 0x12 for code which looks like the beginning of a
function, you can increase the range of the search using the `set
heuristic-fence-post' command.

また、$ spを出力すると、古い値が表示されます。

コードのこの部分はGDBがなくても正しく実行され、0x12には関数がないため、これはGDBがスタックポインターを使用して関数のフレームを追跡するためにアドレス指定するために発生します。

この動作を回避し、このアプリケーションをデバッグできるようにする方法はありますか?

4

2 に答える 2

1

必要なのはGDB/Pythonのフレームアンワインドだと思います。私はそれを自分で使用したことはありませんが、フレームの巻き戻しは、プロセスのコールスタックを再構築する(内部の)プロセスです。

あなたが言ったように、あなたは$SP値を変更するので、GDBは標準の呼び出し規約を認識しません。カスタムフレームアンワインダーを使用すると、使用するスタックレイアウトをGDBに教えることができます。

ドキュメントで提供されている例を次に示します。

 from gdb.unwinders import Unwinder

 class FrameId(object):
     def __init__(self, sp, pc):
         self.sp = sp
         self.pc = pc


 class MyUnwinder(Unwinder):
     def __init__(....):
         super(MyUnwinder, self).__init___(<expects unwinder name argument>)

     def __call__(pending_frame):
         if not <we recognize frame>:
             return None
         # Create UnwindInfo.  Usually the frame is identified by the stack
         # pointer and the program counter.
         sp = pending_frame.read_register(<SP number>)
         pc = pending_frame.read_register(<PC number>)
         unwind_info = pending_frame.create_unwind_info(FrameId(sp, pc))

         # Find the values of the registers in the caller's frame and
         # save them in the result:
         unwind_info.add_saved_register(<register>, <value>)
         ....

         # Return the result:
         return unwind_info

ドキュメントによると、を使用してCPUレジスタにアクセスできますがPendingFrame.read_register (reg_name or reg_id)、明らかに、ローカル変数の読み取りが問題になる可能性があります。

アンワインダーが適切に構築されたら、GDBに透過的に統合され、通常のCLIメカニズムがすべて使用可能になります。

于 2016-01-08T07:41:20.237 に答える
1

これは、GDBがスタックポインタを使用してアドレスを指定し、関数のフレームを追跡するために発生します。

はい、どうやらそうです

gdb_reader_funcsのget_frame_idは、現在のフレームに対応するgdb_frame_idを返します。[...]これを行う1つの方法は、関数に入るときにCODE_ADDRESSが関数の最初の命令を指し、STACK_ADDRESSがスタックポインターの値を指すようにすることです。

これを修正する1つの方法は、コードを2つの異なる関数に分離することだと思います(単にそれらの間をジャンプする場合のイベント)。

于 2016-01-08T10:18:43.777 に答える