如何动态分配函数代码?

2024-01-01

在 C 语言中,函数指针作为来自某个库的回调的通常途径是包含一个void*用户上下文的指针:

void (*fp)(void* ctx);

允许库使用上下文调用回调ctx.

假设我使用的库在回调中不包含上下文指针。我需要为每个上下文进行一个回调。在 C 中动态分配函数指针以提供回调的最可移植的方法是什么?我怎么能够malloc()可以从库中调用的函数代码?

例如:

typedef void (*my_fp_t)(char);

my_fp_t fp = (my_fp_t) malloc(sizeof(...));
init_function_ptr(fp, "Hello, there");
my_library_callback(fp);
...

void my_library_callback(my_fp_t fp) {
  fp('a'); // prints "Hello, there"
}

假设您希望分配实际的函数代码,而不是函数指针。编写引导加载程序和类似内容时完成此操作的方式:

  • 完全确定编译器和 ABI 使用的底层调用约定。您需要确切地知道堆栈帧中的哪些寄存器和/或位置是函数调用和返回时发生的一切。
  • 通过在 C 编译器中编写函数并仔细复制/粘贴程序集,或者在汇编程序中手动编写函数来生成汇编代码。
  • 将汇编程序翻译为操作码。
  • 确保有一块内存可以用来存储数据和执行代码。这也取决于 ABI 和 MMU 设置。
  • 了解如何在此自定义段中分配内存。通常涉及一些链接器脚本摆弄和各种非标准关键字。#pragma __declspec __attribute__blabla上面加糖。高度特定于编译器。
  • 将内存作为原始内存分配给该区域uint8_t func [n]数组,包含十六进制的原始 OP 代码。
  • 关闭严格别名和其他此类邪恶的指针转换。从对象指针转换为函数指针时,确保编译器具有一些定义良好的非标准扩展。
  • 通过调用代码((func_ptr)func) ().

正如您希望看到的那样,这可能是一项艰巨的任务,具体取决于系统。对于使用嵌入式系统编译器的小型微控制器来说,这是很容易实现的。对于 x86 或 PowerPC 等更复杂的系统,使用 gcc 等编译器的情况要小得多。您将依赖于各种不明确的行为,并且代码将完全特定于系统。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何动态分配函数代码? 的相关文章

随机推荐