Oracle® Developer Studio 12.5: パフォーマンスアナライザ

印刷ビューの終了

更新: 2016 年 6 月
 
 

データ収集と解析のためのプログラムの準備

データ収集と解析の準備のために、プログラムに対して特別な作業を行う必要はありません。次の処理のうち、いずれか 1 つでも行うプログラムの場合には、後述の該当するセクションを読んでください。

また、実行時にプログラムからデータ収集を制御する場合は、libcollector ライブラリを使用したデータ収集のプログラム制御を参照してください。

動的割り当てメモリーの利用

    多くのプログラムは、次のような機能を使用して、動的に割り当てられたメモリーに依存しています。

  • mallocvallocalloca (C/C++)

  • new (C++)

  • スタック局所変数 (Fortran)

  • MALLOCMALLOC64 (Fortran)

メモリー割り当てメソッドが初期値を設定するときに明示的に記述される場合を除いて、動的に割り当てられたメモリーの初期の内容にプログラムが依存しないように注意する必要があります。たとえば、malloc(3C) のマニュアルページにある callocmalloc の説明を比較してみます。

動的に割り当てられるメモリーを使用するプログラムを単独で実行すると、正常に機能しているように見えることがありますが、パフォーマンスデータの収集を有効にした状態で実行すると、問題が起きることがあります。この場合、浮動小数点演算の予期しない動作、セグメント例外、アプリケーション固有のエラーメッセージなどが発生する可能性があります。

こうした症状は、アプリケーションが単独で実行されたときには、初期化されていないメモリーの値が動作に影響ないものであっても、パフォーマンスデータの収集ツールとの組み合わせで実行されたときに別の値が設定されることによって、発生する場合があります。この場合は、パフォーマンスツールの問題ではありません。動的に割り当てられるメモリーの内容に依存するアプリケーションにはすべて、潜在的なバグがあります。オペレーティングシステムにより動的に割り当てられるメモリーの内容は、ドキュメントに明確に記載されている場合を除いて、どのような値をとる可能性もあります。現在のオペレーティングシステムが動的に割り当てられるメモリーに必ず特定の値を設定するようになっていたとしても、将来オペレーティングシステムのリリースが変わったとき、あるいはプログラムを別のオペレーティングシステムに移植した場合には、こうした潜在的な問題によって、予期しない動作が発生する可能性があります。

    次のツールが、こうした潜在的な問題の発見に役立ちます。

  • コードアナライザ。コンパイラやその他のツールと使用したときに次の項目を表示できる Oracle Developer Studio ツールです。

    静的コード検査

    コードアナライザは、Oracle Developer Studio の C または C++ コンパイラでアプリケーションをコンパイルし、–xanalyze=code オプションを指定した場合に実行される静的コード検査の結果を表示できます。

    動的メモリーアクセス検査

    コードアナライザは、discover–a オプションを使用してバイナリに計測機構を組み込んだあと、その計測機構が組み込まれたバイナリを実行してデータを生成するときに実行される動的メモリーアクセス検査の結果を表示できます。

    詳細は、Oracle Developer Studio 12.5: コードアナライザユーザーズガイドを参照してください

  • f95 -xcheck=init_local

    詳細は、Oracle Developer Studio 12.5: Fortran ユーザーズガイドまたは f95(1) のマニュアルページを参照してください。

  • lint ユーティリティー

    詳細は、Oracle Developer Studio 12.5: C ユーザーズガイドまたは lint(1) のマニュアルページを参照してください。

  • dbx 下での実行時チェック

    詳細は、Oracle Developer Studio 12.5: dbx コマンドによるデバッグマニュアルまたは dbx(1) のマニュアルページを参照してください。

システムライブラリの使用

