在嵌入式目标上动态加载代码

Tar*_*eeb 10 embedded gcc ld

我有一个在裸机目标上运行的应用程序,具有以下结构

  • main.c中
  • service.c/.H

它编译成ELF可执行文件(system.elf)使用标准gcc -c,ld序列.我使用链接器生成一个显示所有符号地址的映射文件.

现在,在不重新刷新系统的情况下,我需要使用自定义运行时加载器添加额外的功能.请记住,这是一款没有操作系统的裸机.

我想

  • 编译extra.c,它使用service.h中定义的API(并以某种方式链接现有的service.o/system.elf)
  • 在运行时将生成的可执行文件复制到我的SDRAM 并跳转到它
  • 加载的代码应该能够运行并按预期访问service.c中的导出符号

我以为我能够重用map文件来链接extra.o对system.elf但这不起作用:

ld -o extraExe extra.o system.map
Run Code Online (Sandbox Code Playgroud)

gcc或ld是否有某种模式来进行这种后期链接过程?如果没有,我如何实现上面概述的动态代码加载?

小智 7

您可以在ld中使用'-R filename '或'--just-symbols = filename '命令选项.它从文件名中读取符号名称及其地址,但不重新定位或将其包含在输出中.这允许输出文件以符号方式引用system.elf程序中定义的内存的绝对位置.(参见ftp://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_node/ld_3.html).

所以这里的文件名是'system.elf'.您可以使用GCC编译extra.c,通常包括services.h但没有链接并生成'extra.o',然后调用ld,如下所示:

ld -R"system.elf" -o"extra.out" extra.o
Run Code Online (Sandbox Code Playgroud)

'extra.out'将链接您的符号.您可以使用objdump来比较'extra.out'和'extra.o'的内容.请注意,您可以随时通过你的程序的起始地址到其他存储部分就像BSS,数据的LD(如-defsym _TEXT_START_ADDR = 0xAAAA0123)以及起始地址.(即-Tbss,-Tdata)
小心使用与'system.elf'不冲突的有效地址,因为ld不会为此生成错误.您可以在原始链接描述文件中为加载的代码+ data + bss定义新区域,然后重新编译system.elf,然后在链接'extra.o'时将起始地址指向您定义的区域.