Reputation: 1
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?
Upvotes: 1
Views: 1007
Reputation: 1370
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
.
Upvotes: 0
Reputation: 70921
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
Upvotes: 2
Reputation: 16512
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.
Upvotes: 0