mingdu.zheng <at> gmail <dot> com
http://blog.csdn.net/zoomdy/article/details/10615853

官方已解决此问题:

详见:http://hg-pub.ecoscentric.com/ecos/rev/a1df75458e13

问题描述:

在Xubuntu 12.04下编译eCos Synthetic Target的测试程序(通过eCos图形配置工具菜单Build >> Tests),当编译cxxsupp测试程序时出现未解析符号“__sprintf_chk”。

错误输出:

gcc -L/home/pangu/ecos/conf/synth_default_install/lib -Ttarget.ld -o /home/pangu/ecos/conf/synth_default_install/tests/infra/current/tests/cxxsupp tests/cxxsupp.o -g -nostdlib -Wl,-static -Wl,--fatal-warnings
make[1]:正在离开目录 `/home/pangu/ecos/conf/synth_default_build/infra/current'
/usr/lib/gcc/i686-linux-gnu/4.6/libsupc++.a(cp-demangle.o): In function `.L741':
make:离开目录“/home/pangu/ecos/conf/synth_default_build”
(.text+0x4088): undefined reference to `__sprintf_chk'
/usr/lib/gcc/i686-linux-gnu/4.6/libsupc++.a(cp-demangle.o): In function `.L747':
(.text+0x45c3): undefined reference to `__sprintf_chk'
/usr/lib/gcc/i686-linux-gnu/4.6/libsupc++.a(cp-demangle.o): In function `.L747':
(.text+0x473b): undefined reference to `__sprintf_chk'
/usr/lib/gcc/i686-linux-gnu/4.6/libsupc++.a(cp-demangle.o): In function `.L747':
(.text+0x4833): undefined reference to `__sprintf_chk'
/usr/lib/gcc/i686-linux-gnu/4.6/libsupc++.a(cp-demangle.o): In function `d_print_mod_list':
(.text+0x62e9): undefined reference to `__sprintf_chk'
collect2: ld 返回 1
make[1]: *** [/home/pangu/ecos/conf/synth_default_install/tests/infra/current/tests/cxxsupp] 错误 1
make: *** [tests] 错误 2

解决办法:

在packages\hal\synth\arch\<version>\src\synth_entry.c文件中追加以下代码。

#include <stdarg.h>
#include <limits.h>
#include <stdio.h>// __chk_fail -- terminate a function in case of buffer overflow
// copy from gcc-4.8.1/libssp/ssp.c
void __chk_fail (void)
{CYG_FAIL("Buffer overflow detected, aborting");diag_printf("Application error: buffer overflow detected.\n");cyg_hal_sys_exit(1);for(;;);
}// __sprintf_chk -- convert formatted output, with stack checking
// copy from gcc-4.8.1/libssp/sprintf-chk.c
int __sprintf_chk (char *s, int flags __attribute__((unused)),size_t slen, const char *format, ...)
{va_list arg;int done;va_start (arg, format);if (slen > (size_t) INT_MAX)done = vsprintf (s, format, arg);else{done = vsnprintf (s, slen, format, arg);if (done >= 0 && (size_t) done >= slen)__chk_fail ();}va_end (arg);return done;
}

问题原因:

1、Xubuntu 12.04,以及其它最近发行的Linux版本默认开启了GCC的堆栈保护特性,因此sprintf函数调用将会被替换为__sprintf_chk函数调用,__sprintf_chk除了实现sprintf的功能外还将检查堆栈是否溢出。
2、new操作符的实现是由编译器提供的(libsupc++.a),编译eCos Synthetic Target时使用的是Linux下的本地编译器,因此libsupc++.a是在打开堆栈保护特性的情况下编译的,也就是说如果new操作符引用或者间接引用了sprintf函数,那么实际引用的将是__sprintf_chk。
3、new操作符在分配内存失败时需要抛出异常,异常机制经过一系列的函数调用,最终会调用cp-demangle.o文件内的__cxa_demangle函数逆向解析C++名称包装,例如将_Znwj解析为operator new(unsigned int),__cxa_demangle引用了sprintf进行字符串格式化,而在开启GCC堆栈保护特性的情况下,sprintf自动被替换为__sprintf_chk,在Xubuntu中,__sprintf_chk函数由glibc提供,而eCos Synthetic Target虽然编译成Linux下的一个进程,但是使用的仍然是eCos自带的C库,而不是Linux中的C库,而eCos中的C库并没有实现__sprintf_chk函数,因此在链接过程中产生无法解析的符号“__sprintf_chk”,解决办法是实现该函数。

深入解析:

编译器将new和delete操作符的相关代码打包到libsupc++.a静态库(new_op.o和del_op.o),因此使用了new和delete操作符的程序将引用该静态库内的相关代码,根据C++标准要求,new操作符在内存分配失败是将抛出异常,从底层实现角度就是将会调用__cxa_throw函数,而__cxa_throw函数引用了__cxxabiv1::__terminate_handler,这是一个函数指针,该函数指针指向__gnu_cxx::__verbose_terminate_handler函数,该函数引用了cp-demangle.o文件内的__cxa_demangle函数,__cxa_demangle函数引用了__sprintf_chk,使用nm工具输出.o文件符号可以非常清楚地看到函数间可能的调用关系,下面是nm工具的输出,已删除无关的符号,T字母标识的是该.o文件定义的符号,U字母标识的是该.o文件引用的符号。

new_op.o:
00000000 T _Znwj(operator new(unsigned int))U __cxa_throweh_throw.o:U _ZN10__cxxabiv119__terminate_handlerE(__cxxabiv1::__terminate_handler)
00000000 T __cxa_throweh_term_handler.o:
00000000 D _ZN10__cxxabiv119__terminate_handlerEU _ZN9__gnu_cxx27__verbose_terminate_handlerEv(__gnu_cxx::__verbose_terminate_handler())vterminate.o:
00000000 T _ZN9__gnu_cxx27__verbose_terminate_handlerEvU __cxa_demanglecp-demangle.o:
00006e20 T __cxa_demangleU __sprintf_chk

具体的实现以及调用层次关系可以阅读libsupc++的源代码,位于gcc源代码的libstdc++-v3\libsupc++目录下。

补充说明:

cxxsupp是eCos用来测试C++支持的测试程序,其中使用了new和delete操作符,如果这个测试通不过意味着在应用中不能够使用new和delete操作符。默认情况下new和delete操作符的实现代码由编译器提供,即使是eCos也是如此,除非进行显式地重定义覆盖编译器的默认实现。
除了libsupc++.a之外,根据需要还将链接libgcc.a、libgcc_eh.a,这两个静态包同样是由编译器提供的。

eCos编译Synthethic Target程序时无法解析__sprintf_chk的解决办法相关推荐

  1. VC++ MFC单文档应用程序SDI下调用glGenBuffersARB(1, pbo)方法编译通过但执行时出错原因分析及解决办法:glewInit()初始化的错误...

    1.问题症状 在VC++环境下,利用MFC单文档应用程序SDI下开发OpenGL程序,当调用glGenBuffersARB(1, &pbo)方法编译通过但执行时出错,出错代码如下: OpenG ...

  2. QtCreator 编译时提示 warning C4819 的解决办法

    QtCreator 编译时提示 warning C4819 的解决办法 用 QtCreator 和Visual C++ 编译器编译程序时经常会出现类似的警告: warning C4819: 该文件包含 ...

  3. 台达DOP系列触摸屏上传程序时提示“中止传输数据”怎样解决?

    台达DOP系列触摸屏上传程序时提示"中止传输数据"怎样解决? 如下图所示,在上传HMI程序时,首先会提示我们输入密码, 输入正确的密码后,正常情况下,就可以进行程序画面的上传了. ...

  4. Win7 IIS7.5运行ASP时出现500错误的解决办法

    http 500内部服务器错误说明IIS服务器无法解析ASP代码,下面为大家介绍下Win7 IIS7.5运行ASP时出现500错误的解决办法 http 500内部服务器错误说明IIS服务器无法解析AS ...

  5. 使用 QT 时遇到的问题及解决办法

    使用 QT 时遇到的问题及解决办法 Use multi-arg instead [clazy-qstring-arg] 不要使用一连串的 arg().arg().arg() QString(" ...

  6. mysql update语句卡死_oracle执行update语句时卡住问题分析及解决办法

    问题 开发的时候debug到一条update的sql语句时程序就不动了,然后我就在plsql上试了一下,发现plsql一直在显示正在执行,等了好久也不出结果.但是奇怪的是执行其他的select语句却是 ...

  7. keil MDK cannot access target,shutting down debug session的解决办法

    Erase Full Chip:烧写程序之前擦除整个Flash存储器. Erase Sectors: 烧写程序之前擦除程序要使用的扇区. Do not Erase: 不进行擦除操作 cannot ac ...

  8. 手机安装软件解析包错误解决办法

    下载了一款新的APP,满心欢喜的正准备体验的时候,却发现出现了"解析包时出现问题"之类的提示,连安装都无法成功,这样的体验肯定非常不妙.那么安卓解析包出现问题时有没有好的解决办法呢 ...

  9. nginx alias php,Nginx Alias 无法解析PHP的解决办法

    Nginx Alias 无法解析PHP的解决办法: server { listen       80; server_name  xxxx.com.cn; error_log  /tmp/eror.l ...

最新文章

  1. 身份证号码验证-支持新的带x身份证
  2. python logsumexp示例
  3. netfilter与iptables表规则建立
  4. 避免在ConcurrentHashMap.computeIfAbsent()中进行递归
  5. java 中的流_Java中的流(IO
  6. 全排列及相关扩展算法(七)——组合数的字典序(另含全章代码整理)
  7. mysql innodb 间隙锁_Mysql innodb 间隙锁
  8. 解决sklearn库使用过程中No module named model_selection的错误
  9. .ps是什么格式_用Word修图,真的比PS简单十倍不止!可惜知道的人太少了......
  10. 《论语》全译——孔子生平
  11. win10系统截图快捷键
  12. matlab中contourf函数怎么用_有人可以解释如何使用contourf在MATLAB中绘制这个总和吗?...
  13. Mac使用Homebrew极速安装启动RabbitMQ一把梭
  14. Ubuntu系统迁移至固态硬盘(生产环境勿用)
  15. mysql使用group by查询报错SELECT list is not in GROUP BY clause and contains nonaggregated column.
  16. xpath.extract() 的使用
  17. Java代理模式(Cglib)代理模式
  18. 2022视力矫正展,2022青少年眼睛健康展会,护眼产品展
  19. 神奇的sqrt函数以及高精度记时函数
  20. 作为打工人,普通人努力的意义何在?

热门文章

  1. 蓝桥杯单片机备战(四)共阳数码管的静态显示
  2. Acrobat 删除pdf页面
  3. openstack 网络更改版
  4. 安卓 11 文件储存
  5. “搬砖”机器人两天盖一栋房?泥瓦匠表示很心累
  6. Expeditious Cubing(浮点数处理)
  7. php7 error reporting,php中的error_reporting(7)的含义
  8. 浅谈 Web 3.0
  9. PP实施经验分享(17)——S4 PP与ME标准接口报工函数“CO_MES_PRODORDCONF_CREATE_TT”
  10. 玩转docker之mysql容器(常见问题汇总-续更)