Skip to content

Commit 05ed567

Browse files
olsajiriKernel Patches Daemon
authored andcommitted
selftests/bpf: Add test for checking correct nop of optimized usdt
Adding test that attaches bpf program on usdt probe in 2 scenarios; - attach program on top of usdt_1, which is single nop instruction, so the probe stays on nop instruction and is not optimized. - attach program on top of usdt_2 which is probe defined on top of nop,nop5 combo, so the probe is placed on top of nop5 and is optimized. Signed-off-by: Jiri Olsa <jolsa@kernel.org>
1 parent dc8fae7 commit 05ed567

File tree

6 files changed

+132
-1
lines changed

6 files changed

+132
-1
lines changed

tools/testing/selftests/bpf/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,5 @@ verification_cert.h
4747
*.BTF
4848
*.BTF_ids
4949
*.BTF.base
50+
usdt_1
51+
usdt_2

tools/testing/selftests/bpf/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -749,7 +749,8 @@ TRUNNER_EXTRA_SOURCES := test_progs.c \
749749
$(VERIFY_SIG_HDR) \
750750
flow_dissector_load.h \
751751
ip_check_defrag_frags.h \
752-
bpftool_helpers.c
752+
bpftool_helpers.c \
753+
usdt_1.c usdt_2.c
753754
TRUNNER_LIB_SOURCES := find_bit.c
754755
TRUNNER_EXTRA_FILES := $(OUTPUT)/urandom_read \
755756
$(OUTPUT)/liburandom_read.so \

tools/testing/selftests/bpf/prog_tests/usdt.c

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,89 @@ static void subtest_basic_usdt(bool optimized)
247247
#undef TRIGGER
248248
}
249249

250+
#ifdef __x86_64
251+
extern void usdt_1(void);
252+
extern void usdt_2(void);
253+
254+
/* nop, nop5 */
255+
static unsigned char nop1_nop5_combo[6] = { 0x90, 0x0f, 0x1f, 0x44, 0x00, 0x00 };
256+
static unsigned char nop1[6] = { 0x90 };
257+
258+
static void *find_instr(void *fn, unsigned char *instr, size_t cnt)
259+
{
260+
int i;
261+
262+
for (i = 0; i < 10; i++) {
263+
if (!memcmp(instr, fn + i, cnt))
264+
return fn + i;
265+
}
266+
return NULL;
267+
}
268+
269+
static void subtest_optimized_attach(void)
270+
{
271+
struct test_usdt *skel;
272+
__u8 *addr_1, *addr_2;
273+
274+
/* usdt_1 probe has single nop instruction */
275+
addr_1 = find_instr(usdt_1, nop1_nop5_combo, 6);
276+
if (!ASSERT_NULL(addr_1, "usdt_1_find_nop1_nop5_combo"))
277+
return;
278+
279+
addr_1 = find_instr(usdt_1, nop1, 1);
280+
if (!ASSERT_OK_PTR(addr_1, "usdt_1_find_nop1"))
281+
return;
282+
283+
/* usdt_2 probe has nop,nop5 instructions combo */
284+
addr_2 = find_instr(usdt_2, nop1_nop5_combo, 6);
285+
if (!ASSERT_OK_PTR(addr_2, "usdt_2_find_nop1_nop5_combo"))
286+
return;
287+
288+
skel = test_usdt__open_and_load();
289+
if (!ASSERT_OK_PTR(skel, "test_usdt__open_and_load"))
290+
return;
291+
292+
/*
293+
* Attach program on top of usdt_1 which is single nop probe,
294+
* so the probe won't get optimized.
295+
*/
296+
skel->links.usdt_executed = bpf_program__attach_usdt(skel->progs.usdt_executed,
297+
0 /*self*/, "/proc/self/exe",
298+
"optimized_attach", "usdt_1", NULL);
299+
if (!ASSERT_OK_PTR(skel->links.usdt_executed, "bpf_program__attach_usdt"))
300+
goto cleanup;
301+
302+
usdt_1();
303+
usdt_1();
304+
305+
/* nop is on addr_1 address */
306+
ASSERT_EQ(*addr_1, 0xcc, "int3");
307+
ASSERT_EQ(skel->bss->executed, 2, "executed");
308+
309+
bpf_link__destroy(skel->links.usdt_executed);
310+
311+
/*
312+
* Attach program on top of usdt_2 which is probe defined on top
313+
* of nop1,nop5 combo, so the probe gets optimized on top of nop5.
314+
*/
315+
skel->links.usdt_executed = bpf_program__attach_usdt(skel->progs.usdt_executed,
316+
0 /*self*/, "/proc/self/exe",
317+
"optimized_attach", "usdt_2", NULL);
318+
if (!ASSERT_OK_PTR(skel->links.usdt_executed, "bpf_program__attach_usdt"))
319+
goto cleanup;
320+
321+
usdt_2();
322+
usdt_2();
323+
324+
/* nop5 is on addr_2 + 1 address */
325+
ASSERT_EQ(*(addr_2 + 1), 0xe8, "call");
326+
ASSERT_EQ(skel->bss->executed, 4, "executed");
327+
328+
cleanup:
329+
test_usdt__destroy(skel);
330+
}
331+
#endif
332+
250333
unsigned short test_usdt_100_semaphore SEC(".probes");
251334
unsigned short test_usdt_300_semaphore SEC(".probes");
252335
unsigned short test_usdt_400_semaphore SEC(".probes");
@@ -516,6 +599,8 @@ void test_usdt(void)
516599
#ifdef __x86_64__
517600
if (test__start_subtest("basic_optimized"))
518601
subtest_basic_usdt(true);
602+
if (test__start_subtest("optimized_attach"))
603+
subtest_optimized_attach();
519604
#endif
520605
if (test__start_subtest("multispec"))
521606
subtest_multispec_usdt();

tools/testing/selftests/bpf/progs/test_usdt.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,4 +138,13 @@ int usdt_sib(struct pt_regs *ctx)
138138
return 0;
139139
}
140140

141+
int executed;
142+
143+
SEC("usdt")
144+
int usdt_executed(struct pt_regs *ctx)
145+
{
146+
executed++;
147+
return 0;
148+
}
149+
141150
char _license[] SEC("license") = "GPL";
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
#if defined(__x86_64__)
4+
5+
/*
6+
* Include usdt.h with defined USDT_NOP macro to use single
7+
* nop instruction.
8+
*/
9+
#define USDT_NOP .byte 0x90
10+
#include "usdt.h"
11+
12+
__attribute__((aligned(16)))
13+
void usdt_1(void)
14+
{
15+
USDT(optimized_attach, usdt_1);
16+
}
17+
18+
#endif
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
#if defined(__x86_64__)
4+
5+
/*
6+
* Include usdt.h with default nop,nop5 instructions combo.
7+
*/
8+
#include "usdt.h"
9+
10+
__attribute__((aligned(16)))
11+
void usdt_2(void)
12+
{
13+
USDT(optimized_attach, usdt_2);
14+
}
15+
16+
#endif

0 commit comments

Comments
 (0)