'gcc'에 해당되는 글 1건

  1. 2013.08.28 GCC, instrument function
카테고리 없음2013. 8. 28. 16:15




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
/*
    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는 생략해도 된다.

결과는,


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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 $


또 다른 예제.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
/*
    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;
}

결과는,


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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의 내용은,



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#!/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}"



Posted by 쿨한넘