名称
_UNW_createContextForSelf(), _UNW_createContext(), _UNW_destroyContext() ― アンワインドライブラリデータ構造の割り当てと割り当て解除
構文
#include <unwind.h>
_Unwind_Context * _UNW_createContextForSelf(void);
_Unwind_Context * _UNW_createContext(
_UNW_ReadTargetMem read_tgt_mem,
_UNW_LoadMapFromIP load_map_from_ip,
uint32_t ident);
void _UNW_destroyContext(_Unwind_Context* p);
説明
_UNW_createContextForSelf と _UNW_createContext は、いずれも _Unwind_Context と呼ばれるデータ構造体を初期化します。 _Unwind_Context は、 libunwind.so で提供されるスタックアンワインドライブラリにより管理されます。 _UNW_createContextForSelf は通常、プロセスが自身のスタックをアンワインドするときに使用します。 _UNW_createContext は通常、プロセスが、自身以外のプロセスのスタックをアンワインドするとき、またはコアファイルに保存されている「終了済み」プロセスのスタックをアンワインドするときに使用します。
_UNW_createContext を使用して、プロセス
(ターゲットプロセスと呼びます) をアンワインドするとき、クライアントプロセスは、3 つのパラメータを提示する必要があります。
| 1. | | パラメータ read_tgt_mem は、アンワインドライブラリが、ターゲットプロセスのメモリーから値を読み出すために呼び出す関数です。
読み出す値には、アンワインドヘッダー、アンワインドテーブル、アンワインド情報ブロック、プロシージャコールスタック、RSE
(Register Stack Engine) のバッキングストアがあります。 この関数は
64 ビットアドレス空間のどこからでも読める必要があります (32 ビットアプリケーションの場合も)。
これは、Itanium ベース システムのカーネル割り込みのアンワインドヘッダーをカーネルゲートウェイ
メモリーページから読み出すからです。 read_tgt_mem は、 _UNW_ReadTargetMem 型として定義され、この型は、 unwind.h で以下のように定義されています。 typedef void * (* _UNW_ReadTargetMem) (void *dst, uint64_t src, size_t length, uint32_t ident); パラメータの意味は memcpy(3C) のものとほとんど同じです。
パラメータ dst は、パラメータ src で示す位置から、パラメータ length で示すバイト長だけコピーする際のコピー先アドレスです。 src は、カーネルゲートウェイ ページを読み出すのに必要な
64 ビットアドレスを表せるように、型が uint64_t になっていることに注意してください。
64 ビットアプリケーションによりアンワインドする場合は、アンワインドの際に使用する src と dst のすべてのアドレスは 64 ビットポインターです。 32
ビットアプリケーションによりアンワインドする場合は、アンワインドの際に使用する多くのアドレスは
32 ビットポインターです。 ただし、ターゲットメモリーリーダーを呼び出す前に、アンワインドライブラリがこれらのアドレスを、完全な 64
ビットアドレスに 拡張 (swizzle) します。
メモリーモデルと拡張 (swizzle) という用語の詳細は 『『Itanium
Processor Family Runtime Architecture Supplement』: 『32-Bit
Runtime Architecture for HP-UX』』の 『Section
1: Memory Model』 に説明されています。 64 ビットポインターを必要とするアドレス範囲 (したがって、32 ビットアドレス空間ではアクセスできない)
は、カーネルのシグナルハンドラー ラッパー関数 __user_sendsig 用のアンワインドヘッダーとアンワインド情報に関連するアドレスのみです。
クライアントのメモリーリードコールバック関数は、このアドレス範囲を検出し、このアドレス範囲からの読み込みができる必要があります。
この範囲は、プログラムスタートアップ時にマイクロローダーとダイナミックローダーにより、 /usr/include/crt0.h で定義された構造体 load_info_t 内に
(または、完全にバインドされた実行可能ファイルの場合は crt0.o 内に)
定義されます。 『『Itanium Processor Family Runtime Architecture
Supplement: Signal Handling on HP-UX』』 および 『『Itanium
Processor Family Runtime Architecture Supplement: Program Startup
on HP-UX』』 を参照してください。 read_tgt_mem の第 4 パラメータ ident は、アンワインドライブラリ自身には透過的であり、アンワインドを実行するクライアントプログラムで使用するように用意されています。
クライアントプログラムは、 (_UNW_createContext の呼び出しにより) ident 用の値をアンワインドライブラリに渡し、アンワインドライブラリは、この値を read_tgt_mem コールバックに渡します。 たとえば、デバッガは、ターゲットプロセス内の個々のスレッドを識別するために ident を使用することができます。 |
| 2. | | パラメータ load_map_from_ip は、アンワインドライブラリがターゲットプロセスメモリー中の特定の
IP アドレスに対する load_module_desc を取得する必要があるとき、 dlmodinfo の呼び出しの代わりに呼び出す関数です dlmodinfo(3C) を参照)。 呼び出されると、 load_map_from_ip は、構造 load_module_desc のフィールド linkage_ptr、 unwind_base、 text_base に、 (__user_sendsig に関連するインストラクションアドレスを含む) 有効なユーザープロセスインストラクションアドレスに対する正確な値を設定する必要があります。 unwind_base (アンワインドヘッダーのロケーション)
および text_base (ELF の .text セグメントがロードされるロケーション)
は、いずれも (拡張されていない 32 ビットのポインターではなく) 完全な
64 ビットアドレスである必要があります。 linkage_ptr は、プロシージャの GP レジスタの (完全な 64 ビットの) 値です。 『『Itanium
Processor Family Software Conventions and Runtime Architecture』』 の
Chapter 8, 『Procedure Linkage』 を参照してください。 __user_sendsig 用のアンワインド情報は、上記の read_tgt_mem の説明で述べたように、カーネルゲートウェイ ページでやりとりします。 load_map_from_ip の型 _UNW_LoadMapFromIP は、 unwind.h で以下のように定義されています。 typedef void (* _UNW_LoadMapFromIP) ( struct load_module_desc * new_load_map, uint64_t ip, uint32_t ident); パラメータ new_load_map は、事前に割り当てられた構造体 load_module_desc へのポインターで、 load_map_from_ip により設定されます。 パラメータ ip は、情報を要求しているロードモジュールに対応する命令ポインターです。 パラメータ ident は、アンワインドライブラリ自身には透過的であり、アンワインドを実行するクライアントプログラムで使用するように用意されています。
クライアントプログラムは、 (_UNW_createContext の呼び出しにより) ident 用の値をアンワインドライブラリに渡し、アンワインドライブラリは、この値を load_map_from_ip コールバックに渡します。 たとえば、デバッガは、ターゲットプロセス内の個々のスレッドを識別するために ident を使用することができます。 |
| 3. | | _UNW_createContext の第 3 パラメータ ident は、アンワインドを実行するクライアントプログラムで使用するように用意されています。
このパラメータの用法は、上記の read_tgt_mem および load_map_from_ip の項で説明しています。 |
_UNW_createContext は、自身以外のプロセスをアンワインドするときの要件を満足するように設計されていますが、 _UNW_createContext で作成された _Unwind_Context は、プロセスが自身をアンワインドするためにも使用できます。
そのような操作が必要になる理由としては、ダイナミックに生成されたコードや実行時の計測機能付コードのアンワインドなどがあります。
このような状況では、クライアントは _UNW_LoadMapFromIP および _UNW_ReadTargetMem コールバックの登録が必要になる場合があります。
_UNW_destroyContext は、 _UNW_createContextForSelf や _UNW_createContext によって割り当てられたメモリーを解放します。
メモリーリークを避けるためには、 _Unwind_Context オブジェクトを割り当てるアプリケーションは _Unwind_Context が不要になった時点で _UNW_destroyContext を呼び出す必要があります。
アプリケーション使用法
_UNW_createContextForSelf、 _UNW_createContext、 _UNW_destroyContext はスレッドセーフです。
戻り値
構造体 _Unwind_Context へのポインター
エラー
_UNW_createContextForSelf および _UNW_createContext は、次の状況で、アンワインドコンテキストデータ構造体の作成に失敗することがあります。
メモリー不足。メモリー不足の状況でも、アンワインドライブラリの以下の動作は保証されます。
_Unwind_Context の作成に失敗しても、クライアントプログラムが、スタックアンワインドライブラリの _UNW_getAlertCode() のエントリーポイントを呼び出せるだけの _Unwind_Context オブジェクトは作成されます。 このエントリーポイントは、 _Unwind_Context の生成に失敗していたり、 _Unwind_Context ポインターがヌル
(これも生成の失敗を意味します) であったりした場合には、 _UNW_MEMORY_ALLOCATION_ERROR を返します。
生成が成功していた場合は、 _UNW_getAlertCode() は _UNW_OK を返します。
極端なメモリー不足の状況で生成に失敗した場合は、 NULL を返すことで通知します。
実際には、 _Unwind_Context へのポインターに NULL をセットします。 _Unwind_Context のポインターが NULL だと、その後、戻り値の型が _UNW_ReturnCode のインタフェース関数を呼び出したときに、 _UNW_MEMORY_ALLOCATION_ERROR が返されます。
例
例 1
実行中のプロセスをアンワインドするために、 _Unwind_Context を割り当てて初期化します。
#include <unwind.h>
#include <stdio.h>
_Unwind_Context *uc;
_UNW_ReturnCode retcode;
uc = _UNW_createContextForSelf();
if (uc == NULL) {
/* Code to notify user of low memory problem */
}
if (_UNW_getAlertCode(uc) == _UNW_MEMORY_ALLOCATION_ERROR) {
/* Code to notify user of low memory problem */
}
/* Example use of the _Unwind_Context * follows: */
if ((retcode = _UNW_currentContext(uc)) != _UNW_OK) {
/* Notify user: Couldn't determine current context. */
}
例 2
実行中のプロセス以外のプロセスをアンワインドするために、 _Unwind_Context を割り当てて初期化します。
#include <unwind.h>
#include <stdio.h>
_Unwind_Context *uc;
_UNW_ReturnCode retcode;
extern _UNW_ReadTargetMem my_mem_reader;
extern _UNW_LoadMapFromIP my_dlmodule_info;
uint64_t target_ip; /* Target process instruction pointer */
uc = _UNW_createContext(my_mem_reader, my_dlmodule_info,1);
if (_UNW_getAlertCode(uc) == _UNW_MEMORY_ALLOCATION_ERROR) {
/* Code to notify user of low memory problem */
}
/* Example use of the _Unwind_Context * follows: */
if ((retcode = _UNW_setIP(uc,target_ip)) != _UNW_OK) {
/* Notify user: Initialization problem */
}
著者
_UNW_createContextForSelf、 _UNW_createContext、 _UNW_destroyContext は HP
で開発されました。