2

我需要以常数的形式在我的程序中保留一些关于每个函数的信息。我想知道是否可以将函数的常量放在代码存储器之前,所以如果通过函数指针调用函数,则可以通过减去函数指针的值来读取该信息。

为了进一步说明,我的代码内存应如下所示。

ConstantForFunc1
Func1:
 ....

ConstantForFunc2
Func2:
 ....

以下是我将如何阅读该信息的示例代码

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

请注意,使用哈希表对于我想要实现的目标来说太慢了,所以我需要一个非常快速的方法。所有这些修改,即插入常量和从中读取的代码,都是由我正在编写的编译器传递完成的,它修改了 LLVM IR。使用结构对于编译器传递来说太麻烦了,因为它必须修改大量代码。

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)();

老实说,我没有使用函数指针,可能有错误。

于 2013-02-01T13:37:34.957 回答
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 回答
0

由于函数的地址是从可执行二进制文件中知道的(除非它们是从共享库加载的),如果你关闭了地址空间布局随机化(ASLR),你可以使用gperf为你生成一个高效的哈希函数并使用该哈希函数来获取每个函数的常量。

但是,为此,您必须编译您的程序两次,首先从生成的二进制文件中获取函数的地址,以便您可以将这些地址作为输入提供给gperf并使用生成的哈希函数重新编译gperf。但是你必须小心,第一次编译的函数地址在第二次编译时不会变得不同。我不确定,如何实现。

另一种选择是gperf在程序加载后执行类似操作,这样您就不必编译两次。但我不知道该怎么做。

于 2013-02-01T16:05:35.557 回答