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

链接器返回错误:“ unresolvable symbol '_formatted_write' referenced in expression”。

我注意到如果我写了一些垃圾而不是_formatted_write,那么它会返回错误“ undefined symbol .....”,因此,_formatted_write链接器知道。

这让我觉得我应该执行一些额外的步骤以使其“可解决”。但仍然不知道该怎么做。

4

2 回答 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

链接器现在知道所有引导加载程序函数的地址,我们可以链接它,而无需在应用程序中拥有实际的函数代码。我们所需要的就是为我们要执行的每个引导加载程序函数声明一个声明。

于 2016-10-21T19:54:29.330 回答
1

我发现的方法是使用函数指针,即

void (*formatted_write)( int a, char * b, struct mystruct c );

然后,在启动时某处的代码中设置此函数的地址,即

formatted_write = 0xa0000;

然后,您可以使用常规约定调用您的函数。

此外,您可以在编译时使用 -Wl,--just-symbols=symbols.txt 标志。您可以按如下方式设置符号的地址:

formatted_write = 0xa0000;
于 2014-01-10T02:15:38.277 回答