链接脚本:将函数的绝对地址插入生成的代码

5
我有一个关于gcc链接器的问题。
我正在处理嵌入式设备(PIC32),但是PIC32的编译器和链接器基于gcc,因此,“常规”的gcc链接器和PIC32链接器的主要内容应该是相同的。
为了节省闪存空间(微控制器上通常不足),我需要将几个大型函数放在引导加载程序中,并且应用程序应该通过指针调用这些函数。
所以,我需要在生成的代码中创建向量表。
我试图获取函数的绝对地址并将其写入生成的代码,但仍然出现错误。
以下示例中,我试图获取函数_formatted_write的地址。
代码:
.user_addr_table _USER_ADDR_TABLE_ADDR :
{
   KEEP(*(.user_addr_table))
   LONG((ABSOLUTE(_formatted_write))); /* _formatted_write is a name of my function */
} > user_addr_table

链接器返回错误:"在表达式中引用了无法解析的符号“_formatted_write”"。
我注意到如果我写一些垃圾而不是_formatted_write,那么它会返回错误"未定义的符号.....",因此链接器知道_formatted_write
这使我想到我应该执行一些附加步骤来使它"可解决"。但还不知道怎么做。

需要通过向量表中的条目调用这些函数吗?否则,您可以尝试在传递引导加载程序elf文件的符号时进行链接。 - parvus
_formatted_write这个名称是在引导加载程序的映射文件中出现的名称吗? - parvus
2个回答

2

如果有人遇到和我一样的问题(就像几个小时前的我),这里有一个更好的解决方案:

假设"bootloader.out"是引导程序二进制文件。我们可以使用以下命令生成:

nm -g bootloader.out | grep '^[0-9,a-e]\{8\} T' | awk '{printf "PROVIDE(%s = 0x%s);\n",$3,$1}' > bootloader.inc

一个文件,我们可以将其包含在应用程序的链接器脚本中。
INCLUDE bootloader.inc

链接器现在知道所有引导加载程序函数的地址,因此我们可以针对它进行链接,而无需在应用程序中具有实际的函数代码。我们所需要的只是每个我们想要执行的引导加载程序函数的声明。

我尝试了给定的代码,但我注意到正则表达式只包含字母a-e,而不是a-f(以及A-F)。 - undefined
谢谢,是个打字错误。 - undefined

2
我发现解决这个问题的方法是使用函数指针,即
void (*formatted_write)( int a, char * b, struct mystruct c );

然后,在代码中的某个地方设置该函数的地址,即:

formatted_write = 0xa0000;

你可以按照正常惯例调用你的函数。
此外,编译时你可以使用-Wl,--just-symbols=symbols.txt标志。你可以按以下方式设置符号的地址:
formatted_write = 0xa0000;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接