将.init_array部分包含到链接器脚本会产生无法使用的输出

时间:2018-06-05 13:28:17

标签: c++ riscv linker-scripts

我尝试将c ++项目移植到RISC-V。该项目已经使用IAR工具链和Windows成功编译为ARM。

对于RISC-V端口,我编写了自己的CRT0.S文件,该文件执行所有初始化以及我自己的链接器脚本。

通过一些小型演示项目,一切都很完美。 我也可以成功编译和链接项目。问题是当我将.init_array部分添加到链接描述文件时,输出文件从大约4k增加到超过100k。我将这些部分添加到链接器脚本中:

.preinit_array     :
{
  PROVIDE_HIDDEN (__preinit_array_start = .);
  KEEP (*(.preinit_array))
  PROVIDE_HIDDEN (__preinit_array_end = .);
} > ram

.init_array     :
{
  PROVIDE_HIDDEN (__init_array_start = .);
  KEEP (*(SORT(.init_array.*)))
  KEEP (*(.init_array ))
  PROVIDE_HIDDEN (__init_array_end = .);
} > ram

.fini_array     :
{
  PROVIDE_HIDDEN (__fini_array_start = .);
  KEEP (*(SORT(.fini_array.*)))
  KEEP (*(.fini_array ))
  PROVIDE_HIDDEN (__fini_array_end = .);
} > ram

当我现在尝试将此ELF文件加载到GDB时,我只会收到错误 No Registers 。当我从链接器中删除部分时,我可以成功运行代码,只要我不使用未加载的静态对象。

这种行为有什么解释吗?

1 个答案:

答案 0 :(得分:2)

我能够找出问题所在。添加init数组部分时,还添加了标准库中的一些静态对象。该库正在使用系统调用操作系统(ebreak)。因为我们正在研究裸机系统,所以没有接到电话。

解决方案是排除标准库并手动实现delete运算符。现在它工作得很好。

void operator delete(void *p) noexcept
{
    free(p);
}

extern "C" void operator delete(void* p, unsigned long c) noexcept
{
    operator delete(p); // Same as regular delete
}