File: macro

package info (click to toggle)
bpftrace 0.24.1-1.1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 10,496 kB
  • sloc: cpp: 60,982; ansic: 10,952; python: 953; yacc: 665; sh: 536; lex: 295; makefile: 22
file content (188 lines) | stat: -rw-r--r-- 7,325 bytes parent folder | download
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
NAME it mutates the passed variable
PROG macro inc($x) { $x += 1; } begin { $a = 1; inc($a); print($a);  }
EXPECT 2

NAME it assigns to the last expression
PROG macro inc($x) { $x += 1; $x } begin { $a = 1; $b = inc($a); print(($a, $b));  }
EXPECT (2, 2)

NAME it mutates the passed non-scalar map
PROG macro set(@x) { @x[1] = 2; } begin { @a[1] = 1; set(@a);  }
EXPECT @a[1]: 2

NAME it mutates the passed scalar map
PROG macro set(@x) { @x = 2; } begin { @a = 1; set(@a);  }
EXPECT @a: 2

NAME it renames internal variables
PROG macro add(x) { let $y; if (true) { $y = 1 } x + $y  } begin { print(add(1));  }
EXPECT 2

NAME it reads the passed map
PROG macro get(@x) { 1 + @x[1] } begin { @a[1] = 1; print(get(@a));  }
EXPECT 2

NAME it can have side effects
PROG macro print_me($x) { print(("me", $x)); } begin { $a = 1; print_me($a);  }
EXPECT (me, 1)

NAME it can exit early
PROG macro early() { exit(); } begin { early(); print(1); }
EXPECT_NONE 1

NAME it can call other macros as expressions
PROG macro add1(x) { x + 1 } macro add2(y) { y + add1(y) } macro add3(z) { z + add2(z) } begin { print(add3(1));  }
EXPECT 4

NAME it can call other macros as statements
PROG macro add1($x) { $x += 1; } macro add2($y) { add1($y); $y += 1; } macro add3($z) { add2($z); $z += 1; } begin { $a = 1; add3($a); print($a);  }
EXPECT 4

NAME builtin wrapper definition order does not matter
PROG macro add2(x) { x + add1(x) } macro add3(x) { x + add2(x) } macro add1(x) { x + 1 } begin { print(add3(1));  }
EXPECT 4

NAME it accepts arbitrary expressions without variables or maps
PROG macro add_one(x) { x + 1 } begin { $a = 1; print(add_one(1 + 1));  }
EXPECT 3

NAME it accepts arbitrary expressions with variables
PROG macro add_one(x) { x + 1 } begin { $a = 1; print(add_one($a + 1));  }
EXPECT 3

NAME it accepts arbitrary expressions with variables nested
PROG macro add_two(x) { x + 2 } macro add_one(x) { add_two(x + 1) + 1 } begin { $a = 1; print(add_one($a + 1));  }
EXPECT 6

NAME it accepts arbitrary expressions with maps
PROG macro add_one(x) { x + 1 } begin { @a = 1; print(add_one(@a + 1));  }
EXPECT 3

NAME can call the same macro multiple times
PROG macro inc($x) { $x += 1; } begin { $a = 1; inc($a); inc($a); inc($a); print($a);  }
EXPECT 4

NAME for loops can be in macros
PROG macro loop_map(@a) { let $x = 1; for ($kv : @a) { $x += $kv.1;} $x } begin { @x[1] = 5; @x[2] = 10; print(loop_map(@x));  }
EXPECT 16

NAME it works in nested scopes
PROG macro add1($x) { $x + 1 } macro add2($x) { $x + 2 } begin { $a = 1; if ($a == 1) { print(add2($a)); } else { print(add1($a)); }  }
EXPECT 3

NAME it re-names variables to prevent collision
PROG macro inc(x) { $y = x + 1; $y } begin { $y = 2; $z = inc(5); print(($y, $z));  }
EXPECT (2, 6)

NAME it re-names decl variables to prevent collision
PROG macro inc(x) { let $y = x + 1; $y } begin { $y = 2; $z = inc(5); print(($y, $z));  }
EXPECT (2, 6)

NAME it can be part of an expression passed to a macro
PROG macro add_one(x) { x + 1 } begin { $a = add_one(add_one(1) + 1); print($a);  }
EXPECT 4

NAME it expands idents if there is a matching macro
PROG macro one() { $x = 1; $x } begin { $a = one; print($a);  }
EXPECT 1

NAME it replaces the passed in expression in multiple expression locations
PROG macro inc(x) { $y = x + 1; $z = x + 2; $y + $z } begin { $y = 2; print(inc({ $y +=1; $y })); }
EXPECT 10

NAME it replaces the passed in expression in multiple expression statement locations
PROG macro side_effects(x) { x; x; x; } begin { side_effects({ printf("hi") }); }
EXPECT hihihi

NAME the same macro can be called multiple times in a passed expression
PROG macro add_one(x) { x + 1 } begin { print(add_one(add_one(add_one(1)))); }
EXPECT 4

