提问者:小点点

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


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

这是我的第一次尝试:

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更少,以及什么可以改变它们在内存中的位置。 谢谢大家的关注。


共3个答案

匿名用户

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

匿名用户

// and then i can memcpy it to file or smth else and execute by adress of first

在内存中复制它,然后在分配的内存中调用它,然后通过分配的地址调用它。

这一点需要说明:

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

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

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

匿名用户

这很可能是不可能的,因为您没有提到的一个需求,但是为什么不使用函数指针数组呢?

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

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