7

コンテキストを説明するために、私が達成しようとしていることは次のとおりです。.soファイル自体にバージョン文字列を含めるために、共有オブジェクトファイルにconstchar*を埋め込みます。私はデータ分析を行っていますが、この文字列を使用すると、どのバージョンのソフトウェアがデータを生成したかをデータに知らせることができます。これはすべて正常に機能します。

私が抱えている問題は、.soライブラリから文字列を直接読み取ろうとしたときです。使ってみました

nm libSMPselection.so | grep _version_info

取得します

000000000003d968 D __SMPselection_version_info

これはすべて問題なく、期待どおりです(char *は_SMPselection_version_infoと呼ばれます)。ただし、ファイルを開いて0x3d968を探し、文字列の読み取りを開始できると期待していましたが、取得するのはゴミだけです。

.soファイルを開いて、文字列の内容を検索すると(文字列の開始方法はわかっています)、アドレス0x2e0b4で見つけることができます。このアドレスでは、ゼロが終了し、期待どおりにそこにあります。(私は今のところこの方法を使用しています。)

私はコンピューター科学者ではありません。nmで示されるシンボル値が正しくない理由、または別の方法で、シンボルのアドレスでない場合のシンボル値は何であるかを誰かに説明してもらえますか?

(ちなみに私はOSX 10.7を搭載したMacで作業しています)

4

4 に答える 4

7

ELFまたは同様に構造化されたバイナリを想定すると、ELFヘッダー内のものに影響される、ものがロードされるアドレスを考慮する必要があります。

バイナリで使用objdump -Fdすると、逆アセンブラにシンボルの正確なファイルオフセットを表示させることもできます。

を使用objdump -xすると、このローダーアドレスを見つけることができます。通常、標準のLinux実行可能ファイルの場合は0x400000です。

次に注意しなければならないのは、その間接文字列かどうかを確認することです。これは、を使用することで最も簡単に実行できますobjdump -g。文字列が間接文字列であることが判明した場合、出力された位置にobjdump -Fdは文字列ではなくアドレスが表示されます。これから、ローダーアドレスを再度減算する必要があります。私のバイナリの1つの例を示しましょう。

objdump -Fd BIN | grep VersionString
  45152f:       48 8b 1d 9a df 87 00    mov    0x87df9a(%rip),%rbx        # ccf4d0 <acVersionString> (File Offset: 0x8cf4d0)

objdump -x BIN
...
LOAD off    0x0000000000000000 vaddr 0x0000000000400000 paddr 0x0000000000400000 align 2**12
...

したがって、ファイル内の0x8cf4d0を調べて、16進エディターで見つけます。

008C:F4D0 D8 C1 89 00  00 00 00 00  01 00 00 00  FF FF FF FF

そこで、0x89C1D8を取得し、0x400000を減算して、0x49c1d8を取得します。ここで、16進エディターを見ると、次のことがわかります。

0049:C1D0 FF FF 7F 7F  FF FF 7F FF  74 72 75 6E  6B 5F 38 30
0049:C1E0 34 33 00 00  00 00 00 00  00 00 00 00  00 00 00 00

これは「trunk_8043」を意味します。

YMMV、特に他のファイル形式の場合、これはこれらのものがどのように構造化されているかについての一般的な方法であり、特別な場合には多くの疣贅と詳細があります。

于 2012-05-03T12:26:26.973 に答える
2

誰も最も簡単な方法を提案しませんでした:libを動的にロードし(コマンドラインで名前を付けます)、シンボルに対してdlsym()を実行する(またはコマンドラインでも取得できます)バイナリを実行し、文字列ポインターにキャストしますstdoutに出力します。

于 2012-05-03T18:07:38.333 に答える
1

Linuxでは、バイナリから文字列を抽出するのに役立つ「strings」コマンドがあります。

http://linux.about.com/library/cmd/blcmdl1_strings.htm

HPUX(および他のUnixフレーバーでも)には、「what」と呼ばれる同様のコマンドがあります。「@(#)」で始まる文字列のみを抽出しますが、文字列の内容を制御する場合、これは問題ではありません。

于 2012-05-03T11:59:56.617 に答える
1

によって表示されるオフセットがファイル nm内のオフセットであると期待するのはなぜですか?ファイルは単なるメモリイメージではありません。それらには他の多くの情報も含まれており、多かれ少なかれ複雑な形式になっています。Unixでは(少なくともほとんどのUnicesでは)、共有オブジェクトはelf形式を使用します。情報を見つけるには、ファイル内のさまざまなフィールドを解釈し、必要なシンボルがファイル内のどこにあり、どのセグメントにあり、そのセグメントがどこから始まるかを見つける必要があります。(おそらく、それらを読みやすくするライブラリを見つけることができます。).so.so

また、を埋め込んだと言っているのが正しい場合char const*、つまり、コードに次のようなものが含まれている場合:

char const* version = "...";

その場合、のアドレスまたはversionオフセットは、ポインタが指している文字列データではなく、ポインタのアドレスまたはオフセットです。次のように定義します。

char const version[] = "...";

これを解決します。

最後に、最も簡単な解決策は、文字列に高度に識別可能なパターンがあることを確認し、ファイル全体を線形にスキャンしてこのパターンを探すことです。

于 2012-05-03T12:30:16.720 に答える