2

現在、特に Solaris 9 で、pmap コマンドをミラーリングする独自のプログラムを作成しようとしています。ライブラリの名前とパスを解決するのに問題があります。Solaris コマンドの出力は、bash シェルから次のようになります。

bash-2.05# pmap $$
2427:   bash
00010000     496K r-x--  /usr/bin/bash
0009A000      80K rwx--  /usr/bin/bash
000AE000     120K rwx--    [ heap ]
FF100000     688K r-x--  /usr/lib/libc.so.1
FF1BC000      24K rwx--  /usr/lib/libc.so.1
FF1C2000       8K rwx--  /usr/lib/libc.so.1
FF200000     568K r-x--  /usr/lib/libnsl.so.1
FF29E000      32K rwx--  /usr/lib/libnsl.so.1
FF2A6000      32K rwx--  /usr/lib/libnsl.so.1
FF2F0000       8K rwx--    [ anon ]
FF300000      16K r-x--  /usr/lib/libmp.so.2
FF314000       8K rwx--  /usr/lib/libmp.so.2
FF320000       8K r-x--  /usr/platform/sun4u-us3/lib/libc_psr.so.1
FF330000      40K r-x--  /usr/lib/libsocket.so.1
FF34A000       8K rwx--  /usr/lib/libsocket.so.1
FF350000     168K r-x--  /usr/lib/libcurses.so.1
FF38A000      32K rwx--  /usr/lib/libcurses.so.1
FF392000       8K rwx--  /usr/lib/libcurses.so.1
FF3A0000       8K r-x--  /usr/lib/libdl.so.1
FF3B0000       8K rwx--    [ anon ]
FF3C0000     152K r-x--  /usr/lib/ld.so.1
FF3F6000       8K rwx--  /usr/lib/ld.so.1
FFBFC000      16K rw---    [ stack ]
 total      2536K

/proc/$$/map を読み取ることで、プログラムの基本機能をほぼ複製できますが、残っているのは、右側に示されているライブラリ名を解決する方法を見つけることです。/proc/$$/map は /proc/$$/object 内のファイルの名前のみを提供します。これは単なる一般的な名前です。Solaris 10 (私が持っているボックス) では、シンボリック リンクを含む /proc/$$/path を使用できるようですが、作業中のボックスにはこれらがありません。これらのライブラリ名を取得する方法について簡単なアイデアを持っている人はいますか? プログラムをトラスすると、 /proc/$$/as が開き、メモリを調べて何とか見つけたようですが、どこを見ているのか、その理由はまだわかりません。

4

1 に答える 1

3

の Solaris 実装は、pmap実際には OpenSolaris を介してソース形式で入手できますpmap.c。しかし、これは非常に複雑なことです。基本は達成するのがより簡単です。

Solaris にはマップ用のハンドルが3 つあります。 /proc

  1. /proc/<PID>/mapstruct prmap「通常の」ワーキング セット サイズを反映するデータを含む
  2. /proc/<PID>/rmapこれには、仮想セット サイズ (VSZ) 以外のデータも含まれstruct prmapます。つまり、マッピングがコミットされていない場合でも、マッピングされた VA 範囲を反映します。
  3. /proc/<PID>/xmapこれにはstruct prxmapデータが含まれており、実際にアドレス空間をトロールしてメモリ常駐領域を識別します。

ユーティリティは、 ( )、( )、または( )pmapのいずれかの引数を渡さない場合にこれらを調べますが、マップ プロシージャ ファイルを単に開いたり読み取ったりするだけではありません。これが、ソースコードの解析を難しくしている主な原因です。map-rrmap-xxmap

それにもかかわらず、次のようなコードを使用して、自明な Solaris [rx]map(もちろんアクセスする場合struct prxmapの代わりに使用) パーサーを構築できます。struct prmapxmap

char mappath[MAXPATHLEN];
sprintf(mappath, "/proc/%d/map", getpid());
int fd = open(mappath, O_RDONLY);
size_t nread;
size_t mapsz = (1 << 20);                 /* start at 1MB */
struct prmap *cur*mapbuf = malloc(mapsz);

while ((nread = pread(fd, mapbuf, mapsz, 0)) == mapsz) {
    free(mapbuf);
    mapsz *= 2;
    mapbuf = malloc(mapsz);
}
for (cur = mapbuf; nread; cur++, nread -= sizeof(*mapbuf))
    prettyprint(cur);
free(mapbuf);

いくつかのヒント:

  • mmap()ファイルにアクセスしようとしないでくださいmap。それは機能しません (procfs では許可されていません)。
  • その一部を順番に読み取ろうとしないでください。上記 (全体を最初からサイズ変更されたバッファーに再読み込みする) は、連続したシーケンスを実行するよりも高速read()です。常に最初から読み取ります (pread例のように使用するか、lseek(..., 0, SEEK_SET)いずれかの前に使用しますread)。

実験を楽しんでください!

編集:

マッピングの背後にあるパス名を見つけることに心を決めたので、これは非常に難しい作業の 1 つです。pmapはそれ自体を処理しませんが、 の機能を使用してlibprocこれらの名前を解決します。これは、 で見つかったようtrussに、プロセスのアドレス空間を調べてこれらを抽出する場合がありますが、他のいくつかの手法も使用します。これは基本的に、これを行う「iter」関数libproc/Psymtab.cです。Solaris 9 とそれ以降のバージョンにも違いがあります...思い出せません、あまりにも昔のことです...

于 2011-11-10T15:00:20.587 に答える