日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

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

發布時間:2024/1/8 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 eCos编译Synthethic Target程序时无法解析__sprintf_chk的解决办法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

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的解决办法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。