さまざまな コレクタは、さまざまなシステムライブラリからの関数に割り込んでトレースデータを収集し、データ収集の整合性を保証します。コレクタがライブラリ関数の呼び出しに割り込む状況を次に示します。

  • 同期待ちトレースデータの収集。Oracle Solaris では、コレクタは Oracle Solaris C ライブラリ libc.so からの関数に割り込みます。

  • I/O トレースデータの収集。コレクタは次の関数に割り込みます。

    /* interposition function handles */
    static int (*__real_open)(const char *path, int oflag, ...) = NULL;
    #if WSIZE(32)
    static int (*__real_open64)(const char *path, int oflag, ...) = NULL;
    #endif
    static int (*__real_fcntl)(int fildes, int cmd, ...) = NULL;
    static int (*__real_openat)(int fildes, const char *path, int oflag, ...) = NULL;
    static int (*__real_close)(int fildes) = NULL;
    static FILE *(*__real_fopen)(const char *filename, const char *mode) = NULL;
    static int (*__real_fclose)(FILE *stream) = NULL;
    static int (*__real_dup)(int fildes) = NULL;
    static int (*__real_dup2)(int fildes, int fildes2) = NULL;
    static int (*__real_pipe)(int fildes[2]) = NULL;
    static int (*__real_socket)(int domain, int type, int protocol) = NULL;
    static int (*__real_mkstemp)(char *template) = NULL;
    static int (*__real_mkstemps)(char *template, int slen) = NULL;
    static int (*__real_creat)(const char *path, mode_t mode) = NULL;
    
    #if WSIZE(32)
    static int (*__real_creat64)(const char *path, mode_t mode) = NULL;
    #endif
    static FILE *(*__real_fdopen)(int fildes, const char *mode) = NULL;
    
    static ssize_t (*__real_read)(int fildes, void *buf, size_t nbyte) = NULL;
    static ssize_t (*__real_write)(int fildes, const void *buf, size_t nbyte) = NULL;
    static ssize_t (*__real_readv)(int fildes, const struct iovec *iov, int iovcnt) = NULL;
    static ssize_t (*__real_writev)(int fildes, const struct iovec *iov, int iovcnt) = NULL;
    static size_t (*__real_fread)(void *ptr, size_t size, size_t nitems, FILE *stream) = NULL;
    static size_t (*__real_fwrite)(void *ptr, size_t size, size_t nitems, FILE *stream) = NULL;
    static ssize_t (*__real_pread)(int fildes, void *buf, size_t nbyte, off_t offset) = NULL;
    static ssize_t (*__real_pwrite)(int fildes, const void *buf, size_t nbyte, off_t offset) = NULL;
    #if OS(Linux)
    static ssize_t (*__real_pwrite64)(int fildes, const void *buf, size_t nbyte, off64_t offset) = NULL;
    #endif
    static char *(*__real_fgets)(char *s, int n, FILE *stream) = NULL;
    static int (*__real_fputs)(const char *s, FILE *stream) = NULL;
    static int (*__real_fputc)(int c, FILE *stream) = NULL;
    static int (*__real_fprintf)(FILE *stream, const char *format, ...) = NULL;
    static int (*__real_vfprintf)(FILE *stream, const char *format, va_list ap) = NULL;
    
    static off_t (*__real_lseek)(int fildes, off_t offset, int whence) = NULL;
    static offset_t (*__real_llseek)(int fildes, offset_t offset, int whence) = NULL;
    static int (*__real_chmod)(const char *path, mode_t mode) = NULL;
    static int (*__real_access)(const char *path, int amode) = NULL;
    static int (*__real_rename)(const char *old, const char *new) = NULL;
    static int (*__real_mkdir)(const char *path, mode_t mode) = NULL;
    static int (*__real_getdents)(int fildes, struct dirent *buf, size_t nbyte) = NULL;
    static int (*__real_unlink)(const char *path) = NULL;
    static int (*__real_fseek)(FILE *stream, long offset, int whence) = NULL;
    static void (*__real_rewind)(FILE *stream) = NULL;
    static long (*__real_ftell)(FILE *stream) = NULL;
    static int (*__real_fgetpos)(FILE *stream, fpos_t *pos) = NULL;
    static int (*__real_fsetpos)(FILE *stream, const fpos_t *pos) = NULL;
    #if WSIZE(32)
    static int (*__real_fgetpos64)(FILE *stream, fpos64_t *pos) = NULL;
    static int (*__real_fsetpos64)(FILE *stream, const fpos64_t *pos) = NULL;
    #endif // WSIZE(32)
    static int (*__real_fsync)(int fildes) = NULL;
    static struct dirent *(*__real_readdir)(DIR *dirp) = NULL;
    #if OS(Linux)
    static int (*__real_flock)(int fd, int operation) = NULL;
    #endif
    static int (*__real_lockf)(int fildes, int function, off_t size) = NULL;
    static int (*__real_fflush)(FILE *stream) = NULL;
    #if OS(Linux) && ARCH(Intel) && WSIZE(32)
    static FILE *(*__real_fopen_2_1)(const char *filename, const char *mode) = NULL;
    static int (*__real_fclose_2_1)(FILE *stream) = NULL;
    static FILE *(*__real_fdopen_2_1)(int fildes, const char *mode) = NULL;
    static int (*__real_fgetpos_2_2)(FILE *stream, fpos_t *pos) = NULL;
    static int (*__real_fsetpos_2_2)(FILE *stream, const fpos_t *pos) = NULL;
    static FILE *(*__real_fopen_2_0)(const char *filename, const char *mode) = NULL;
    static int (*__real_fclose_2_0)(FILE *stream) = NULL;
    static FILE *(*__real_fdopen_2_0)(int fildes, const char *mode) = NULL;
    static int (*__real_fgetpos_2_0)(FILE *stream, fpos_t *pos) = NULL;
    static int (*__real_fsetpos_2_0)(FILE *stream, const fpos_t *pos) = NULL;
    #endif
  • ヒープトレースデータの収集。コレクタは、mallocreallocmemalignfree の関数に割り込みます。これらの関数は、C 標準ライブラリ libc.so のほか、libumen.solibmalloc.solibmtmalloc.so などのライブラリにあります。

  • MPI トレースデータの収集。コレクタは、指定された MPI ライブラリからの関数に割り込みます。

  • 時間データの完全性の確保。コレクタは setitimer に割り込み、プログラムがプロファイルタイマーを使用しないようにします。

  • ハードウェアカウンタデータの完全性の確保。 コレクタは、ハードウェアカウンタライブラリ libcpc.so からの関数に割り込み、プログラムがカウンタを使用しないようにします。プログラムからこのライブラリの関数への呼び出しは、値 -1 を返します。

  • 派生プロセスに対するデータ収集の有効化。コレクタは、fork(2)、 fork1(2)、 vfork(2)、 fork(3F)、 posix_spawn(3p)、 posix_spawnp(3p)、 system(3C)、 system(3F)、 sh(3F)、 popen(3C)、 exec(2) の関数とそのバリアントに割り込みます。vfork の呼び出しは、内部で fork1 の呼び出しに置き換えられます。これらの割り込み処理が行われるのは、collect コマンドの場合です。

  • コレクタによる SIGPROF シグナルおよび SIGEMT シグナルの処理の保証。コレクタは sigaction に割り込み、シグナルハンドラがこれらのシグナル用のプライマリシグナルハンドラであるかどうかを確認します。

    次の状況では割り込み処理は成功しません。

  • 割り込み対象関数が入っているライブラリとプログラムを静的にリンクした場合。

  • コレクタライブラリが事前読み込みされていない実行中アプリケーションに dbx を接続した場合。

  • これらのライブラリのいずれか 1 つを動的に読み込み、このライブラリの中でだけ検索することによってシンボルを解決する場合。

