【问题标题】:How to write dynamic loader for bare-metal arm-application如何为裸机臂应用程序编写动态加载程序
【发布时间】:2011-08-02 21:56:56
【问题描述】:

我正在开发一个基于 arm9 处理器的项目。我们只使用裸机,没有任何操作系统,所以很遗憾我们还不支持共享库/动态加载器。

我希望能够从例如 SD 卡加载库,它也可以从主应用程序调用函数。

我的第一次尝试是使用链接器覆盖功能(将库放置在特定的绝对定位部分),但是正如我之前提到的那样,调用主应用程序函数存在问题 -> 每次更改主应用程序时,库都必须重新编译才能回调。

根据这一点,我将不得不编写自己的动态加载器,但我是这方面的新手。请有人给我任何例子如何处理它或如何开始这样的项目?我们正在使用 gcc 作为 arm-elf 目标。

问候 一月

【问题讨论】:

  • 通常,如果一个“库”回调到一个“程序”中,它会通过调用一个函数指针来实现,该指针已在之前的库调用中传递。这样库不依赖于程序的修订。至于使程序“更少”依赖于库的确切构建,跳转表会很简单。

标签: shared-libraries arm dynamic-data relocation bare-metal


【解决方案1】:

检查this application note。它详细描述了动态链接的工作原理以及编写自己的动态加载器需要做什么。它还提供了一些替代方案。我认为跳转表很容易实现,可以解决您更改 API 地址的问题。


编辑:下面是如何做一个简单的跳表。首先,决定您需要从主程序中导出哪些功能。然后做一个函数指针的结构:

typedef struct _MyAPI
{
  int    (*init)(int flags);
  int    (*exit)(int exitcode);
  void * (*getmem)(size_t size);
  void   (*freemem)(void *ptr);
} MyAPI;

在主程序中,定义该结构的一个实例,填写指针,并将其放置在某个预定义的地址:

#include <jumptbl.h>
int    main_init(int flags)
{
  return 0;
}
//...
MyAPI main_API __attribute__((section(".jumptbl"))) = 
{
  &main_init,
  &main_exit,
  &main_getmem,
  &main_freemem,
};

(如果您使用这种方法,则需要在链接器文件中描述 .jumptbl 部分并确保它获得固定地址)

在加载的模块中,获取跳转表的指针,并用它来调用主程序:

#include <jumptbl.h>

MyAPI *pAPI = (MyAPI*)(0x1000000); // there should be a better way to do this

int main()
{
  pAPI->init(0);
  void *block = pAPI->getmem(0x30);
  //...
}

希望这会有所帮助!

【讨论】:

  • 感谢您的回答。请问您知道arm编译器工具链与GCC有多大不同吗? appnote 建议使用 symdefs 文件来创建跳转表,但不幸的是我不知道 gcc 中的 symdefs 替代方案...
  • 我也不确定什么是 symdef,但我在 jumptables 上添加了一个小方法,希望它足够清楚。
  • 感谢您提供有关 jumtables 的信息。这是完美的例子,正如我所需要的。
猜你喜欢
  • 1970-01-01
  • 2018-01-25
  • 1970-01-01
  • 1970-01-01
  • 2012-08-13
  • 1970-01-01
  • 2023-03-19
  • 1970-01-01
  • 2015-04-26
相关资源
最近更新 更多