Как поместить константы в память кода

Мне нужно хранить некоторую информацию о каждой функции в моей программе в виде постоянного числа. Мне было интересно, можно ли поместить константу для функции непосредственно перед ней в памяти кода, поэтому, если функция вызывается через указатель функции, эта информация может быть прочитана путем вычитания значения указателя функции.

Чтобы проиллюстрировать далее, моя память кода должна выглядеть следующим образом.

ConstantForFunc1
Func1:
....

ConstantForFunc2
Func2:
....

И следующий пример кода, как я бы прочитал эту информацию

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

И обратите внимание, что использование хэш-таблиц слишком медленное для того, чего я пытаюсь достичь, поэтому мне нужен очень быстрый метод. И вся эта модификация, которая вставляет константы и код для чтения из них, выполняется с помощью прохода компилятора, который я пишу и который модифицирует IR LLVM. Использование структур было бы слишком громоздким для прохода компилятора, так как это должно было бы изменить много кода.

2

Решение

То, что вы делаете, пока не имеет смысла:

Вы могли бы использовать структуры, может быть?

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

Если честно, я не использовал указатели на функции, у Пробаби есть ошибки.

6

Другие решения

Разве это не приемлемо вообще?

#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
}

Это не обязательно надежное решение, не говоря уже о портативности.

0

Поскольку адреса функций известны из исполняемого двоичного файла (если они не загружены из общей библиотеки курса), если вы отключили рандомизацию размещения адресного пространства (ASLR), вы можете использовать Gperf создать высокоэффективную хеш-функцию для вас и использовать эту хеш-функцию для получения констант для каждой функции.

Однако для этого вам придется дважды скомпилировать вашу программу, сначала чтобы получить адреса функций из сгенерированного двоичного файла, чтобы вы могли дать эти адреса в качестве входных данных для gperf и перекомпилировать, используя хеш-функцию, сгенерированную gperf, Но вы должны быть осторожны, чтобы адреса функций из первой компиляции не изменились во второй компиляции. Я не уверен, как этого добиться.

Альтернативой было бы сделать что-то вроде gperf только после загрузки вашей программы, так что вам не придется компилировать дважды. Но я не знаю, как это сделать.

0
По вопросам рекламы [email protected]