コレクタが割り込み処理を行えなかった場合には、パフォーマンスデータが消去されたり無効になったりする可能性があります。

er_sync.soer_iotrace.soer_heap.so、および er_mpviewn.so (n は MPI バージョンを示す) ライブラリは、それぞれ同期待ちトレースデータ、I/O トレースデータ、ヒープトレースデータ、または MPI トレースデータが要求された場合にのみロードされます。

データ収集とシグナル

シグナルは、クロックプロファイリングとハードウェアカウンタプロファイリングの両方に使用されます。SIGPROF は、すべての実験のデータ収集で使用されます。シグナルを生成する期間は、収集されるデータによって異なります。Solaris での SIGEMT または Linux での SIGIO はハードウェアカウンタプロファイリングに使用されます。オーバーフローの間隔は、プロファイリングのユーザーパラメータによって異なります。プロファイリングシグナルを使用または操作する何らかのユーザーコードが、データ収集の妨げになる可能性があります。コレクタは、そのシグナルハンドラをプロファイルシグナル用にインストールする場合、シグナルを配信するシステムコールの処理が中断されないようにするためのフラグを設定します。この設定により、プロファイリングシグナルをほかの目的に使用しているターゲットプログラムの動作が変更される可能性があります。

コレクタは、そのシグナルハンドラをプロファイルシグナル用にインストールするときに、ターゲットが独自のシグナルハンドラをインストールしたかどうかを記憶しています。コレクタはまた、一部のシグナル処理ルーチンに割り込み、ユーザーがこれらのシグナル用にシグナルハンドラをインストールできないようにします。コレクタは、実験の開始時にユーザーハンドラを置き換える場合と同様に、そのユーザーのハンドラを保存します。

