File: scratch_buffer.cpp

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 (158 lines) | stat: -rw-r--r-- 4,627 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
#include "common.h"

namespace bpftrace::test::codegen {

static constexpr uint64_t SMALL_ON_STACK_LIMIT = 0;
static constexpr uint64_t LARGE_ON_STACK_LIMIT = 128;
static constexpr uint64_t MAX_STRLEN = 64;

static void test_stack_or_scratch_buffer(const std::string &input,
                                         const std::string &name,
                                         uint64_t on_stack_limit)
{
  auto bpftrace = get_mock_bpftrace();
  bpftrace->config_->on_stack_limit = on_stack_limit;
  bpftrace->config_->max_strlen = MAX_STRLEN;
  bpftrace->safe_mode_ = true;

  test(*bpftrace, input, name);
}

TEST(codegen, tuple_scratch_buf)
{
  test_stack_or_scratch_buffer("kprobe:f { (1, \"xxxx\") }",
                               NAME,
                               SMALL_ON_STACK_LIMIT);
}

TEST(codegen, tuple_stack)
{
  test_stack_or_scratch_buffer("kprobe:f { (1, \"xxxx\") }",
                               NAME,
                               LARGE_ON_STACK_LIMIT);
}

TEST(codegen, fmt_str_args_scratch_buf)
{
  test_stack_or_scratch_buffer(R"(kprobe:f { printf("%s %d\n", "xxxx", 1) })",
                               NAME,
                               SMALL_ON_STACK_LIMIT);
}

TEST(codegen, fmt_str_args_stack)
{
  test_stack_or_scratch_buffer(R"(kprobe:f { printf("%s %d\n", "xxxx", 1) })",
                               NAME,
                               LARGE_ON_STACK_LIMIT);
}

TEST(codegen, str_scratch_buf)
{
  test_stack_or_scratch_buffer("kprobe:f { str(arg0) }",
                               NAME,
                               SMALL_ON_STACK_LIMIT);
}

TEST(codegen, str_stack)
{
  test_stack_or_scratch_buffer("kprobe:f { str(arg0) }",
                               NAME,
                               LARGE_ON_STACK_LIMIT);
}

TEST(codegen, map_value_int_scratch_buf)
{
  test_stack_or_scratch_buffer("kprobe:f { @x = 1; @y = @x }",
                               NAME,
                               SMALL_ON_STACK_LIMIT);
}

TEST(codegen, map_value_int_stack)
{
  test_stack_or_scratch_buffer("kprobe:f { @x = 1; @y = @x }",
                               NAME,
                               LARGE_ON_STACK_LIMIT);
}

// Using two tuples with different sizes will trigger copying tuples to the
// scratch buffer or stack prior to updating the map
TEST(codegen, map_value_tuple_scratch_buf)
{
  test_stack_or_scratch_buffer(
      R"(kprobe:f { @x = ("xxx", 1); @x = ("xxxxxxx", 1); @y = @x })",
      NAME,
      SMALL_ON_STACK_LIMIT);
}

TEST(codegen, map_value_tuple_stack)
{
  test_stack_or_scratch_buffer(
      R"(kprobe:f { @x = ("xxx", 1); @x = ("xxxxxxx", 1); @y = @x })",
      NAME,
      LARGE_ON_STACK_LIMIT);
}

// Use an if statement with same variable name with two scopes to ensure
// initialization happens prior to both scopes
TEST(codegen, variable_scratch_buf)
{
  test_stack_or_scratch_buffer(
      "kprobe:f { if (arg0 > 0) { $x = 1; } else { $x = 2 } }",
      NAME,
      SMALL_ON_STACK_LIMIT);
}

TEST(codegen, variable_stack)
{
  test_stack_or_scratch_buffer(
      "kprobe:f { if (arg0 > 0) { $x = 1; } else { $x = 2 } }",
      NAME,
      LARGE_ON_STACK_LIMIT);
}

TEST(codegen, map_key_scratch_buf)
{
  test_stack_or_scratch_buffer("kprobe:f { @x[1] = 1; @y[\"yyyy\"] = @x[1]; }",
                               NAME,
                               SMALL_ON_STACK_LIMIT);
}

TEST(codegen, map_key_stack)
{
  test_stack_or_scratch_buffer("kprobe:f { @x[1] = 1; @y[\"yyyy\"] = @x[1]; }",
                               NAME,
                               LARGE_ON_STACK_LIMIT);
}

// Test map keys with aggregation and map-related functions
TEST(codegen, call_map_key_scratch_buf)
{
  test_stack_or_scratch_buffer("kprobe:f { @x[1] = count(); @y = hist(10); "
                               "has_key(@x, 1); delete(@x, 1); }",
                               NAME,
                               SMALL_ON_STACK_LIMIT);
}

TEST(codegen, call_map_key_stack)
{
  test_stack_or_scratch_buffer("kprobe:f { @x[1] = count(); @y = hist(10); "
                               "has_key(@x, 1); delete(@x, 1); }",
                               NAME,
                               LARGE_ON_STACK_LIMIT);
}

TEST(codegen, probe_str_scratch_buf)
{
  test_stack_or_scratch_buffer("tracepoint:sched:sched_one { @x = probe }",
                               NAME,
                               SMALL_ON_STACK_LIMIT);
}

TEST(codegen, probe_str_stack)
{
  test_stack_or_scratch_buffer("tracepoint:sched:sched_one { @x = probe }",
                               NAME,
                               LARGE_ON_STACK_LIMIT);
}

} // namespace bpftrace::test::codegen