Могу ли я быть уверен, что двоичный код функций будет копироваться последовательно? - PullRequest
0 голосов
/ 04 августа 2020

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

Это моя первая попытка:

source.cpp

void func1(int var1, int var2)
{
  func2();
  func3();
  //etc.
}
void func2(...){...}
void func3(...){...}
void funcn(){return 123;}//last func as border, I do not use it

//////////////////////////////////////////////////

main.cpp

#include"source.cpp"

long long size= (long long)funcn-(long long)func1;// i got size of binary code of this funcs;
// and then i can memcpy it to file or smth else and execute by adress of first

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

source.cpp

extern void(*pfunc1)(int, int);
extern void(*pfuncn)();

void(*pfunc1)(int , int) = &func1;
void(*funcn)() = &funcn;

static void __declspec(noinline) func1(int var1, int var2)
{
 //the same impl
}
static void __declspec(noinline) func2(...){...}
static void __declspec(noinline) func3(...){...}
static void __declspec(noinline) funcn(...){retunr 123;}

//////////////////////////////////
main.cpp
#include"source.cpp"

long long size= (long long) pfuncn - (long long) pfunc1;
//same impl

Это сработало после моего 1-го обновления, но потом мне пришлось обновить его снова, и теперь это дает мне неправильный размер. Размер был около 900+ байт. Я изменил некоторые функции, и размер стал 350+ байтов, я не так много менял. Я отключил оптимизацию и встроенную оптимизацию.

Итак, мой вопрос в том, как быть уверенным, что моя функция func1 будет иметь меньший адрес, чем последняя функция, и что может изменить их местоположение в памяти. Спасибо за внимание.

Ответы [ 3 ]

4 голосов
/ 04 августа 2020
// and then i can memcpy it to file or smth else and execute by adress of first

скопируйте его в память, а затем вызовите в выделенной памяти, а затем вызовите по адресу выделения.

Это необходимо указать:

Вы не можете скопировать код из одного места в другое и надеяться, что он сработает.

  1. Нет никаких гарантий, что весь код, необходимый для вызова функции, будет расположен в непрерывном блоке.
  2. Нет никакой гарантии, что указатель функции действительно указывает на начало необходимого кода.
  3. Нет никаких гарантий, что вы сможете эффективно записывать в исполняемую память. Для ОС вы бы очень походили на вирус.
  4. нет никаких гарантий, что код будет перемещаемым (сможет работать после перемещения в другое место). для этого требуется использовать только относительные адреса

Вкратце: если у вас нет вспомогательных инструментов, go выходящих за рамки стандартного C ++, даже не думайте об этом.

2 голосов
/ 04 августа 2020

G CC только семейство!

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

int __attribute__((section(".foosection"))) foo()
{
    /* some code here */
}

в сценарии компоновщика в .text вам нужно добавить

 .text :
  {
 
      /* ... */

    __foosection_start = .;
     *(*foosection)
     *(.foosection*) 
     __foosection_end = .;

     /* .... */

и в том месте, где вы хотите знать или используйте его

extern unsigned char __foosection_start[];
extern unsigned char __foosection_end[];

void printfoo()
{
    printf("foosection start: %p, foosection end: %p\n ", (void *)__foosection_start, (void *)__foosection_end);
}
0 голосов
/ 04 августа 2020

Вероятно, это невозможно из-за требования, которое вы не упомянули, но почему бы не использовать массив указателей на функции?

std::function<void()> funcs[] = {
    func2,
    func3,
    [](){ /* and an inline lambda, because why not */ },
};

// Call them in sequence like so: 
for (auto& func: funcs) {
   func();
}
...