我能确定函数的二进制代码会被顺序复制吗?

Can I be sure that the binary code of the functions will be copied sequentially?

抱歉,如果这个问题已经存在,因为我希望使用这种方法,但我只是不知道它是如何调用的。所以,我的目的是从内存中执行一系列函数,为此我复制了第一个和最后一个函数的大小。

这是我的第一次尝试:

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

这在我第一次更新后有效,但后来,我不得不再次更新,现在这给了我错误的尺寸。大小接近 900+ 字节。我改变了一些功能,大小变成了 350+ 字节我没有改变那么多。 我禁用了优化和内联优化。

所以我的问题是如何确保我的 func1 的地址比上一个 funcn 少,以及什么可以改变它们在内存中的位置。谢谢关注

由于您没有提到的要求,这可能是不可能的,但为什么不使用函数指针数组呢?

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

// Call them in sequence like so: 
for (auto& func: funcs) {
   func();
}
// and then i can memcpy it to file or smth else and execute by adress of first

copy it in memory and then call it in allocated memory and then call by adress of allocation.

需要说明的是:

您不能将代码从一个位置复制到另一个位置并希望它能正常工作。

  1. 不能保证调用函数所需的所有代码 位于一个连续的块中。
  2. 不能保证函数指针实际指向 所需代码的开头。
  3. 不能保证您可以有效地写入可执行内存。对于 OS,你看起来很像病毒。
  4. 不保证代码是可重定位的(在移动到不同位置后能够工作)。为此,它只需要使用相对地址

简而言之:除非你有超出标准C++范围的支持工具,否则别想了。

仅限 GCC 系列!

您可以强制编译器将整个函数放在单独的部分。然后就可以知道函数所在的内存区域了

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