プロファイリングシグナルは、カーネル内のプロファイリングタイマーまたはハードウェアカウンタオーバーフロー処理コードから、または kill(2)、sigsend(2)、tkill(2)、tgkill(2)、または _lwp_kill(2) のシステムコール、raise(3C) および sigqueue(3C) のライブラリコール、あるいは kill コマンドへの応答として送信されます。コレクタが起点を区別できるように、シグナルコードがシグナルとともに配信されます。シグナルコードは、プロファイリングのために配信される場合はコレクタによって処理されます。プロファイリングのために配信されない場合は、ターゲットのシグナルハンドラに配信されます。

コレクタが dbx の下で実行されているときに、配信されたプロファイリングシグナルのシグナルコードが破壊されたり、プロファイルシグナルがシステムまたはライブラリコールあるいはコマンドから生成されたかのように扱われたりする場合があります。その場合は、ユーザーのハンドラに誤って配信されます。ユーザーハンドラが SIG_DFL に設定されていた場合は、プロセスが失敗してコアダンプが生成されます。

コレクタがターゲットプロセスへの接続のあとに呼び出された場合、コレクタはそのシグナルハンドラをインストールしますが、シグナル処理ルーチンに割り込むことはできません。これらのユーザーコードが接続のあとにシグナルハンドラをインストールした場合は、コレクタのシグナルハンドラがオーバーライドされ、データは失われます。

どちらかのプロファイリングシグナルを含むシグナルによって、システムコールが途中で終了することがあります。この動作を処理するようにプログラムを準備する必要があります。libcollector は、データ収集のシグナルハンドラをインストールするときに、可能であればシステムコールを再開するように指定します。ただし、sleep(3C) などの一部のシステムコールはエラーを報告することなく早期に復帰します。

標本シグナルと一時停止/再開シグナル

シグナルは、ユーザーが標本シグナル (-l) または一時停止/再開シグナル (-y) として指定できます。この使用には SIGUSR1 または SIGUSR2 が推奨されますが、ターゲットによって使用されない任意のシグナルを使用できます。

プロファイリングシグナルは、プロセスがそれ以外ではそのシグナルを使用しない場合に使用できますが、ほかのシグナルが使用できない場合にのみ使用するようにしてください。コレクタは、一部のシグナル処理ルーチンに割り込み、ユーザーがこれらのシグナル用にシグナルハンドラをインストールできないようにします。コレクタは、実験の開始時にユーザーハンドラを置き換える場合と同様に、そのユーザーのハンドラを保存します。

コレクタがターゲットプロセスへの接続のあとに呼び出され、ユーザーコードが標本または一時停止/再開シグナル用にシグナルハンドラをインストールした場合、それらのシグナルは指定されたとおりに動作しなくなります。

setuidsetgid の使用

動的ローダーによって課される制約により、setuid(2) を使用してパフォーマンスデータを収集することが困難になります。 プログラムが setuid を呼び出すか、setuid ファイルを実行する場合、コレクタは新しいユーザー ID に必要なアクセス権がないために、実験ファイルに書き込めない可能性があります。

collect コマンドは、ターゲットのアドレス空間 (LD_PRELOAD) に共有ライブラリ libcollector.so を挿入して動作します。実行可能ファイルが setuid または setgid を呼び出す、または setuid または setgid を呼び出す派生プロセスを作成する場合、その実行可能ファイルから collect コマンドを起動すると、いくつかの問題が発生する可能性があります。root ではないユーザーとして実験を実行すると、共有ライブラリが信頼できるディレクトリにインストールされていないために収集が失敗します。対策としては、root ユーザーとして実験を実行するか、crle(1) を使用してアクセス権を与えます。セキュリティバリアーを迂回するときには十分な注意を払い、各自のリスクで行ってください。

collect コマンドを実行するとき、umask は、自分、exec() によって実行されるプログラムの setuid 属性および setgid 属性によって設定されているユーザーまたはグループ、およびプログラム自体によって設定されるユーザーまたはグループに対して、書き込みアクセスを許可するように設定されている必要があります。マスクが正しく設定されていない場合、一部のファイルが実験に対して書き込まれず、実験が処理不能になることがあります。ログファイルが書き込み可能な場合、実験の処理を試みたときにエラーが示されます。

ターゲット自身が UID または GID を設定する何らかのシステムコールを発行した場合、自分の umask を変更してから fork を行うか、ほかの実行可能ファイルを exec() で実行した場合、または crle を使用してランタイムリンカーが共有オブジェクトを検索する方法が構成された場合には、ほかの問題が発生する可能性があります。

