3

几年前,我阅读了一篇博客(现在链接已被遗忘),甚至看到了在我以前的组织中为固件开发补丁时大量使用函数指针的示例。

但由于安全原因/签署了 NDA,我无法获取代码副本(我为不这样做并遵循最佳实践而感到自豪)。

我已经看到这些函数是用一些命名约定编码的,比如:

filename_func_<version>_<minor_string>(arguments,other arguments)

和类似的文件被编码(补丁的一部分)并在 ROM 中刷新,当函数被调用时,它从补丁位置获取函数的新定义的地址。

对此有任何想法/细节吗?

4

1 回答 1

1

必须设计该系统以使这项工作发挥作用。

有多个方面必须协调:

  • 必须有一种方法来更改函数指针。
  • 代码必须通过指针调用函数。

有多种方法可以详细地做到这一点,但它们最终会成为主题的变体。

/* Declaration of function pointer used to invoke the function */
extern int (*filename_func_ptr)(int arg1, char const *arg2);

/* Two versions of the function */
extern int filename_func_1_1(int arg1, char const *arg2);
extern int filename_func_1_2(int arg1, char const *arg2);

/* Definition of function pointer - pointing to version 1.1 of the function */
int (*filename_func_ptr)(int arg1, char const *arg2) = filename_func_1_1;

/* Use of function pointer */
static void some_function(void)
{
    printf("%d\n", (*filename_func_ptr)(1, "pi"));
}

请注意,您可能永远不会在同一个文件中同时拥有filename_func_1_1()filename_func_1_2()声明。我描述的效果是“好像”。

修补后,无论您选择何种方式,结果就像您这样写:

int (*filename_func_ptr)(int arg1, char const *arg2) = filename_func_1_2;

您可能会遇到动态加载(dlsym()、加号dlopen()等)的问题以获取新符号。这将需要一个文件名供库动态加载,以及一种将函数名转换为指向正确函数的指针的方法。

每个可修补函数都需要通过指针统一调用。这就是允许您替换该功能的原因。考虑一个动态(共享)库是否足够(因为它可能会更简单)。如果您使用固件,则可能没有那么奢侈。

您需要考虑如何处理具有不同接口的多个功能;您会使用此处所示的单个全局变量,还是必须在每次调用时适当转换的通用函数指针类型,或者联合类型,或者持有指针的结构,或者......有很多组织事物的方法.

于 2012-04-28T20:57:17.383 回答