Joe
Joe

Reputation: 3160

How to check where a function is referenced from

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:

Upvotes: 3

Views: 1506

Answers (3)

4566976
4566976

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

frhack
frhack

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

Kuba Wyrostek
Kuba Wyrostek

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

Related Questions