実効 GID を変更するターゲット上で実験が root として開始された場合、実験の終了時に自動的に実行される er_archive プロセスが失敗します。これは、このプロセスには「信頼できる」にマークされていない共有ライブラリが必要なためです。この場合、実験の終了直後に、実験が記録されたマシン上で、er_archive ユーティリティー (または er_print ユーティリティーか analyzer コマンド) を実行できます。

libcollector ライブラリを使用したデータ収集のプログラム制御

プログラムからデータ収集を制御するために、コレクタ共有ライブラリ libcollector.so に含まれているいくつかの API 関数を使用できます。これらの関数は C で記述されています。また、Fortran インタフェースも提供されています。ライブラリとともに提供されるヘッダーファイルに、C インタフェースと Fortran インタフェースの両方が定義されています。

API 関数は、次のように定義されます。

void collector_sample(char *name);
void collector_pause(void);
void collector_resume(void);
void collector_terminate_expt(void);

CollectorAPI クラスに、Java プログラム用の類似の機能が用意されており、これについては、Java インタフェースで説明しています。

C および C++ インタフェース

collectorAPI.h を取り込み、配下の libcollector.so API 関数の存在をチェックする実際の関数を含む、-lcollectorAPI にリンクすることにより、コレクタ API の C/C++ インタフェースにアクセスできます。

有効な実験がない場合、API 呼び出しは無視されます。

Fortran インタフェース

Fortran API の libfcollector.h ファイルは、ライブラリへの Fortran インタフェースを定義します。このライブラリを使用するには、アプリケーションを -lcollectorAPI にリンクする必要があります。このライブラリには、下位互換性を維持するため、-lfcollector というもう 1 つの名前も用意されています。動的関数とスレッドによる呼び出しの一時停止と再開を除けば、Fortran API は C/C++ API と同じ機能を提供します。

Fortran の場合、API 関数を使用するには、次の文を挿入します。

include "libfcollector.h"

注 -  どんな言語を使用している場合も、プログラムを -lcollector とリンクしないでください。リンクした場合、コレクタが予期しない動作をすることがあります。

Java インタフェース

次の文を使用して、CollectorAPI クラスをインポートし、Java API にアクセスします。ただし、アプリケーションは、クラスパスが /installation_directory/lib/collector.jar (installation_directory は Oracle Developer Studio ソフトウェアがインストールされているディレクトリです) を指している状態で起動される必要があります。

import com.sun.forte.st.collector.CollectorAPI;

Java CollectorAPI メソッドは、次のように定義されます。

CollectorAPI.sample(String name)
CollectorAPI.pause()
CollectorAPI.resume()
CollectorAPI.terminate()

Java API には、動的関数 API 以外の C および C++ API と同じ関数が含まれています。

C インクルードファイルの libcollector.h には、データが収集されていないときには実際の API 関数への呼び出しを迂回するマクロが含まれています。この場合、関数は動的にロードされません。ただし、一部の条件では適切に機能しないことがあるため、これらのマクロを使用するのは危険です。 マクロを使用しないので、collectorAPI.h を使用すると安全性が高まります。このファイルでは、関数が直接参照されます。

Fortran API サブルーチンはパフォーマンスデータが収集されているときには C API 関数を呼び出し、そうでないときには復帰します。チェック処理のオーバーヘッドは非常に小さいので、プログラムのパフォーマンスにはあまり影響がないはずです。

パフォーマンスデータを収集するには、この章で後述するように、コレクタを使用してプログラムを実行する必要があります。API 関数への呼び出しを挿入することによって、データ収集が有効になることはありません。

マルチスレッドプログラムで API 関数を使用する場合は、これらの関数が 1 つのスレッドによってのみ呼び出されるようにしてください。API 関数は、個別のスレッドではなくプロセスに適用される動作を実行します。各スレッドが API 関数を呼び出すと、記録されたデータが期待したものにならない可能性があります。たとえば、あるスレッドが collector_pause()collector_terminate_expt() を呼び出したときに、ほかのスレッドがまだプログラム内のそのポイントに達していない場合、すべてのスレッドについて収集が一時停止または停止され、この API 呼び出しの前にコードを実行していたスレッドのデータが失われる可能性があります。

C/C++、Fortran、および Java API 関数

