/*
test.c
2013. 8. 28.
*/
#include <stdio.h>
#include <stdlib.h>
__attribute__ ((no_instrument_function))
void __cyg_profile_func_enter(void *this, void *callsite)
{
printf ("__cyg_profile_func_enter\n");
}
__attribute__ ((no_instrument_function))
void __cyg_profile_func_exit(void *this, void *callsite)
{
printf ("__cyg_profile_func_exit\n");
}
__attribute__ ((constructor))
void myConstructor( void )
{
printf ("constructor\n");
}
__attribute__ ((destructor))
void myDestructor( void )
{
printf ("destuctor!\n");
}
void func_a( void )
{
printf ("func_a\n");
return;
}
__attribute__ ((no_instrument_function))
void func_b( void )
{
printf ("func_b\n");
return;
}
int main()
{
printf ("main\n");
func_a();
func_b();
return 0;
}
constructor, destructor는 생략해도 된다.
결과는,
dqxt@dons-pleiades ~/study/kernel/instrument_fn $ gcc -o test -finstrument-functions test.c dqxt@dons-pleiades ~/study/kernel/instrument_fn $ ./test __cyg_profile_func_enter constructor __cyg_profile_func_exit __cyg_profile_func_enter main __cyg_profile_func_enter func_a __cyg_profile_func_exit func_b __cyg_profile_func_exit __cyg_profile_func_enter destuctor! __cyg_profile_func_exit dqxt@dons-pleiades ~/study/kernel/instrument_fn $
또 다른 예제.
/*
test2.c
2013. 8. 28.
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
static FILE *fp_trace;
__attribute__ ((constructor))
void trace_begin (void)
{
printf ("constructor.\n");
fp_trace = fopen("trace.out", "w");
}
__attribute__ ((destructor))
void trace_end (void)
{
printf ("destructor.\n");
if (fp_trace != NULL) {
fclose(fp_trace);
}
}
__attribute__ ((no_instrument_function))
void __cyg_profile_func_enter (void *func, void *caller)
{
printf ("__cyg_profile_func_enter.\n");
if (fp_trace != NULL) {
fprintf(fp_trace, "e %p %p %lu\n", func, caller, time(NULL) );
}
}
__attribute__ ((no_instrument_function))
void __cyg_profile_func_exit (void *func, void *caller)
{
printf ("__cyg_profile_func_exit.\n");
if(fp_trace != NULL) {
fprintf(fp_trace, "x %p %p %lu\n", func, caller, time(NULL));
}
}
void func_a( void )
{
printf ("in function_a.\n");
return;
}
__attribute__ ((no_instrument_function))
void func_b( void )
{
printf ("in function_b.\n");
return;
}
int main()
{
printf ("in main.\n");
func_a();
func_b();
return 0;
}
결과는,
dqxt@dons-pleiades ~/study/kernel/instrument_fn $ gcc -o test2 -finstrument-functions test2.c dqxt@dons-pleiades ~/study/kernel/instrument_fn $ ./test2 __cyg_profile_func_enter. constructor. __cyg_profile_func_exit. __cyg_profile_func_enter. in main. __cyg_profile_func_enter. in function_a. __cyg_profile_func_exit. in function_b. __cyg_profile_func_exit. __cyg_profile_func_enter. destructor. __cyg_profile_func_exit. dqxt@dons-pleiades ~/study/kernel/instrument_fn $ ./readtracelog.sh test2 trace.out Exit trace_begin at 2013-08-28T16:12:39+0900 Enter main at 2013-08-28T16:12:39+0900, called from ?? (??:0) Enter func_a at 2013-08-28T16:12:39+0900, called from main (??:?) Exit func_a at 2013-08-28T16:12:39+0900 Exit main at 2013-08-28T16:12:39+0900 Enter trace_end at 2013-08-28T16:12:39+0900, called from ?? (??:0) dqxt@dons-pleiades ~/study/kernel/instrument_fn $
readtracelog.sh의 내용은,
#!/bin/sh
if test ! -f "$1"
then
echo "Error: executable $1 does not exist."
exit 1
fi
if test ! -f "$2"
then
echo "Error: trace log $2 does not exist."
exit 1
fi
EXECUTABLE="$1"
TRACELOG="$2"
while read LINETYPE FADDR CADDR CTIME; do
FNAME="$(addr2line -f -e ${EXECUTABLE} ${FADDR}|head -1)"
CDATE="$(date -Iseconds -d @${CTIME})"
if test "${LINETYPE}" = "e"
then
CNAME="$(addr2line -f -e ${EXECUTABLE} ${CADDR}|head -1)"
CLINE="$(addr2line -s -e ${EXECUTABLE} ${CADDR})"
echo "Enter ${FNAME} at ${CDATE}, called from ${CNAME} (${CLINE})"
fi
if test "${LINETYPE}" = "x"
then
echo "Exit ${FNAME} at ${CDATE}"
fi
done < "${TRACELOG}"
