File: ltrace.stp

package info (click to toggle)
systemtap 4.4-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 38,260 kB
  • sloc: cpp: 77,147; ansic: 61,828; xml: 49,277; exp: 42,244; sh: 11,046; python: 2,772; perl: 2,252; tcl: 1,305; makefile: 1,086; lisp: 105; java: 102; awk: 101; asm: 91; sed: 16
file content (138 lines) | stat: -rwxr-xr-x 3,012 bytes parent folder | download | duplicates (5)
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)
	  }
      }
    }
}