兼雑記

なにやら先生と紛らわしいそうで生まれてきてすいません。あばうと
<< 2005/11 >>
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30

| サイト本体 | 昔の更新履歴兼雑記 | タイトル一覧 |

分類は アーカイブ任せにした方がいいのかも。


 | 

2005-11-03

[][] 実行時に情報を調べる話のまとめ 02:21

このへんの話もーちょい調べたら今度まとめてみたいなとか思うけど何がわかってないのか混乱してきたから、現状のまとめ。

共有ライブラリの名前とロードされたアドレスを取得する (実行時 ldd 相当)

ldd と違ってどのアドレスにロードされているかの情報も欲しい。 Linux だと /proc/self/maps に書いてある情報。

  • Linux では dl_iterate_phdr でにコールバック関数を渡してやる。
  • FreeBSD では dlinfo(RTLD_SELF, RTLD_DI_LINKMAP, &lmap) などとして link_map という構造体をゲットすればいい。
  • MacOSX では dyld(3) 。 _dyld_image_count と _dyld_get_image_name と _dyld_get_image_vmaddr_slide を使えばいい。
  • Win32 では今のところどうすればいいやら。
  • NetBSD では見当らない。 dlctl(3) というのが今作ってるところだ、って man に書いてあって、ヘッダを見ると DL_GETLIST なんてのがあるので、これでできるかもしれない。

ところで dlinfo が man に無いのはヒドい話だと思う。

自分のプロセスの名前を取得する

これ、案外できない。 argv[0] ですむ場合が多いんだけど。

  • Linux では /proc/self/exe くらいかな。
  • FreeBSD では dlinfo(RTLD_SELF, RTLD_DI_LINKMAP, &lmap) で自分自身も入ってくる。
  • MacOSX は _dyld_* で自分自身も入ってくる。
  • Win32 では GetModuleHandle(NULL) の返り値に対して GetModuleFileName 。
  • NetBSD は不明。 dlctl が動けばこれは FreeBSD 同様に引っこ抜けると思われる。

共有ライブラリオープンする

基本は dlopen 。まぁよくやられてるのでサンプル豊富。

  • Linux, FreeBSD, NetBSD では dlopen 。
  • MacOSX では dlopen か NSAddImage(name, NSADDIMAGE_OPTION_WITH_SEARCHING) かな。
  • Win32 では LoadLibrary(name)

ていうかまぁ、 dlsym もサンプル豊富なので省略。

起動後に共有ライブラリの名前とアドレスを取得する

最初のができるなら問題無いけど、 dlopen の返り値使えばもっと速かったりとか。

  • LinuxFreeBSD は dlopen の返り値を dh として、 dlinfo(dh, RTLD_DI_LINKMAP, &lmap) 。
  • MacOSX では、うーんよくわからない。 _dyld_* は起動時の状態しか取れないように見える。
  • Win32 では LoadLibrary の返り値を dh として、 GetModuleFileName(dh, buf, 1024) とか。ただロードアドレスが取れない。
  • NetBSD ではたぶんできない。同じく dlctl が実装されれば、って話。

ちなみに、 dlfcn 環境では、関数名を一つでもヒントとして渡せば、 dlsym の返り値を dladdr に渡してやれば問題なくわかる。

ファイル名からシンボル一覧を取得する (nm相当)

ぶっちゃけ nm しておいてパーズでもいい、が…

libbfd を使うのが基本。基本的には、 bfd_read_minisymbols を使ってそれで得られたものを bfd_minisymbol_to_symbol で変換するのがいいと思う。 bfd_read_minisymbols の第二引数は 0, 1 で指定するダイナミックシンボルを見るか否か。基本的には片方がゼロ個ならもう一方を読めばまず取得できると思う。ところで strip した共有ライブラリから nm -D でシンボル取得できるって知らんかったです…

また、 bfd_get_symtab_upper_bound, bfd_canonicalize_symtab, bfd_get_dynamic_symtab_upper_bound, bfd_canonicalize_dynamic_symtab を使う手もある。速度差はほとんどないように見える、うちのマシン (Celeron 1.7GHz, linux-2.6.11-mm4, glibc-2.3.5) ではシンボルが 8514個ある libkdecore.so を 100 回読んでどっちも 0.6秒くらいで、 0.02秒とかそのくらい minisymbol のやり方の方が速かった。 Win32 でのみ後者が速かった。んで前者の方が省メモリ

  • Linux, FreeBSD, NetBSD, MacOSX, Win32 ともに基本的に前者のやり方でいい。
  • MacOSX で後者をやると mach-o.c の中で謎の assertion failure が出る。たぶん libbfd のバグを踏んでいる。また、 dynamic 系は常に失敗する。 OSX 標準添付の nm に -D が無いあたりとも関係ありそう。詳しくはTODO。
  • Win32 で dynamic 系をやると返って来なくなる。(但しWINE)

まとめると、 minisymbol 系を使った方がたぶん無難。 Linux, FreeBSD では dynamicバージョンと通常バージョン両方やってみると良い。 MacOSX と Win32 では通常バージョンのみが良いと思う。

関数ポインタから任意関数を呼び出す

関数の型がコンパイル時に決まるなら ( (int (*) (const char* s))0x80482cc)("hello"); とかでいい。(ちなみに puts がここにロードされてた)

たぶん libffi でイケるけど Linux 以外では未確認。

読むべきヘッダ

k.inabak.inaba 2005/11/03 10:03 Win32でロードアドレス、CreateToolhelp32Snapshot→Module32First/Next でどうでしょう。外してたらすみません。

shinichiro_hshinichiro_h 2005/11/03 10:54 おお。まさにこれですね。 Win32 に無いはず無いと思いつつも探し切れませんでした。情報どうもありがとうございます。

通りすがり通りすがり 2005/11/06 20:38 libbdf は便利なんだけど GPL なので、ぶっちゃけ使いにくいんですよね…
GNU の作ったものの中では一番ソースが汚い物の一つなので、誰か使いやすいライセンスでさっくりと書き直してくれると良いのだけれども…

shinichiro_hshinichiro_h 2005/11/06 20:42 あー、私はまぁなんでもGPLでいいじゃん的ですけど、ネックになる人にはなるんでしょうね…ただ、さっくり書き直せる規模でもない気も。

espresso3389espresso3389 2005/11/16 01:13 通りすがりの者ですが、Win32でのロードアドレスは、単純に、LoadLibraryの返値をそのまま(DWORD_PTR)などにキャストした値を真に受けて良いはずです。この動作は、ちゃんとドキュメント化されているはずです。

shinichiro_hshinichiro_h 2005/11/16 06:37 なるほど情報ありがとうございます。ですが、どの dll がロードされているかわからない場合(例えば起動時にロードされた dll や他の dll から連鎖的にロードされた dll)などには、 Toolhelp などが欲しいところですね…

 | 
1970 | 01 |
2003 | 12 |
2004 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2005 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2006 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2007 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2008 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2009 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2010 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 10 | 12 |
2011 | 01 | 02 | 03 | 04 | 06 | 08 | 09 | 10 | 11 | 12 |
2012 | 01 |
(1709184 since 04.04.21)
なにかあれば下記メールアドレスへ。
shinichiro.hamaji _at_ gmail.com
shinichiro.h