2

プログラムの各関数に関する情報を定数の形式で保持する必要があります。関数の定数をその直前のコードメモリに入れることができるのではないかと思っていたので、関数ポインタから関数を呼び出すと、関数ポインタの値を引くことでその情報を読み取ることができます。

さらに説明すると、私のコードメモリは次のようになります。

ConstantForFunc1
Func1:
 ....

ConstantForFunc2
Func2:
 ....

そして、以下は私がその情報を読む方法のサンプルコードです

FuncPointer f = &Func2;
int constantForFunc2 = *((int*)(f - sizeof(int)));

また、ハッシュテーブルの使用は、私が達成しようとしていることには遅すぎるため、非常に高速な方法が必要であることに注意してください。そして、定数とそれらから読み取るコードを挿入するこのすべての変更は、私が書いているコンパイラパスによって行われ、LLVMIRを変更します。構造体を使用すると、多くのコードを変更する必要があるため、コンパイラーパスには煩雑になります。

4

3 に答える 3

6

あなたがしていることはまだ意味がありません:

多分構造体を使うことができますか?

struct example
{
  int constantForFunc;
  void (*ptrToFunc)();
};

//After declaring, maybe 3, functions

struct example funcList[3] = {{5, &func1}, {10, &func2}, {15, &func3}};

int currentFuncConstant=funcList[1].constantForFunc;
(*funcList[1].ptrToFunc)();

私は正直に関数ポインタを使用していません。probabyには間違いがあります。

于 2013-02-01T13:37:34.957 に答える
0

関数のアドレスは実行可能バイナリからわかっているため(もちろん共有ライブラリからロードされている場合を除く)、アドレス空間配置のランダム化(ASLR)をオフにしている場合は、gperfを使用して非常に効率的なハッシュ関数を生成できます。そのハッシュ関数を使用して、各関数の定数を取得します。

ただし、このためには、プログラムを2回コンパイルする必要があります。最初に、生成されたバイナリから関数のアドレスを取得します。これにより、これらのアドレスを入力として指定し、gperfによって生成されたハッシュ関数を使用して再コンパイルできますgperf。ただし、最初のコンパイルからの関数のアドレスが2番目のコンパイルで異ならないように注意する必要があります。どうすればそれを達成できるかわかりません。

gperf別の方法は、プログラムがロードされた直後のようなことをすることです。そうすれば、2回コンパイルする必要はありません。しかし、私はそれを行う方法がわかりません。

于 2013-02-01T16:05:35.557 に答える
0

これはまったく受け入れられませんか?:

#include <iostream>

using namespace std;

const int Const__Fxn1 = 1;
void Fxn1()
{
  cout << "Fxn1" << endl;
}

const int Const__Fxn2 = 2;
void Fxn2()
{
  cout << "Fxn2" << endl;
}

#define GetFxnConst(FxnName) Const__ ## FxnName

int main()
{
  cout << GetFxnConst(Fxn1) << endl;
  cout << GetFxnConst(Fxn2) << endl;
  return 0;
}

オプション 2:

#include <iostream>
#include <cstring>

using namespace std;

const volatile int v1 = 0;
volatile unsigned v2 = 0;

void Fxn1()
{
  if (v1) { v2 = 0x12345601; }
  cout << "Fxn1" << endl;
}

void Fxn2()
{
  if (v1) { v2 = 0x12345602; }
  cout << "Fxn2" << endl;
}

int FindFxnConst(void(*f)())
{
  const unsigned char* p = (const unsigned char*)f;
  while (memcmp(p, "\x56\x34\x12", 3))
    p++;
  return p[-1];
}

int main()
{
  Fxn1();
  cout << FindFxnConst(Fxn1) << endl;
  Fxn2();
  cout << FindFxnConst(Fxn2) << endl;
  return 0;
}

出力 ( Ideone ):

Fxn1
1
Fxn2
2

他のマジック プレフィックスを使用して、関数ごとに 8 ビットを超えるデータを埋め込むことができます。

  if (v1)
  {
    v2 = 0x12345611; // byte 1
    v2 = 0x789ABC22; // byte 2
    v2 = 0xDEF01233; // byte 3
    v2 = 0xFEDCBA44; // byte 4
  }

これは必ずしも信頼できるソリューションではなく、ポータブルであることは言うまでもありません。

于 2013-02-01T14:22:24.237 に答える