link错误__semihosting_swi_guard multiply defined问题

来源:互联网 发布:知乎 百事可乐 无糖 编辑:程序博客网 时间:2024/06/05 22:33

最近在mstar上编译c++代码,编译最后link时报错:

Error: L6200E: Symbol __semihosting_swi_guard multiply defined (by use_semi.o and use_no_semi.o).

陌生的错误,从来没见过,__semihosting_swi_guard重定义,这个是什么东西,立即在工程里展开搜索,结果0,工程代码里都没有这个东西。郁闷了。

找google,恩,相关文章不少啊。

Semihosting:一种机制,在RVCT C库中,对某些ISO C功能的支持由主机调试环境提供,提供改功能的机制就是Semihosting.关于它推荐个文章:

基于arm的semihosting的分析与实现 http://www.docin.com/p-72364998.html

关于这个错误,ARM官网上也有说明并且给出了解决方法,详见http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0056d/Babdhjff.html

大致意思是如果在程序中引入了__use_no_semihosting_swi,但最终映像仍链接了Semihosting库,会提示重定义。或者你的程序里调用了一些标准C的函数,如malloc,printf之类,但这些函数在嵌入式C语言里是没有定义的,你需要对你调用的这些函数进行重新定义。

为帮助找出这些使用了Semihosting的函数,可以使用-verbose链接选项。关于-verbose选项官方说明http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0493c/CHDJIBID.html。

mstar中使用:

打开link.mak文件,目录proj\sc\customer\product\common\mak\,找到如下代码段

ifeq ($(LINKER),RVCTV22_link)
ifeq ($(filter __I_SW__ ,$(PP_OPT_COMMON)),__I_SW__)
LDFLAGS=--elf --noremove --map --symbols --info sizes --info unused --xref --entry 0x0 --list $(OUT)link.info --symdefs symdefs.info
else
# Eric: Use RVCT linker functional link to save unused section
LDFLAGS=--elf --remove --map --symbols --info sizes --info unused --xref --entry 0x0 --list $(OUT)link.info --symdefs symdefs.info --keep MontageRam --keep msmDrvTypeA_s --feedback $(BUILD)$(PRODUCT)/fb.txt
endif
endif

我代码中LINKER=RVCTV22_link,所以修改红色代码部分,添加-verbose 选项:

LDFLAGS=--elf --remove --verbose --map --symbols --info sizes --info unused --xref --entry 0x0 --list $(OUT)link.info --symdefs symdefs.info --keep MontageRam --keep msmDrvTypeA_s --feedback $(BUILD)$(PRODUCT)/fb.txt

重新编译代码,代码中调用的c库函数或者semihosting的函数会被__I_use_semihosting_swi标记,在log中查找__I_use_semihosting_swi,这些实现这些函数。

比如:

  Loading member sys_exit.o from c_a__un.l.

                               definition: _sys_exit

                               reference: __I_use_semihosting_swi

只要在代码里重新实现_sys_exit函数就可

void _sys_exit(int exit)
{
exit = exit;
}

重新编译,ok!