]> The Tcpdump Group git mirrors - tcpdump/blob - instrument-functions.c
autoconf: Add the option to print functions names (entry and exit)
[tcpdump] / instrument-functions.c
1 /*
2 * Redistribution and use in source and binary forms, with or without
3 * modification, are permitted provided that: (1) source code
4 * distributions retain the above copyright notice and this paragraph
5 * in its entirety, and (2) distributions including binary code include
6 * the above copyright notice and this paragraph in its entirety in
7 * the documentation or other materials provided with the distribution.
8 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
9 * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
10 * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
11 * FOR A PARTICULAR PURPOSE.
12 */
13
14 #ifndef _GNU_SOURCE
15 #define _GNU_SOURCE
16 #endif
17
18 #include <stdio.h>
19 #include <dlfcn.h>
20
21 extern int profile_func_level;
22 int profile_func_level = -1;
23
24 /*
25 * Generate instrumentation calls for entry and exit to functions.
26 * Just after function entry and just before function exit, the
27 * following profiling functions are called with the address of the
28 * current function and its call site (currently not use).
29 *
30 * The attribute 'no_instrument_function' causes this instrumentation is
31 * not done.
32 *
33 * These profiling functions print the function names with indentation
34 * and call level.
35 *
36 * To instument a static function, remove temporarily the static specifier.
37 */
38
39 void __cyg_profile_func_enter(void *this_fn, void *call_site)
40 __attribute__((no_instrument_function));
41
42 void __cyg_profile_func_exit(void *this_fn, void *call_site)
43 __attribute__((no_instrument_function));
44
45 /*
46 * The get_function_name() get the function name by calling dladdr()
47 */
48
49 static const char *get_function_name(void *func)
50 __attribute__((no_instrument_function));
51
52 static const char *
53 get_function_name(void *func)
54 {
55 Dl_info info;
56 const char *function_name;
57
58 if(dladdr(func, &info))
59 function_name = info.dli_sname;
60 else
61 function_name = NULL;
62 return function_name;
63 }
64
65 void
66 __cyg_profile_func_enter(void *this_fn,
67 void *call_site __attribute__((unused)))
68 {
69 int i;
70 const char *function_name;
71
72 if((function_name = get_function_name(this_fn)) != NULL) {
73 profile_func_level += 1;
74 for (i = 0 ; i < profile_func_level ; i++)
75 putchar(' ');
76 printf("[>> %s (%d)]\n", function_name, profile_func_level);
77 }
78 fflush(stdout);
79 }
80
81 void
82 __cyg_profile_func_exit(void *this_fn,
83 void *call_site __attribute__((unused)))
84 {
85 int i;
86 const char *function_name;
87
88 if((function_name = get_function_name(this_fn)) != NULL) {
89 for (i = 0 ; i < profile_func_level ; i++)
90 putchar(' ');
91 printf ("[<< %s (%d)]\n", function_name, profile_func_level);
92 profile_func_level -= 1;
93 }
94 fflush(stdout);
95 }