在一个裸金属C/C++项目中,我使用嵌入式gcc arm(目前是最新的4.9-2015-q2)。
出于某些原因,我不得不避免使用一些函数,比如stdio等函数(不想使用重定目标或半托管)。
此外,我将FreeRtos与heap_4.c一起使用,并将例如malloc()
直接重定向到pvPortMalloc()
,如下所示:
void* malloc(size_t s) {
return pvPortMalloc(s);
}
因此,我不希望在二进制文件中包含工具链堆管理代码的任何部分。
现在,有一些情况,因为我的团队的开发人员打算使用例如printf()
,它间接引用_malloc_r()
(以及更多),实际上很难找到它是从哪里引用的,也很难找到修复的地方。
(使用printf()
只是一个例子。在我的项目中,我有printf()的自定义实现,它直接打印到uart,而不使用stdio。但也有其他情况,例如类型信息去映射,…)
目前,我的项目(由大约200个c和c++源文件组成)编译得很好,没有以任何方式引用_malloc_r()
——只要我使用gcc 4.8构建。
但是,当使用gcc 4.9进行构建时,我看到了对_malloc_r
和更多内容的不必要引用。
可能有命令行工具来分析我的elf文件,以找出特定函数的引用来源吗?
编辑2015-07-20:
- 最后,我解决了我的根本问题,即我需要使用gcc 4.9构建我的整个项目,而不需要在代码中引用
_malloc_r
- 我通过应用这个答案找到的一些参考资料
此外,我发现有一个
__gnu_cxx::__snprintf_lite()
引用了iostream
的完整版本,我不希望在我的代码中使用它。该__gnu_cxx::__snprintf_lite()
由gcc
stl
实现的一些例外使用(例如由__throw_out_of_range_fmt()
引用)。(是的,我的代码使用std::map
)。我摆脱iostream
的方法是简单地提供我自己的__gnu_cxx::__snprintf_lite()
,如下所示(有我自己的小占地面积vsnprintf
):namespace __gnu_cxx { int __snprintf_lite(char* buf, size_t bufsize, const char* fmt, va_list ap) { return vsnprintf(buf, bufsize, fmt, ap); } }
这可以通过查看gcc-4.9库源(例如
src/gcc/libstdc++-v3/src/c++11/snprintf_lite.cc
)进行检查。
这是一个在静态编译程序中查找_exit
引用的示例:
/* hello.c */
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
write(1, "Hellon", 6);
_exit(0);
}
编译:
$ gcc hello.c -static -g
查找_exit
:的地址
$ nm a.out | grep " _exit"
000000000040f760 T _exit
用objdump -d -j .text
拆下,grep
拆下_exit
的地址,cut
拆下线路外的地址,用管道传输到addr2line
:
$ objdump -d -j .text a.out | grep 40f760 | cut -c 1-8 | addr2line -e a.out -f
oom
dl-tls.o:?
main
/home/m/hello.c:8
__run_exit_handlers
??:?
??
??:0
_Exit
??:?
_dl_non_dynamic_init
??:?
abort
??:?
do_lookup_x
dl-lookup.o:?
_dl_relocate_object
??:?
_dl_signal_error
??:?
dl_open_worker
dl-open.o:?
_dl_close_worker.part.0
dl-close.o:?
_dl_start_profile
??:?
结果是:
函数oom
、main
、__run_exit_handlers
。。。请参考函数CCD_ 30。
我不确定我是否正确理解了你,但你似乎想避免在项目中使用一些特定的函数。不如简单地毒害函数标识符?
此代码无法(故意)为printf
:编译
#define printf FORBIDDEN
int main(int argc, char *argv[]) {
printf("Test");
}
出现以下错误:
Untitled.cpp:11:3: error: no matching function for call to 'FORBIDDEN'
printf("Test");
^~~~~~
Untitled.cpp:3:16: note: expanded from macro 'printf'
#define printf FORBIDDEN
^~~~~~~~~
因此,声明和重新定义的顺序并不重要。您不需要知道所有调用禁用函数的函数:
#define printf FORBIDDEN
// this in included file:
void otherfunc() {
printf("I fail.");
}
// eof included file
int main(int argc, char *argv[]) {
otherfunc();
}
使用自定义malloc.h的Peraphs,您可以在其中取消定义或重新定义_malloc_r
类似于:
extern _PTR malloc _PARAMS ((size_t));
#ifdef __CYGWIN__
#undef _malloc_r
#define _malloc_r(r, s) malloc (s)
#else
extern _PTR _malloc_r _PARAMS ((struct _reent *, size_t));
#endif
看看挂钩马洛克太
GNU C库允许您修改malloc、realloc和通过指定适当的钩子函数来释放。你可以用这些钩子为了帮助您调试使用动态内存分配的程序实例
钩子变量在malloc.h中声明。
另一个提示是使用LD_PRELOAD LD_PRELLOAD技巧是什么?