1

現在抱えている問題を正確に説明する方法がわからなかったので、質問のタイトルがあいまいでしたら申し訳ありません。

私が今持っているのは、変数に格納されている仮想アドレスのリストです。たとえば、私は持っています

0x8c334dd

char 変数に格納されます。このアドレスは、データを持つ別の変数のアドレスです。私がやりたいことは、そのアドレスに行き、そこに保存されているデータを取得することです。

私の仮定では、ポインターを逆参照するのが最善の方法でした。残念ながら、アドレスが指している変数の型がわからないので、この場合、逆参照はどのように機能しますか? できません:*(char *) 8c334ddアドレスが指している変数の型がわからないため...

としてキャストすると、(int *)一部のアドレスが指しているいくつかの変数のデータの一部を取得します (複数のアドレスがあることを思い出してください) が、他のアドレスについてはアドレスを取得するだけであり、データが必要です (この変数は構造体、文字など)。

ELF シンボル テーブルを使用しています

4

2 に答える 2

3

一般に、C++ または C では、使用しているポインターの型を知る方法がありません。

この問題を解決する通常の方法は、ポインターが構造体を指すようにし、構造体内の既知の位置にデータの型を示すようにすることです。通常、既知の位置は構造体の最初の位置です。

例:

// signature value; use any value unlikely to happen by chance
#define VAR_SIG 0x11223344

typedef enum
{
    vartypeInvalid = 0,
    vartypeInt,
    vartypeFloat,
    vartypeDouble,
    vartypeString,
    vartypeMax  // not a valid vartype
} VARTYPE;

typedef struct
{
    VARTYPE type;
#ifdef DEBUG
    uint32_t sig;
#endif // DEBUG
    union data
    {
        int i;
        float f;
        double d;
        char *s;
    };
} VAR;

その後、サニティ チェックを実行できます。typeフィールドの値がより大きいかvartypeInvalid小さいvartypeMaxかを確認できます (サニティ チェック コードでこれらの名前を編集する必要はありません。さらにタイプを追加する場合は、前vartypeMaxにそれらを追加します。リスト)。また、DEBUGビルドの場合、署名フィールドsigに特定の署名値が含まれていることを確認できます。(これは、インスタンスを初期化するための初期化コードがVAR常にsigフィールドを設定する必要があることを意味します。)

このようなことを行う場合、どのように初期化しますか? ランタイム コードは常に機能します。

VAR v;

#ifdef DEBUG
v.sig = VAR_SIG;
#endif // DEBUG
v.type = vartypeFloat;
v.data = 3.14f;

コンパイル時に初期化したい場合はどうしますか? int型は の最初の型であるため、整数値で初期化するのは簡単ですunion

VAR v =
{
    vartypeInt,
#ifdef DEBUG
    VAR_SIG,
#endif // DEBUG
    1234
};

C99 準拠バージョンの C を使用している場合は、実際に構造体をフィールド名で初期化し、任意の型を割り当てることができます。floatしかし、Microsoft C は C99 に準拠していないため、構造体をordouble値で初期化したい場合、上記は悪夢です。(float 値を整数にキャストすると、C は型を変更するだけでなく、値を丸めます。また、32 ビットを正しく表す 32 ビット整数値を移植可能に取得するためのトリックは私が知っているものではありません。 C プログラムではコンパイル時に float になります。)

コンパイル時のフロート パッキング/パニング

ただし、ポインターを使用している場合は簡単です。ユニオンの最初のフィールド名をポインター型にし、ポインターをキャストして、void *上記のように構造体を初期化します (ポインターは1234上記の場所に移動します)。

他の誰かのコードで書かれたテーブルを読んでいて、型識別子フィールドを追加する方法がない場合、私には一般的な答えはありません。ポインターをさまざまなタイプとして読み込んで、どれが機能するかを確認できると思いますか?

于 2012-09-17T21:28:38.417 に答える
0

ELF シンボル テーブルで作業している人々のために、何かを追加したかったのですが、DWARF ファイルの DIE の方が作業しやすいことがわかりました。ELF の代わりに DWARF を使用して、変数のアドレス、型、および名前を取得できます。libdwarf には優れたドキュメントがあります。

于 2012-09-18T18:40:02.620 に答える