1

私の質問に答えるために DynamoRIO について知る必要はないかもしれませんが、C++ プログラムで C クライアントを使用してDynamoRIOでバイナリ インストルメンテーションを行っています。現在、署名を持つ関数をラップしています:

virtual void foo(Klass& s)

そして、ラップ関数で、この関数呼び出し ( Klass& s) の引数を void ポインター ( void *arg1) に取得できます。Klassこの引数を使用する必要があります (つまり、フィールドへのアクセス、メソッドの呼び出し)が、C++ クラスであり、使用しているクライアントが純粋な C であるため、適切なポインターにキャストできません。

void*の内容を次のようにキャストして印刷しようとすると、次のsize_tようになります。

printf("%zd\n", (size_t)arg1);

25102856それは私がメモリアドレスであると推測しているような8桁の数字を私に与えます。

私の質問は、プログラムでこのオブジェクトにアクセスするにはどうすればよいですか?

Pls はあなたが必要とするすべての情報を尋ねます、私はすべてのアイデアを受け入れます。

4

3 に答える 3

3

これを機能させるには、次の例のように、ゲッターとセッターに C スタイルのラッパーを定義します。

あなたのクラスのために

class Klass {
public:
  int getA() const;
  void setA(int);
  virtua int getB() const;
};

このクラスをラップする C 構造体を定義します。

typedef int (*GetInt)(void*);
typedef void (*SetInt)(void*,int);
// and similar for other types


struct KlassCInterface {
  void* object;
  GetInt getA;
  SetInt setA;
  GetInt getB;
};

extern "C" int getA(void* obj)
{
    return static_cast<Klass*>(klassObj)->getA();
}
...
KlassCInterface* getCInterface(Klass* obj)
{
   // malloc just in case your client want to use free()
   KlassCInterface* retVal = (KlassCInterface*)malloc(sizeof(KlassCInterface));
   retVal->object = obj;
   retVal->getA = &getA;
   ...
   return retVal;     
}

void* データを渡すときは、C インターフェイスの構造体として渡します。

Klass* obj = new Klass(...);
KlassCInterface* objC = getCInterface(obj);

registerData(objC);

C コードでは、次の C インターフェイスを使用します。

void doSthWihtKlass(void* data)
{
   KlassCInterface* objC  = (KlassCInterface*)data;
   printf("%d\n", objC->getA(objC->object));
}
于 2012-10-16T18:26:13.120 に答える
1

ポインターのセマンティクスについてもっと学ぶ必要があります (これが @Alek の意味だと思います)。

まず、%pprintf 形式指定子を使用して、ポインターを直接出力できます。これは通常、ポインタが指しているメモリ位置など、役立つ値になります。

ポインターを a にキャストし、char *それを使用してメモリからバイトを直接読み取ることができます。または、 にキャストして、unsigned char *を使用して「16 進ダンプ」を実行できます%x。これを にキャストしてint *、C 実装で表される整数を読み取ることができます。たとえば、未使用ビットのない 8 ビット バイトの 4 バイトの 2 の補数のリトル エンディアン符号付き整数などです。

((unsigned long *)(((short *) ptr) + 7))[4]たとえば、7 つの short のサイズと 4 つの unsigned long のサイズに等しいバイト数をスキップして、メモリ位置から unsigned long を読み取ります。an の正しい表現 (C 実装が期待する) がunsigned longその正確なメモリ位置に書き込まれたと仮定すると、その値が得られます。

が指すメモリのどこに何が書き込まれているのかを正確に確認する必要があるだけでなくptr(これが ABI が言及された理由です)、結果のプログラムは移植性がなく、気まぐれに変更/中断される可能性があります。

<inttypes.h>ヘッダーで指定されている正確な幅の整数型も必要になる場合があります。

于 2012-10-19T12:06:29.667 に答える
1

これは難しいはずです。基礎となる C++ ABI について知っておく必要があります。G++ はこれを実装ます。

通常、C++ クラスは C の構造体とほぼ同じように実装されます。大まかに言うと、基底クラス オブジェクトが宣言の順序で最初に来ます。次に、クラスの他のすべてのサブオブジェクトが、宣言の順序で続きます。この規則は、囲まれたすべてのオブジェクトに再帰的に適用されます。より多くの情報を保存する必要があるため、ポリモーフィック オブジェクトのレイアウトは異なります。特に、仮想メソッドへのポインター、またはこれらのポインターを含む構造体へのポインターは、オブジェクトと一緒にどこかに格納する必要があります。

これはいずれも ISO 14882 によって対処されていないことに注意してください。これをいじると、未定義の動作が確実に呼び出されます。

仮想メソッドの呼び出しに関しては、v テーブルを探す必要があります。もう一度、コンパイラから ABI を調べてください。

于 2012-10-16T17:37:20.590 に答える