我需要以常数的形式保存程序中每个函数的一些信息。我想知道是否可以在代码存储器中将函数的常量放在它之前,所以如果通过函数指针调用函数,则可以通过减去函数指针的值来读取该信息。
为了进一步说明,我的代码存储器应如下所示。
ConstantForFunc1
Func1:
....
ConstantForFunc2
Func2:
....
以下是我将如何阅读该信息的示例代码
FuncPointer f = &Func2;
int constantForFunc2 = *((int*)(f - sizeof(int)));
请注意,使用哈希表对于我想要实现的目标来说太慢了,所以我需要一个非常快速的方法。所有这些修改,即插入常量和代码来从中读取,都是通过编译器传递来完成的,我正在编写并修改LLVM IR。使用结构对于编译器传递来说太麻烦了,因为它必须修改很多代码。
答案 0 :(得分: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有错误。
答案 1 :(得分: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
}
这不一定是可靠的解决方案,更不用说便携了。
答案 2 :(得分:0)
由于函数的地址是从可执行二进制文件中获知的(除非它们是从共享库中加载的),如果您关闭了地址空间布局随机化(ASLR),则可以使用gperf生成为您提供高效的哈希函数,并使用该哈希函数获取每个函数的常量。
但是,为此,您必须编译程序两次,首先从生成的二进制文件中获取函数的地址,以便您可以将这些地址作为gperf
的输入并使用由gperf
生成的哈希函数。但是必须要小心,第一次编译中的函数地址在第二次编译中不会有所不同。我不确定,如何实现这一点。
另一种方法是在加载程序后执行gperf
之类的操作,这样就不需要编译两次了。但我不知道该怎么做。