0

我有一个用于嵌入式系统的工作二进制文件。现在我想为它写一个补丁。补丁将被加载到主程序下方的 RAM 中,然后将从主程序中调用。问题是如何告诉 gcc 使用将从补丁中使用的某些函数的手动设置地址。换句话说:旧代码具有功能sin(),我可以使用 nm 找出sin()旧代码中的地址。我的修补代码将使用sin()(或来自主程序的其他东西),我想告诉 gcc(或者可能是 ld 或其他东西)在sin()链接修补代码时使用函数的静态地址。可能吗?

4

1 回答 1

0

问题是您会替换所有对sin()修补代码的原始函数的引用。这将要求运行时系统包含用于解析引用的所有目标代码数据,并且原始代码是可修改的(例如,不在 ROM 中)。

Windriver 的 RTOS VxWorks 可以做一些接近你所建议的事情;这样做的方式您使用“部分链接”(GNU 链接器选项-r)来生成带有将在运行时解析的链接的目标文件 - 这允许使用未解析的链接创建目标文件 - 即不完整的可执行文件。VxWorks 本身包含一个加载器和运行时“链接器”,可以动态加载部分链接的目标文件并解析引用。但是,加载的目标文件必须完全可以使用已加载的目标代码解析 - 因此没有循环依赖关系,在您的示例中,您必须重新加载/重新启动系统,以便之前sin()加载包含的目标文件那些引用它的,否则只有那些之后加载的才会使用新的实现。

因此,如果您要使用 VxWorks(或具有类似功能的操作系统),解决方案可能很简单,否则您必须实现自己的加载器/链接器,这当然是可能的,但并非易事。

另一种可能更简单的可能性是通过变量中保存的指针让所有代码调用函数,以便在运行时解析所有调用(或至少所有可能要替换的调用)。您必须加载补丁,然后修改sin()函数的指针,以便此后的所有调用都对新函数进行。这种方法的问题是你要么必须先验您以后可能想要替换哪些函数,或者以这种方式调用所有函数(这在内存方面可能非常昂贵。对于这个解决方案来说,拥有某种允许您标记函数的预处理器或代码生成器可能会很有用这将是“动态”的,并且可以自动生成指针和调用代码。例如,您可以这样编写代码:

__dynamic void myFunction( void ) ;

...

myFunction() ;

并且您的自定义预处理器将生成:

void myFunction( void ) ;
void (*__dynamic_myFunction)(void) = myFunction() ;

...

__dynamic_myFunction() ;

那么您的补丁/加载程序代码将使用替换函数的地址重新分配 myFunctionDyn。

您可以生成仅包含 __dynamic_xxxxx 符号的名称和地址的“动态符号表”,并将其包含在您的应用程序中,以便加载程序可以通过将 xxxxx 名称与加载的目标文件中的符号匹配来更改 __dynamic_xxxxx 变量 - 如果您加载一个普通的二进制文件,但是您必须向加载程序提供链接信息 - 即要重新分配哪个 __dynamic_xxxxx 变量以及要分配给它的地址。

于 2013-04-02T10:41:50.477 回答