在微控制器运行时更新符号 table
Updating Symbol table at runtime in microcontroller
我正在开发一个带有 ARM 微控制器的项目,我在运行时将一个 C 模块(或目标文件)文本段加载到 FLASH。
但是现在加载模块后,这个模块中函数的地址都变了。
那么,是否可以更改符号 table 上的地址?如果是这样,怎么做到的?
通常绝对地址由 linker 解析,编译器生成的目标模块不 linked 并且包含将由 linker 解析的符号信息。
要在 运行 时间加载目标模块,需要 运行 时间能够执行 link 并动态定位步骤。也就是说,它必须能够设置相对于加载位置的地址,并将任何 link 解析为已加载的代码(静态或动态)。为实现这一点,运行time 必须包含已加载代码的符号 table,并且能够使用新代码更新该符号 table,因为新代码可能是 linked 到现有代码,如果加载更多模块,可能 link 到以前动态加载的代码。
这是可以做到的,例如,VxWorks 是一个 RTOS,它完全可以做到这一点 - 尽管是 RAM 而不是 Flash。然而,从头开始实施并不是一项微不足道的任务,并且需要保留包含所有 public 符号的符号 table 意味着它需要大量的内存资源,这在微控制器板上通常不可用。 运行时间必须支持和理解目标文件格式。
为了动态地 link 并定位到闪存,有必要在写入闪存时省略尚未解析的地址,并在符号 table 完成后追溯写入它们。
我认为知道如何做到这一点后,您可能会认为不值得付出努力并设计一些替代解决方案。
如果代码是完全独立的并且不需要 link 与现有代码,那么这可能是一个更简单的问题,并且本质上是引导加载程序所做的。在那种情况下,您将创建一个完全 linked 和定位的二进制文件并将其加载到构建时指定的位置,然后有一些“执行”或引导加载程序选择多个 executable 中的哪个到 运行。最好在重置后进行选择,以确保处理器状态处于已知状态并且不依赖于任何先前的执行。
另一种解决方案可能是避免任何加载和 运行 本机代码的尝试,而是支持嵌入式语言解释器,并用该语言编写动态加载的代码。存在用于 Lua 等语言的解释器,实现您自己的嵌入式脚本语言并不难,并且某些语言(例如 FORTH)非常容易实现。总的来说,这可能更安全,因为 运行time 系统可以将您的解释代码与系统的其余部分隔离开来,而动态加载 linking 任意目标代码则不能。
我正在开发一个带有 ARM 微控制器的项目,我在运行时将一个 C 模块(或目标文件)文本段加载到 FLASH。
但是现在加载模块后,这个模块中函数的地址都变了。
那么,是否可以更改符号 table 上的地址?如果是这样,怎么做到的?
通常绝对地址由 linker 解析,编译器生成的目标模块不 linked 并且包含将由 linker 解析的符号信息。
要在 运行 时间加载目标模块,需要 运行 时间能够执行 link 并动态定位步骤。也就是说,它必须能够设置相对于加载位置的地址,并将任何 link 解析为已加载的代码(静态或动态)。为实现这一点,运行time 必须包含已加载代码的符号 table,并且能够使用新代码更新该符号 table,因为新代码可能是 linked 到现有代码,如果加载更多模块,可能 link 到以前动态加载的代码。
这是可以做到的,例如,VxWorks 是一个 RTOS,它完全可以做到这一点 - 尽管是 RAM 而不是 Flash。然而,从头开始实施并不是一项微不足道的任务,并且需要保留包含所有 public 符号的符号 table 意味着它需要大量的内存资源,这在微控制器板上通常不可用。 运行时间必须支持和理解目标文件格式。
为了动态地 link 并定位到闪存,有必要在写入闪存时省略尚未解析的地址,并在符号 table 完成后追溯写入它们。
我认为知道如何做到这一点后,您可能会认为不值得付出努力并设计一些替代解决方案。
如果代码是完全独立的并且不需要 link 与现有代码,那么这可能是一个更简单的问题,并且本质上是引导加载程序所做的。在那种情况下,您将创建一个完全 linked 和定位的二进制文件并将其加载到构建时指定的位置,然后有一些“执行”或引导加载程序选择多个 executable 中的哪个到 运行。最好在重置后进行选择,以确保处理器状态处于已知状态并且不依赖于任何先前的执行。
另一种解决方案可能是避免任何加载和 运行 本机代码的尝试,而是支持嵌入式语言解释器,并用该语言编写动态加载的代码。存在用于 Lua 等语言的解释器,实现您自己的嵌入式脚本语言并不难,并且某些语言(例如 FORTH)非常容易实现。总的来说,这可能更安全,因为 运行time 系统可以将您的解释代码与系统的其余部分隔离开来,而动态加载 linking 任意目标代码则不能。