Reputation: 3160
In a bare metal C/C++ project, I use gcc-arm-embedded (currently the most recent 4.9-2015-q2).
For some reasons, I have to avoid using some functions, like some of stdio et cetera (don't want to use retargeting or semihosting).
Further, I use FreeRtos with heap_4.c and had e.g. malloc()
redirected directly to pvPortMalloc()
like this:
void* malloc(size_t s) {
return pvPortMalloc(s);
}
Therefore, I don't want to have any parts of the toolchain's heap management code within my binary.
Now, there are some situations, as were a developer of my team means to use e.g. printf()
which indirectly references _malloc_r()
(and some more) and it's actually quite hard to find out where it's referenced from and so where to fix.
(The use printf()
is just an example here. In my project, I have custom implementation of printf() which prints directly to uart without using stdio. But there are other cases, e.g. type info demangeling, …)
Currently, I have the situation that my project (which consists of about 200 c and c++ source files) compiles well without referencing _malloc_r()
in any way - as long as I build with gcc 4.8.
But when building with gcc 4.9, I see unwanted references to _malloc_r
and some more.
Might there be command line tool to analyze my elf file for finding out where specific functions are referenced from?
Edit 2015-07-20:
_malloc_r
inside of my code.Further I find out, that there is a __gnu_cxx::__snprintf_lite()
which references the full blown of iostream
which I don't want in my code. This __gnu_cxx::__snprintf_lite()
is used by some exceptions of the gcc
stl
implementation (e.g. referenced by __throw_out_of_range_fmt()
). (Yep, my code uses std::map
). My way to get rid of iostream
was to simply provide my own __gnu_cxx::__snprintf_lite()
like this (having my own small footprint vsnprintf
):
namespace __gnu_cxx {
int __snprintf_lite(char* buf, size_t bufsize, const char* fmt, va_list ap) {
return vsnprintf(buf, bufsize, fmt, ap);
}
}
This can be checked by viewing the gcc-4.9 library sources (e.g. src/gcc/libstdc++-v3/src/c++11/snprintf_lite.cc
).
Upvotes: 3
Views: 1506
Reputation: 2499
This is an example for finding out the references to _exit
in a statically compiled program:
/* hello.c */
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
write(1, "Hello\n", 6);
_exit(0);
}
Compile it:
$ gcc hello.c -static -g
Find out the address of _exit
:
$ nm a.out | grep " _exit"
000000000040f760 T _exit
Disassemble with objdump -d -j .text
, grep
for the address of _exit
, cut
the address out of the line and pipe it to 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
??:?
The result is:
Functions oom
, main
, __run_exit_handlers
, ... do reference the function _exit
.
Upvotes: 3
Reputation: 5112
Peraphs using a custom malloc.h where you can undef or redefine _malloc_r
Something similar to:
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
Take a look to Hooks-for-Malloc too
The GNU C Library lets you modify the behavior of malloc, realloc, and free by specifying appropriate hook functions. You can use these hooks to help you debug programs that use dynamic memory allocation, for example.
The hook variables are declared in malloc.h.
Another hint is using LD_PRELOAD What is the LD_PRELOAD trick?
Upvotes: 2
Reputation: 6221
I am not sure, whether I understood you correctly, but it seems you want to avoid using some specific functions in your project. How about simply poisoning the function identifiers?
This code fails to compile (intentionally) for printf
:
#define printf FORBIDDEN
int main(int argc, char *argv[]) {
printf("Test");
}
with the following error:
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
^~~~~~~~~
So the order of declaration and redefinition does not matter. You do not need to know all functions that call forbidden functions:
#define printf FORBIDDEN
// this in included file:
void otherfunc() {
printf("I fail.");
}
// eof included file
int main(int argc, char *argv[]) {
otherfunc();
}
Upvotes: 2