I want to store the called functions addresses or names from the start up of the system to crash of the system. Is there any way to retrieve these function addresses from any hardware register when they called during program execution?
-
2do you mean the [stacktrace](http://en.wikipedia.org/wiki/Stack_trace), if so you can look at http://stackoverflow.com/questions/77005/how-to-generate-a-stacktrace-when-my-gcc-c-app-crashes – Karthik T Jul 02 '13 at 10:05
-
1Which compiler are you using? – alk Jul 02 '13 at 10:06
-
If using gcc this might help: http://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#index-finstrument_002dfunctions-2387 – alk Jul 02 '13 at 10:14
-
Is there a good reason you can't just use a debugger? – Philip Kendall Jul 02 '13 at 10:37
4 Answers
From the gcc documentation:
Generate instrumentation calls for entry and exit to functions. Just after function entry and just before function exit, the following profiling functions are called with the address of the current function and its call site. (On some platforms, __builtin_return_address does not work beyond the current function, so the call site information may not be available to the profiling functions otherwise.)
void __cyg_profile_func_enter (void *this_fn, void *call_site); void __cyg_profile_func_exit (void *this_fn, void *call_site);
Example:
#include <stdio.h>
void __cyg_profile_func_enter(void * this_fn, void * call_site)
{
fprintf(stderr, "enter: %p %p\n", this_fn, call_site);
}
void __cyg_profile_func_exit(void * this_fn, void * call_site)
{
fprintf(stderr, " exit: %p %p\n", this_fn, call_site);
}
void foo(void);
void bar(void);
void foo(void)
{
bar();
return;
}
void bar(void)
{
return;
}
int main(void)
{
bar();
foo();
return 0;
}
Compile and link this using:
gcc -finstrument-functions -finstrument-functions-exclude-function-list=__cyg_profile_func_enter,__cyg_profile_func_exit -Wall -g -o main main.c
The expected output would look similar to this:
enter: 0x400665 0x7fcfedaf6c8d
enter: 0x400643 0x400681
exit: 0x400643 0x400681
enter: 0x40061c 0x400686
enter: 0x400643 0x400633
exit: 0x400643 0x400633
exit: 0x40061c 0x400686
exit: 0x400665 0x7fcfedaf6c8d

- 69,737
- 10
- 105
- 255
-
1
-
Thanks for the answer. Here by doing the instrumentation the extra code will be added in the executable file. Further increasing the size of executable and also increasing the load on system. Is there any other way to do this? – user2542088 Jul 03 '13 at 04:01
-
`addr2line` doesn't work. I copy-pasted this example and I get `??:0` when I do `addr2line -e main -p 0x55858295a230`. I'm using WSL-2 Ubuntu, does that matter? – Bob Apr 10 '23 at 18:47
You can't save the function address from within the function itself and you can't access the function name during the execution but you can save it before invoking the function:
savefptr(myfunction);
savefname("myfunction");
myfunction(a,b,c);
With the appropriate definition of savefptr()
and savefname()
.
If this is done for tracing/debugging (e.g. you want to produce a log to know what's going on in the code) it might be good enoug to trace the file name and line of code using the __FILE__
and __LINE__
macros:
fprintf (stderr, "I'm in:'%s' line %d.",
__FILE__, __LINE__);
I would advice against using compiler or OS specifics if can avoid them.

- 16,122
- 6
- 43
- 74
I ONLY did some similar work under *nix system, therefore I provide my solution for you base on *nix.
I assumed you use gcc
as your default compiler, and then you'd better enable both -finstrument-functions
and -fdump-rtl-expand
in your makefile, for example:
CFLAGS += -Wall -O -ggdb -Wstrict-prototypes -Wno-pointer-sign -finstrument-functions -fdump-rtl-expand
After this, you can implement the trace function, for example, your_trace.c:
#include <stdio.h>
#include <stdlib.h>
/* Function prototypes with attributes */
void main_constructor( void )
__attribute__ ((no_instrument_function, constructor));
void main_destructor( void )
__attribute__ ((no_instrument_function, destructor));
void __cyg_profile_func_enter( void *, void * )
__attribute__ ((no_instrument_function));
void __cyg_profile_func_exit( void *, void * )
__attribute__ ((no_instrument_function));
static FILE *fp;
void main_constructor( void )
{
fp = fopen( "trace.txt", "w" );
if (fp == NULL) exit(-1);
}
void main_deconstructor( void )
{
fclose( fp );
}
void __cyg_profile_func_enter( void *this, void *callsite )
{
fprintf(fp, "E%p\n", (int *)this);
}
void __cyg_profile_func_exit( void *this, void *callsite )
{
fprintf(fp, "X%p\n", (int *)this);
}
After these, after compile your code, you will see a *.map file, which contain function information. Also compiled with trace.c, and if simply run you output file after compile, and it will generate function call information, namely, trace.txt
file, it has function address, you can use add2line
to see each of them or you can use pvtrace
tool to get the function call with trace.txt
, for example, my compiled program named DEMO
, then:
-> pvtrace ./DEMO
You will get graph.dot
and it recorded your run time function call.
OR
use just enable -ggdb
and use debug tool to see each function address, like DDD
or GDB
.

- 1,340
- 2
- 17
- 37
-
Thanks for the answer. Here by doing the instrumentation the extra code will be added in the executable file. Further increasing the size of executable and also increasing the load on system. Is there any other way to do this? – user2542088 Jul 03 '13 at 04:02
-
@user2542088, I think you can add flag like `-DDEBUG` or `-DRELEASE` to seperate you target file, in debug version you will enable this feature, but for release verion, you disable this feature – How Chen Jul 05 '13 at 07:03