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
|
/*
* current.stp (requires Guru mode)
*
* Test the validity of the current pointer in various contexts.
*/
global length
function commlen:long () %{
THIS->__retvalue = strlen(current->comm);
%}
function pcommlen:long () %{
THIS->__retvalue = strlen(current->parent->comm);
%}
probe begin { println("systemtap starting probe") }
probe
timer.profile,
%( arch != "ia64" %?
# __switch_to is macro definition in ia64,
# and ia64_switch_to is defined in assemble language
%( arch != "x86_64" %?
# __switch_to can not be probed on x86_64 - see PR2068
kernel.function("__switch_to").call,
%( arch != "i386" %?
# __switch_to.return is broken on i686 - see PR4542
kernel.function("__switch_to").return,
%)
%)
%)
/* XXX
* It would be nice if we could just do this:
* kernel.statement("__switch_to@*:*")
* to probe every line in the function
*/
/* add other kernels/archs here as desired... */
%( arch == "x86_64" %?
%( kernel_vr == "2.6.9-22.ELsmp" %?
/* the lines before, at, and after the update of pcurrent */
kernel.statement("__switch_to@arch/x86_64/kernel/process.c:508"),
kernel.statement("__switch_to@arch/x86_64/kernel/process.c:509"),
kernel.statement("__switch_to@arch/x86_64/kernel/process.c:510"),
%)
%( kernel_vr == "2.6.9-24.ELsmp" %?
/* the lines before, at, and after the update of pcurrent */
kernel.statement("__switch_to@arch/x86_64/kernel/process.c:501"),
kernel.statement("__switch_to@arch/x86_64/kernel/process.c:502"),
kernel.statement("__switch_to@arch/x86_64/kernel/process.c:503"),
%)
%)
kernel.function("*@kernel/sched.c").call,
kernel.function("*@kernel/sched.c").return,
module("*").function("*interrupt*").call ?,
module("*").function("*interrupt*").return ?
{
length <<< commlen()
length <<< pcommlen()
}
function get_TASK_COMM_LEN:long() %{
/* TASK_COMM_LEN was introduced in 2.6.11, before which
* the length of the comm string was hard-coded to 16 */
#ifdef TASK_COMM_LEN
THIS->__retvalue = TASK_COMM_LEN;
#else
THIS->__retvalue = 16;
#endif
%}
probe end {
println("systemtap ending probe")
printf("count = %d\n", @count(length))
printf("sum = %d\n", @sum(length))
printf("min = %d\n", @min(length))
printf("max = %d\n", @max(length))
printf("avg = %d\n", @avg(length))
/*
* Check that the min & max lengths look reasonable. If any string was
* either empty or too big, then the current pointer probably wasn't
* valid, even though it dereferenced without crashing.
*/
if (@min(length) > 0) {
println("systemtap test success")
} else {
println("unexpected minimum length")
println("systemtap test failure")
}
if (@max(length) < get_TASK_COMM_LEN()) {
println("systemtap test success")
} else {
println("unexpected maximum length")
println("systemtap test failure")
}
}
|