2 gcc -o itrace.so -shared -fPIC -Wall -ggdb2 itrace.c -ldw
8 #include <elfutils/libdwfl.h>
14 #define PREFIX "itrace: "
20 static char *debuginfo_path;
23 static const Dwfl_Callbacks proc_callbacks =
25 .find_debuginfo = dwfl_standard_find_debuginfo,
26 .debuginfo_path = &debuginfo_path,
28 .find_elf = dwfl_linux_proc_find_elf,
33 dwfl = dwfl_begin (&proc_callbacks);
34 assert (dwfl != NULL);
37 if (dwfl_linux_proc_report (dwfl, getpid ()) != 0
38 || dwfl_report_end (dwfl, NULL, NULL) != 0)
40 fprintf (stderr, "dwfl reporting: %m\n");
49 struct getmodules_callback_arg
55 static int getmodules_callback (Dwfl_Module *module,
56 void **module_userdata_pointer,
57 const char *module_name,
58 Dwarf_Addr module_low_addr, void *arg_voidp)
60 struct getmodules_callback_arg *arg = arg_voidp;
62 arg->name = dwfl_module_addrname (module, (GElf_Addr) arg->addr);
63 return arg->name ? DWARF_CB_ABORT : DWARF_CB_OK;
67 addr_lookup (void *addr)
69 Dwfl *dwfl = dwfl_get ();
70 struct getmodules_callback_arg arg;
74 dwfl_getmodules (dwfl, getmodules_callback, &arg, 0);
80 addr_print (void *addr)
84 name = addr_lookup (addr);
89 sprintf (buf, "%p", addr);
100 static struct stack *stack;
101 static unsigned stack_at, stack_size;
103 void __cyg_profile_func_enter (void *this_fn, void *call_site)
107 if (stack_at == stack_size)
109 unsigned size_new = stack_size ? stack_size * 2 : 0x100;
110 struct stack *stack_new;
112 stack_new = realloc (stack, sizeof (*stack) * size_new);
115 fprintf (stderr, PREFIX "stack size %u allocation failure!\n",
120 stack_size = size_new;
122 stack[stack_at].this_fn = this_fn;
123 stack[stack_at].call_site = call_site;
126 indent = stack_at - 1 <= INDENT_MAX ? stack_at - 1 : INDENT_MAX;
128 fprintf (stderr, PREFIX "%*s->%s", indent, "", addr_print (this_fn));
129 fprintf (stderr, " (%s)\n", addr_print (call_site));
132 void __cyg_profile_func_exit (void *this_fn, void *call_site)
136 indent = stack_at - 1 <= INDENT_MAX ? stack_at - 1 : INDENT_MAX;
138 fprintf (stderr, PREFIX "%*s<-%s", indent, "", addr_print (this_fn));
139 fprintf (stderr, " (%s)\n", addr_print (call_site));
143 fprintf (stderr, PREFIX "stack empty!\n");
146 if (stack[stack_at - 1].this_fn != this_fn
147 || stack[stack_at - 1].call_site != call_site)
149 fprintf (stderr, PREFIX "Unexpected function leave, resetting the stack\n");