このセクションでは、API 関数について説明します。

  • C および C++: collector_sample(char *name)

    Fortran: collector_sample(string name)

    Java: CollectorAPI.sample(String name)

    標本パケットを記録し、その標本に指定された名前または文字列をラベルとして付けます。このラベルは、パフォーマンスアナライザの「タイムライン」ビューで標本を選択したときに「選択の詳細」ウィンドウに表示されます。Fortran の引数 string の型は、character です。

    標本ポイントに含まれるデータは、プロセスに関するものであり、個々のスレッドに関するものではありません。マルチスレッドアプリケーションの場合、collector_sample() API 関数は、標本の記録中に別の呼び出しが行われても、1 つの標本だけが書き込まれるようにします。記録される標本の数は、呼び出しを行うスレッドの数よりも少なくなります。

    パフォーマンスアナライザは、別々のメカニズムによって記録された標本同士を区別しません。API 呼び出しによって記録された標本だけを見たい場合には、パフォーマンスデータの記録時にほかのあらゆる標本モードを停止します。

  • C、C++、Fortran: collector_pause()

    Java: CollectorAPI.pause()

    実験へのイベント固有データの書き込みを停止します。実験はオープン状態のままであり、大域データの書き込みは続けられます。有効な実験がない場合やデータの記録がすでに停止されている場合には、呼び出しは無視されます。この関数は、たとえすべてのイベント固有データの書き込みが collector_thread_resume() 関数によって特定のスレッドに対して有効にされていたとしても、その書き込みを停止します。

  • C、C++、Fortran: collector_resume()

    Java: CollectorAPI.resume()

    collector_pause() を呼び出したあとに、実験へのイベント固有データの書き込みを再開します。有効な実験がない場合やデータの記録が有効である場合には、呼び出しは無視されます。

  • C、C++、Fortran: collector_terminate_expt()

    Java: CollectorAPI.terminate

    データの収集対象である実験を終了します。それ以後のデータは収集されませんが、プログラムの実行は正常に続行されます。有効な実験がない場合は、呼び出しは無視されます。

動的な関数とモジュール

使用している C または C++ プログラムが、関数を動的にコンパイルしてデータ空間に取り込む場合、動的関数やモジュールのデータをパフォーマンスアナライザに表示するには、コレクタに情報を与える必要があります。この情報は、コレクタ API 関数の呼び出しによって渡されます。API 関数の定義は、次のとおりです。

void collector_func_load(char *name, char *alias,
    char *sourcename, void *vaddr, int size, int lntsize,
    Lineno *lntable);
void collector_func_unload(void *vaddr);

Java HotSpot 仮想マシンによってコンパイルされる Java メソッドには別のインタフェースが使用されるので、これらの API 関数を使用する必要はありません。Java インタフェースは、コンパイルされたメソッドの名前をコレクタに知らせます。 Java コンパイル済みメソッドの関数データと注釈付き逆アセンブリのリストを見ることはできますが、注釈付きソースリストを見ることはできません。

このセクションでは、API 関数について説明します。

collector_func_load() 関数

実験への記録のため、動的にコンパイルされた関数に関する情報をコレクタに渡します。パラメータリストを次の表に示します。

表 6  collector_func_load() のパラメータリスト
パラメータ
定義
name
パフォーマンスツールで使用する、動的にコンパイルされた関数の名前。実際の関数名でなくてもかまいません。この名前は関数の通常の命名規則に従っている必要はありませんが、空白文字や引用符は含めないようにします。
alias
関数の説明に使用する任意の文字列。NULL も使用できます。この文字列が解釈の対象となることはありません。空白文字を含めることができます。アナライザの「サマリー」タブに表示されます。何の関数であるか、またはなぜ関数が動的に構築されたかを示すために使用できます。
sourcename
関数の構築元であるソースファイルのパス。NULL も使用できます。このソースファイルは、注釈付きソースリストに使用されます。
vaddr
関数が読み込まれたアドレス。
size
バイト数による関数のサイズ。
lntsize
行番号テーブルのエントリの数を示すカウント。行番号情報がない場合には、ゼロとなります。
lntable
lntsize エントリが入っているテーブル。各エントリは、整数対です。第 1 整数はオフセット、第 2 整数は行番号です。あるエントリのオフセットと次のエントリのオフセットとの間の命令はすべて、最初のエントリの行番号に対応します。オフセットは数値の昇順にする必要がありますが、行番号の順序は任意です。lntableNULL の場合、関数のソースリストは利用できませんが、逆アセンブリリストは利用できます。

collector_func_unload() 関数

アドレス vaddr にある動的関数がアンロードされたことをコレクタに通知します。