我尝试将c++项目移植到RISC-V。已经使用IAR工具链为Windows和Windows成功编译了该项目。
对于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 。当我从链接器中删除这些部分时,只要不使用未加载的静态对象,就可以成功运行代码。
此行为有任何解释吗?
最佳答案
我能够找出问题所在。在添加init数组部分时,还添加了一些来自标准库的静态对象。该库正在使用对操作系统的系统调用(ebreak)。由于我们正在使用裸机系统,因此未捕获 call 。
解决方案是排除标准库,并手动实现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
}