ロードされたすべての共有ライブラリを反復処理して、それらのベースアドレスとファイル名を取得したいと思います。これは基本的dl_iterate_phdr
にLinux上にあります。
しかし、私はMacでも同じことをしたいと思っています。
ロードされたすべての共有ライブラリを反復処理して、それらのベースアドレスとファイル名を取得したいと思います。これは基本的dl_iterate_phdr
にLinux上にあります。
しかし、私はMacでも同じことをしたいと思っています。
dyld(3)のマニュアルページ(オンラインではなくなったようです)に記載されている関数は、類似の機能を提供しているようです。
その内容は次のとおりです。
名前
_dyld_image_count, _dyld_get_image_header, _dyld_get_image_vmaddr_slide, _dyld_get_image_name, _dyld_register_func_for_add_image, _dyld_register_func_for_remove_image, NSVersionOfRunTimeLibrary, NSVersionOfLinkTimeLibrary _NSGetExecutablePath
概要
#include <mach-o/dyld.h> uint32_t _dyld_image_count(void); const struct mach_header* _dyld_get_image_header(uint32_t image_index); intptr_t _dyld_get_image_vmaddr_slide(uint32_t image_index); const char* _dyld_get_image_name(uint32_t image_index); void _dyld_register_func_for_add_image(void (*func)(const struct mach_header* mh, intptr_t vmaddr_slide)); void _dyld_register_func_for_remove_image(void (*func)(const struct mach_header* mh, intptr_t vmaddr_slide)); int32_t NSVersionOfRunTimeLibrary(const char* libraryName); int32_t NSVersionOfLinkTimeLibrary(const char* libraryName); int _NSGetExecutablePath(char* buf, uint32_t* bufsize);
説明
dlopen()
これらのルーチンは、およびによって提供されるものを超えて、dyldの追加の内省を提供します。dladdr()
_dyld_image_count()
dyldによってマップされた画像の現在の数を返します。このカウントを使用してすべての画像を反復することはスレッドセーフではないことに注意してください。反復中に別のスレッドが画像を追加または削除している可能性があるためです。
_dyld_get_image_header()
image_indexでインデックス付けされた画像のマッハヘッダーへのポインタを返します。が範囲外の場合image_index
、NULLが返されます。
_dyld_get_image_vmaddr_slide()
でインデックス付けされた画像の仮想メモリアドレススライド量を返しますimage_index
。が範囲外の場合image_index
、ゼロが返されます。
_dyld_get_image_name()
でインデックス付けされた画像の名前を返しますimage_index
。C文字列は引き続きdyldによって所有されているため、削除しないでください。が範囲外の場合image_index
、NULLが返されます。
_dyld_register_func_for_add_image()
プログラムに新しいイメージ(バンドルまたは動的共有ライブラリ)が追加されたときに呼び出される指定された関数を登録します。この関数が最初に登録されると、現在プロセスの一部である画像ごとに1回呼び出されます。
_dyld_register_func_for_remove_image()
画像がプロセスから削除されたときに呼び出される指定された関数(バンドルまたは動的共有ライブラリ)を登録します。
NSVersionOfRunTimeLibrary()
libraryNameで指定された現在ロードされているdylibのcurrent_version番号を返します。libraryNameパラメーターは、/ path / libbar.3.dylibの場合は「bar」、/ path / Foo.framework / Versions / A/Fooの場合は「Foo」になります。このようなライブラリがロードされていない場合、この関数は-1を返します。
NSVersionOfLinkTimeLibrary()
ビルド時にメインの実行可能ファイルがリンクされたcurrent_version番号を返します。libraryNameパラメーターは、/ path / libbar.3.dylibの場合は「bar」、/ path / Foo.framework / Versions / A/Fooの場合は「Foo」になります。メインの実行可能ファイルが指定されたライブラリに対してリンクしなかった場合、この関数は-1を返します。
_NSGetExecutablePath()
メインの実行可能ファイルのパスをバッファにコピーしますbuf
。bufsize
パラメータは、最初はバッファのサイズである必要があります。パスが正常にコピーされた場合、この関数は0を返し、*bufsize
は変更されません。バッファが十分に大きくない場合は-1を返し、*bufsize
は必要なサイズに設定されます。_NSGetExecutablePath()
実行可能ファイルへの「実際のパス」ではなく、実行可能ファイルへの「パス」を返すことに注意してください 。つまり、パスは実際のファイルではなくシンボリックリンクである可能性があります。深いディレクトリでは、必要な合計bufsizeは。より大きくなる可能性がありますMAXPATHLEN
。
完了のためだけに:
入力は静的コンテンツ(関数など)へのポインターであり、目標はライブラリとそのセクションを見つけることでした。
私はこれを関数に実装しましたptr_is_in_exe
:
static bool
ptr_is_in_exe(const void *ptr, const struct mach_header *& header, intptr_t& offset, uintptr_t& vmaddr, std::string& image_name)
{
uint32_t i, count = _dyld_image_count();
for (i = 0; i < count; i++) {
header = _dyld_get_image_header(i);
offset = _dyld_get_image_vmaddr_slide(i);
uint32_t j = 0;
struct load_command* cmd = (struct load_command*)((char *)header + sizeof(struct mach_header));
if(header->magic == MH_MAGIC_64)
cmd = (struct load_command*)((char *)header + sizeof(struct mach_header_64));
while (j < header->ncmds) {
if (cmd->cmd == LC_SEGMENT) {
struct segment_command* seg = (struct segment_command*)cmd;
if (((intptr_t)ptr >= (seg->vmaddr + offset)) && ((intptr_t)ptr < (seg->vmaddr + offset + seg->vmsize))) {
vmaddr = seg->vmaddr;
image_name = _dyld_get_image_name(i);
return true;
}
}
if (cmd->cmd == LC_SEGMENT_64) {
struct segment_command_64* seg = (struct segment_command_64*)cmd;
if (((uintptr_t)ptr >= (seg->vmaddr + offset)) && ((uintptr_t)ptr < (seg->vmaddr + offset + seg->vmsize))) {
vmaddr = seg->vmaddr;
image_name = _dyld_get_image_name(i);
return true;
}
}
j++;
cmd = (struct load_command*)((char*)cmd + cmd->cmdsize);
}
}
return false;
}