NAME macro arg idents take precedence over macros with no arguments
PROG macro add() { 2 } macro ident(add) { add } begin { print(ident(1)); }
EXPECT 1

# This is more of a regression test for clone that wasn't cloning the Iterable node
NAME macro replaces all instances
PROG macro first_key(@x) { let $x; for ($k : @x) { $x = $k.0; break; } $x } begin { @a[1] = 0; @b[2] = 0; print((first_key(@a), first_key(@b))); }
EXPECT (1, 2)

# Test builtins
NAME builtin wrapper comm
PROG begin { if (__builtin_comm == comm() && __builtin_comm == comm) { print(comm); } }
EXPECT bpftrace

NAME builtin wrapper cgroup
PROG begin { if (__builtin_cgroup == cgroup() && __builtin_cgroup == cgroup) { printf("SUCCESS %llu\n", cgroup); } }
EXPECT_REGEX SUCCESS [0-9]+

NAME builtin wrapper cpid
RUN {{BPFTRACE}} -e 'begin { if (__builtin_cpid == cpid() && __builtin_cpid == cpid) { printf("SUCCESS %llu\n", cpid); } }' -c './testprogs/syscall nanosleep 1e9'
EXPECT_REGEX SUCCESS [0-9]+
TIMEOUT 3

NAME builtin wrapper cpu
PROG begin { if (__builtin_cpu == cpu() && __builtin_cpu == cpu) { printf("SUCCESS %llu\n", cpu); } }
EXPECT_REGEX SUCCESS [0-9]+

NAME builtin wrapper curtask
PROG begin { if (__builtin_curtask == curtask() && __builtin_curtask == curtask) { printf("SUCCESS %llu\n", curtask); } }
EXPECT_REGEX SUCCESS [0-9]+

NAME builtin wrapper elapsed
PROG begin { printf("SUCCESS1 %llu\n", __builtin_elapsed); printf("SUCCESS2 %llu\n", elapsed); printf("SUCCESS3 %llu\n", elapsed()); }
EXPECT_REGEX SUCCESS1 [0-9]+
EXPECT_REGEX SUCCESS2 [0-9]+
EXPECT_REGEX SUCCESS3 [0-9]+

NAME builtin wrapper func
PROG k:vfs_read { if (__builtin_func == func() && __builtin_func == func) { print(func); } exit(); }
EXPECT vfs_read
AFTER ./testprogs/syscall read

NAME builtin wrapper gid
PROG begin { if (__builtin_gid == gid() && __builtin_gid == gid) { print(gid); } }
EXPECT_REGEX [0-9][0-9]*

NAME builtin wrapper jiffies
PROG begin { if (__builtin_jiffies == jiffies() && __builtin_jiffies == jiffies) { printf("SUCCESS %llu\n", jiffies);} }
EXPECT_REGEX SUCCESS [0-9]+
REQUIRES_FEATURE jiffies64
MIN_KERNEL 5.9

NAME builtin wrapper ncpus
PROG begin { if (__builtin_ncpus == ncpus() && __builtin_ncpus == ncpus) { print(ncpus); } }
EXPECT_REGEX ^[1-9][0-9]*$

NAME builtin wrapper numaid
PROG begin { if (__builtin_numaid == numaid() && __builtin_numaid == numaid) { printf("SUCCESS %d\n", numaid); } }
EXPECT_REGEX SUCCESS [0-9]+

NAME builtin wrapper probe
PROG k:do_nanosleep { if (__builtin_probe == probe() && __builtin_probe == probe) { print(probe); } exit(); }
EXPECT kprobe:do_nanosleep
AFTER ./testprogs/syscall nanosleep 1e8

NAME builtin wrapper rand
PROG begin { printf("SUCCESS1 %llu\n", __builtin_rand); printf("SUCCESS2 %llu\n", rand); printf("SUCCESS3 %llu\n", rand()); }
EXPECT_REGEX SUCCESS1 [0-9]+
EXPECT_REGEX SUCCESS2 [0-9]+
EXPECT_REGEX SUCCESS3 [0-9]+

NAME builtin wrapper retval
PROG kretprobe:vfs_read { if (__builtin_retval == retval() && __builtin_retval == retval) { printf("SUCCESS %d\n", retval); exit(); } }
EXPECT_REGEX SUCCESS .*
AFTER ./testprogs/syscall read

NAME builtin wrapper uid
PROG begin { if (__builtin_uid == uid() && __builtin_uid == uid) { printf("SUCCESS %d\n", uid); } }
EXPECT_REGEX SUCCESS [0-9]+

NAME builtin wrapper usermode
PROG begin { if (__builtin_usermode == usermode() && __builtin_usermode == usermode) { printf("SUCCESS %d\n", usermode); } }
EXPECT_REGEX SUCCESS 1
ARCH x86_64

NAME builtin wrapper username
PROG begin { if (__builtin_username == username() && __builtin_username == username) { printf("SUCCESS %s\n", username); } }
EXPECT_REGEX SUCCESS .*