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 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
|
#! /usr/bin/env stap
// configuration options
global follow_fork = 0 // -Gfollow_fork=1 means trace descendant processes too
global count = 0 // -Gcount=1 means summarize time and calls for each library call */
global report_line%
global report_line_returnval%
global func_time%
global func_time_total%
global func_calls%
global calls_nonreturn
probe begin
{
// list of calls that never .return
calls_nonreturn["__libc_start_main"]=1
}
function filter_p()
{
// from strace.stp
if (target() == 0) return 0;
if (!follow_fork && pid() != target()) return 1;
if (follow_fork && !target_set_pid(pid())) return 1;
return 0;
}
function arg:string (arg1:long) {
if (arg1 < 255)
return sprintf("%d", arg1)
else
return sprintf("%#lx", arg1)
}
function report (rl)
{
printf("%s", report_line[rl])
rll = strlen(report_line[rl])
n_tabs = ((64 - rll) / 8)
if (rll % 8 == 0)
n_tabs -= 1
if (rll <= 64)
for (i=0; i < n_tabs; i++)
{
printf("\t")
}
}
probe process.plt, process.library("*").plt
{
if (filter_p()) next;
if (strlen($$name) == 0) next;
if ($$name in calls_nonreturn)
next
if (count) // -Gcount=1
{
func_calls[$$name] <<< 1
func_time[$$name]=gettimeofday_us()
next
}
%( arch == "x86_64" %?
outline = sprintf("%s (%s, %s, %s, %s)", $$name, arg(register("rdi")), arg(register("rsi")), arg(register("rdx")), arg(register("rcx")))
%)
%( arch == "i386" %?
outline = sprintf("%s[%d] %s (%s, %s, %s, %s)", execname(), tid(), $$name, arg(register("edi")), arg(register("esi")), arg(register("edx")), arg(register("ecx")))
%)
report_line[$$name] = outline
}
probe process.plt.return, process.library("*").plt.return
{
if (filter_p()) next;
if (strlen($$name) == 0) next;
// cache cumulative time spent in each call
if (count)
{
now = gettimeofday_us()
then = func_time[$$name]
func_time_total[$$name] += now-then
delete func_time[$$name]
next
}
report_line_returnval[$$name] = arg(retval)
foreach (rl in report_line) {
first_key = rl
break
}
// if we have nested calls then wait for the return of the first call
if ($$name == first_key)
{
foreach (rl in report_line)
{
report (rl)
printf ("=%s\n", report_line_returnval[rl])
}
delete report_line
delete report_line_returnval
}
}
probe end
{
if (count)
{
cumulative_time = 0
printf ("%% time seconds calls\n")
printf ( "------ --------- -------\n")
foreach (ttt in func_time_total)
{
cumulative_time += func_time_total[ttt]
}
foreach (ttt in func_time_total)
{
percent = (func_time_total[ttt] * 100) / cumulative_time
if (percent > 0)
{
printf("%5d%% ", percent)
printf("%14d ", func_time_total[ttt]%1000000)
printf("%10d ", @count(func_calls[ttt]))
printf(" %s\n",ttt)
}
}
}
}
|