github.com/shogo82148/std@v1.22.1-0.20240327122250-4e474527810c/runtime/traceback.go (about)

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package runtime
     6  
     7  import (
     8  	"github.com/shogo82148/std/unsafe"
     9  )
    10  
    11  // SetCgoTracebackは、Cコードからトレースバック情報を収集し、そのトレースバック情報をシンボル情報に変換するために使用する3つのC関数を記録します。
    12  // これらは、cgoを使用するプログラムのスタックトレースを印刷するときに使用されます。
    13  //
    14  // トレースバックとコンテキスト関数は、シグナルハンドラから呼び出すことができるため、
    15  // 非同期シグナルセーフ関数のみを使用する必要があります。
    16  // シンボライザ関数は、プログラムがクラッシュしている間に呼び出される可能性があるため、
    17  // メモリの使用に注意する必要があります。これらの関数のいずれも、Goにコールバックすることはできません。
    18  //
    19  // context関数は、構造体へのポインタを単一の引数として呼び出されます。
    20  //
    21  //	struct {
    22  //		Context uintptr
    23  //	}
    24  //
    25  // In C syntax, this struct will be
    26  //
    27  //	struct {
    28  //		uintptr_t Context;
    29  //	};
    30  //
    31  // Contextフィールドが0の場合、context関数は現在のトレースバックコンテキストを記録するために呼び出されます。
    32  // おそらくスタックポインタとPCなど、後でスタックトレースを生成するために必要な現在の実行ポイントに関する情報をContextフィールドに記録する必要があります。
    33  // この場合、context関数はCコードから呼び出されます。
    34  //
    35  // Contextフィールドが0でない場合、それは以前のcontext関数の呼び出しで返された値です。
    36  // この場合、GoコードがCコードの呼び出し元に戻るとき、つまりコンテキストが不要になったときに呼び出されます。
    37  // これにより、context関数は関連するリソースを解放できます。
    38  //
    39  // context関数が呼び出されるたびに完全なスタックトレースを記録し、
    40  // traceback関数でそれを単にコピーすることが正しいと言えますが、
    41  // 典型的なプログラムでは、context関数はそのコンテキストのためにトレースバックを記録することなく多数の呼び出しが行われます。
    42  // context関数の呼び出しで完全なスタックトレースを記録することは、効率的ではない可能性があります。
    43  //
    44  // traceback関数は、構造体へのポインタを単一の引数として呼び出されます。
    45  //
    46  //	struct {
    47  //		Context    uintptr
    48  //		SigContext uintptr
    49  //		Buf        *uintptr
    50  //		Max        uintptr
    51  //	}
    52  //
    53  // In C syntax, this struct will be
    54  //
    55  //	struct {
    56  //		uintptr_t  Context;
    57  //		uintptr_t  SigContext;
    58  //		uintptr_t* Buf;
    59  //		uintptr_t  Max;
    60  //	};
    61  //
    62  // Contextフィールドが0の場合、現在のプログラム実行ポイントからトレースバックを収集するために使用されます。
    63  // この場合、traceback関数はCコードから呼び出されます。
    64  //
    65  // それ以外の場合、Contextは以前のcontext関数の呼び出しで返された値です。
    66  // traceback関数は、その保存されたプログラム実行ポイントからスタックトレースを収集する必要があります。
    67  // traceback関数は、コンテキストが有効で変更されていないことがわかっている場合にのみ、
    68  // コンテキストを記録した実行スレッド以外の実行スレッドから呼び出すことができます。
    69  // traceback関数は、同じスレッドでコンテキストを記録した深い呼び出しスタックでも呼び出すことができます。
    70  // traceback関数は、同じContext値で複数回呼び出されることがあります。
    71  // 特定のコンテキスト値に対して最初に呼び出された場合、可能であれば結果をキャッシュするのが通常適切です。
    72  //
    73  // Unixシステムのシグナルハンドラからtraceback関数が呼び出された場合、
    74  // SigContextはシグナルハンドラに渡されたシグナルコンテキスト引数です(uintptr_tにキャストされたCのucontext_t*)。
    75  // これを使用して、シグナルが発生したポイントからトレースを開始できます。
    76  // traceback関数がシグナルハンドラから呼び出されていない場合、SigContextはゼロになります。
    77  //
    78  // Bufはトレースバック情報を格納する場所です。
    79  // Buf[0]が呼び出し元のPCであり、Buf[1]がその関数の呼び出し元のPCであるような、PC値である必要があります。
    80  // Maxは格納するエントリの最大数です。
    81  // 関数は、スタックのトップを示すためにゼロを格納する必要があります。
    82  // または、呼び出し元が別のスタック、おそらくGoスタックにあることを示します。
    83  //
    84  // runtime.Callersとは異なり、返されるPC値は、
    85  // シンボライザ関数に渡された場合、呼び出し命令のファイル/行を返す必要があります。
    86  // 追加の減算は必要ありません。また、適切ではありません。
    87  //
    88  // すべてのプラットフォームで、トレースバック関数は、GoからCへの呼び出しとCからGoへの呼び出しの間でスタックトレースを要求する場合に呼び出されます。
    89  // linux/amd64、linux/ppc64le、linux/arm64、およびfreebsd/amd64では、トレースバック関数は、cgo呼び出しを実行しているスレッドがシグナルを受信した場合にも呼び出されます。
    90  // トレースバック関数は、いつ呼び出されるかについての仮定をするべきではありません。将来のGoのバージョンでは、追加の呼び出しが行われる可能性があります。
    91  //
    92  // シンボライザ関数は、構造体へのポインタを単一の引数として呼び出されます。
    93  //
    94  //	struct {
    95  //		PC      uintptr // 情報を取得するプログラムカウンタ
    96  //		File    *byte   // ファイル名(NULで終わる)
    97  //		Lineno  uintptr // 行番号
    98  //		Func    *byte   // 関数名(NULで終わる)
    99  //		Entry   uintptr // 関数のエントリポイント
   100  //		More    uintptr // このPCに対してさらに情報がある場合は非ゼロに設定します
   101  //		Data    uintptr // ランタイムによって使用されない、関数で使用可能なデータ
   102  //	}
   103  //
   104  // C言語の構文では、この構造体は次のようになります。
   105  //
   106  //	struct {
   107  //		uintptr_t PC;
   108  //		char*     File;
   109  //		uintptr_t Lineno;
   110  //		char*     Func;
   111  //		uintptr_t Entry;
   112  //		uintptr_t More;
   113  //		uintptr_t Data;
   114  //	};
   115  //
   116  // PCフィールドは、traceback関数の呼び出しで返される値です。
   117  //
   118  // トレースバック関数が特定のトレースバックに対して最初に呼び出された場合、
   119  // PC以外のすべてのフィールドは0になります。
   120  // 情報が利用できない場合は、フィールドを0/nilに設定して、他のフィールドを埋める必要があります。
   121  // Dataフィールドは、呼び出し間で有用な情報を格納するために使用できます。
   122  // Moreフィールドは、このPCに対してさらに情報がある場合は非ゼロに設定します。
   123  // Moreが非ゼロに設定されている場合、同じPCで再度呼び出され、異なる情報を返すことができます(これはインライン関数で使用するために意図されています)。
   124  // Moreがゼロの場合、次のPC値でトレースバック関数が呼び出されます。
   125  // トレースバックが完了すると、PCがゼロに設定された状態で関数が1回呼び出されます。
   126  // これは、情報を解放するために使用できます。
   127  // 各呼び出しでは、Moreフィールドがゼロである場合を除き、構造体のフィールドが呼び出し前と同じ値に設定されたままになります。
   128  // 関数は、呼び出し間で構造体ポインタのコピーを保持してはいけません。
   129  //
   130  // SetCgoTracebackを呼び出すとき、version引数は関数が受け取る構造体のバージョン番号です。
   131  // 現在、これは0でなければなりません。
   132  //
   133  // シンボライザ関数がnilの場合、トレースバック関数の結果は数値として表示されます。
   134  // トレースバック関数がnilの場合、シンボライザ関数は呼び出されません。
   135  // コンテキスト関数がnilの場合、トレースバック関数はコンテキストフィールドが0に設定された状態でのみ呼び出されます。
   136  // コンテキスト関数がnilの場合、GoからCへの呼び出しでは、C部分の呼び出しスタックのトレースバックは表示されません。
   137  //
   138  // SetCgoTracebackは、理想的にはinit関数から1回だけ呼び出す必要があります。
   139  func SetCgoTraceback(version int, traceback, context, symbolizer unsafe.Pointer)