xref: /aosp_15_r20/external/bcc/tests/python/test_usdt.py (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
1*387f9dfdSAndroid Build Coastguard Worker#!/usr/bin/env python3
2*387f9dfdSAndroid Build Coastguard Worker#
3*387f9dfdSAndroid Build Coastguard Worker# USAGE: test_usdt.py
4*387f9dfdSAndroid Build Coastguard Worker#
5*387f9dfdSAndroid Build Coastguard Worker# Copyright 2017 Facebook, Inc
6*387f9dfdSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License")
7*387f9dfdSAndroid Build Coastguard Worker
8*387f9dfdSAndroid Build Coastguard Workerfrom __future__ import print_function
9*387f9dfdSAndroid Build Coastguard Workerfrom bcc import BPF, USDT
10*387f9dfdSAndroid Build Coastguard Workerfrom unittest import main, TestCase
11*387f9dfdSAndroid Build Coastguard Workerfrom subprocess import Popen, PIPE
12*387f9dfdSAndroid Build Coastguard Workerfrom tempfile import NamedTemporaryFile
13*387f9dfdSAndroid Build Coastguard Workerimport ctypes as ct
14*387f9dfdSAndroid Build Coastguard Workerimport inspect
15*387f9dfdSAndroid Build Coastguard Workerimport os
16*387f9dfdSAndroid Build Coastguard Workerimport signal
17*387f9dfdSAndroid Build Coastguard Worker
18*387f9dfdSAndroid Build Coastguard Workerclass TestUDST(TestCase):
19*387f9dfdSAndroid Build Coastguard Worker    def setUp(self):
20*387f9dfdSAndroid Build Coastguard Worker        # Application, minimum, to define three trace points
21*387f9dfdSAndroid Build Coastguard Worker        app_text = b"""
22*387f9dfdSAndroid Build Coastguard Worker#include <unistd.h>
23*387f9dfdSAndroid Build Coastguard Worker#include <stdint.h>
24*387f9dfdSAndroid Build Coastguard Worker#include <stdio.h>
25*387f9dfdSAndroid Build Coastguard Worker#include <string.h>
26*387f9dfdSAndroid Build Coastguard Worker#include "folly/tracing/StaticTracepoint.h"
27*387f9dfdSAndroid Build Coastguard Worker
28*387f9dfdSAndroid Build Coastguard Workerint main() {
29*387f9dfdSAndroid Build Coastguard Worker  char s[100];
30*387f9dfdSAndroid Build Coastguard Worker  int i, a = 200, b = 40;
31*387f9dfdSAndroid Build Coastguard Worker  for (i = 0; i < 100; i++) s[i] = (i & 7) + (i & 6);
32*387f9dfdSAndroid Build Coastguard Worker  uint64_t j = 0;
33*387f9dfdSAndroid Build Coastguard Worker  char s1[64];
34*387f9dfdSAndroid Build Coastguard Worker  const char* str = "str";
35*387f9dfdSAndroid Build Coastguard Worker  size_t len = strlen(str);
36*387f9dfdSAndroid Build Coastguard Worker  while (1) {
37*387f9dfdSAndroid Build Coastguard Worker    FOLLY_SDT(test, probe_point_1, s[7], b);
38*387f9dfdSAndroid Build Coastguard Worker    FOLLY_SDT(test, probe_point_3, a, b);
39*387f9dfdSAndroid Build Coastguard Worker    FOLLY_SDT(test, probe_point_1, s[4], a);
40*387f9dfdSAndroid Build Coastguard Worker    FOLLY_SDT(test, probe_point_2, 5, s[10]);
41*387f9dfdSAndroid Build Coastguard Worker    FOLLY_SDT(test, probe_point_3, s[4], s[7]);
42*387f9dfdSAndroid Build Coastguard Worker
43*387f9dfdSAndroid Build Coastguard Worker    memset(&s1, '\0', sizeof(s1));
44*387f9dfdSAndroid Build Coastguard Worker    strncpy(s1, str, len);
45*387f9dfdSAndroid Build Coastguard Worker    snprintf(s1 + len, sizeof(s1) - len, "%d", j);
46*387f9dfdSAndroid Build Coastguard Worker    FOLLY_SDT(test, probe_point_4, j++, &s1);
47*387f9dfdSAndroid Build Coastguard Worker
48*387f9dfdSAndroid Build Coastguard Worker    memset(&s1, '\0', sizeof(s1));
49*387f9dfdSAndroid Build Coastguard Worker    strncpy(s1, str, len);
50*387f9dfdSAndroid Build Coastguard Worker    snprintf(s1 + len, sizeof(s1) - len, "%d", j);
51*387f9dfdSAndroid Build Coastguard Worker    FOLLY_SDT(test, probe_point_5, &s1, j++);
52*387f9dfdSAndroid Build Coastguard Worker
53*387f9dfdSAndroid Build Coastguard Worker    sleep(1);
54*387f9dfdSAndroid Build Coastguard Worker  }
55*387f9dfdSAndroid Build Coastguard Worker  return 1;
56*387f9dfdSAndroid Build Coastguard Worker}
57*387f9dfdSAndroid Build Coastguard Worker"""
58*387f9dfdSAndroid Build Coastguard Worker        # BPF program
59*387f9dfdSAndroid Build Coastguard Worker        self.bpf_text = b"""
60*387f9dfdSAndroid Build Coastguard Worker#include <linux/blkdev.h>
61*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/ptrace.h>
62*387f9dfdSAndroid Build Coastguard Worker
63*387f9dfdSAndroid Build Coastguard Workerstruct probe_result_t1 {
64*387f9dfdSAndroid Build Coastguard Worker  char v1;
65*387f9dfdSAndroid Build Coastguard Worker  int  v2;
66*387f9dfdSAndroid Build Coastguard Worker};
67*387f9dfdSAndroid Build Coastguard Worker
68*387f9dfdSAndroid Build Coastguard Workerstruct probe_result_t2 {
69*387f9dfdSAndroid Build Coastguard Worker  int  v1;
70*387f9dfdSAndroid Build Coastguard Worker  char v2;
71*387f9dfdSAndroid Build Coastguard Worker};
72*387f9dfdSAndroid Build Coastguard Worker
73*387f9dfdSAndroid Build Coastguard Workerstruct probe_result_t3 {
74*387f9dfdSAndroid Build Coastguard Worker  int v1;
75*387f9dfdSAndroid Build Coastguard Worker  int v2;
76*387f9dfdSAndroid Build Coastguard Worker};
77*387f9dfdSAndroid Build Coastguard Worker
78*387f9dfdSAndroid Build Coastguard Workerstruct probe_result_t4 {
79*387f9dfdSAndroid Build Coastguard Worker  u64  v1;
80*387f9dfdSAndroid Build Coastguard Worker  char v2[8];
81*387f9dfdSAndroid Build Coastguard Worker};
82*387f9dfdSAndroid Build Coastguard Worker
83*387f9dfdSAndroid Build Coastguard Workerstruct probe_result_t5 {
84*387f9dfdSAndroid Build Coastguard Worker  char v1[8];
85*387f9dfdSAndroid Build Coastguard Worker  u64  v2;
86*387f9dfdSAndroid Build Coastguard Worker};
87*387f9dfdSAndroid Build Coastguard Worker
88*387f9dfdSAndroid Build Coastguard WorkerBPF_PERF_OUTPUT(event1);
89*387f9dfdSAndroid Build Coastguard WorkerBPF_PERF_OUTPUT(event2);
90*387f9dfdSAndroid Build Coastguard WorkerBPF_PERF_OUTPUT(event3);
91*387f9dfdSAndroid Build Coastguard WorkerBPF_PERF_OUTPUT(event4);
92*387f9dfdSAndroid Build Coastguard WorkerBPF_PERF_OUTPUT(event5);
93*387f9dfdSAndroid Build Coastguard Worker
94*387f9dfdSAndroid Build Coastguard Workerint do_trace1(struct pt_regs *ctx) {
95*387f9dfdSAndroid Build Coastguard Worker    struct probe_result_t1 result = {};
96*387f9dfdSAndroid Build Coastguard Worker    bpf_usdt_readarg(1, ctx, &result.v1);
97*387f9dfdSAndroid Build Coastguard Worker    bpf_usdt_readarg(2, ctx, &result.v2);
98*387f9dfdSAndroid Build Coastguard Worker    event1.perf_submit(ctx, &result, sizeof(result));
99*387f9dfdSAndroid Build Coastguard Worker    return 0;
100*387f9dfdSAndroid Build Coastguard Worker};
101*387f9dfdSAndroid Build Coastguard Workerint do_trace2(struct pt_regs *ctx) {
102*387f9dfdSAndroid Build Coastguard Worker    struct probe_result_t2 result = {};
103*387f9dfdSAndroid Build Coastguard Worker    bpf_usdt_readarg(1, ctx, &result.v1);
104*387f9dfdSAndroid Build Coastguard Worker    bpf_usdt_readarg(2, ctx, &result.v2);
105*387f9dfdSAndroid Build Coastguard Worker    event2.perf_submit(ctx, &result, sizeof(result));
106*387f9dfdSAndroid Build Coastguard Worker    return 0;
107*387f9dfdSAndroid Build Coastguard Worker}
108*387f9dfdSAndroid Build Coastguard Workerint do_trace3(struct pt_regs *ctx) {
109*387f9dfdSAndroid Build Coastguard Worker    struct probe_result_t3 result = {};
110*387f9dfdSAndroid Build Coastguard Worker    bpf_usdt_readarg(1, ctx, &result.v1);
111*387f9dfdSAndroid Build Coastguard Worker    bpf_usdt_readarg(2, ctx, &result.v2);
112*387f9dfdSAndroid Build Coastguard Worker    event3.perf_submit(ctx, &result, sizeof(result));
113*387f9dfdSAndroid Build Coastguard Worker    return 0;
114*387f9dfdSAndroid Build Coastguard Worker}
115*387f9dfdSAndroid Build Coastguard Workerint do_trace4(struct pt_regs *ctx) {
116*387f9dfdSAndroid Build Coastguard Worker    struct probe_result_t4 result = {};
117*387f9dfdSAndroid Build Coastguard Worker    bpf_usdt_readarg(1, ctx, &result.v1);
118*387f9dfdSAndroid Build Coastguard Worker    bpf_usdt_readarg_p(2, ctx, &result.v2, sizeof(result.v2));
119*387f9dfdSAndroid Build Coastguard Worker    event4.perf_submit(ctx, &result, sizeof(result));
120*387f9dfdSAndroid Build Coastguard Worker    return 0;
121*387f9dfdSAndroid Build Coastguard Worker}
122*387f9dfdSAndroid Build Coastguard Workerint do_trace5(struct pt_regs *ctx) {
123*387f9dfdSAndroid Build Coastguard Worker    struct probe_result_t5 result = {};
124*387f9dfdSAndroid Build Coastguard Worker    bpf_usdt_readarg_p(1, ctx, &result.v1, sizeof(result.v1));
125*387f9dfdSAndroid Build Coastguard Worker    bpf_usdt_readarg(2, ctx, &result.v2);
126*387f9dfdSAndroid Build Coastguard Worker    event5.perf_submit(ctx, &result, sizeof(result));
127*387f9dfdSAndroid Build Coastguard Worker    return 0;
128*387f9dfdSAndroid Build Coastguard Worker}
129*387f9dfdSAndroid Build Coastguard Worker"""
130*387f9dfdSAndroid Build Coastguard Worker
131*387f9dfdSAndroid Build Coastguard Worker        # Compile and run the application
132*387f9dfdSAndroid Build Coastguard Worker        self.ftemp = NamedTemporaryFile(delete=False)
133*387f9dfdSAndroid Build Coastguard Worker        self.ftemp.close()
134*387f9dfdSAndroid Build Coastguard Worker        comp = Popen(["gcc", "-I", "%s/include" % os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))),
135*387f9dfdSAndroid Build Coastguard Worker                      "-x", "c++", "-o", self.ftemp.name, "-"],
136*387f9dfdSAndroid Build Coastguard Worker                     stdin=PIPE)
137*387f9dfdSAndroid Build Coastguard Worker        comp.stdin.write(app_text)
138*387f9dfdSAndroid Build Coastguard Worker        comp.stdin.close()
139*387f9dfdSAndroid Build Coastguard Worker        self.assertEqual(comp.wait(), 0)
140*387f9dfdSAndroid Build Coastguard Worker        self.app = Popen([self.ftemp.name])
141*387f9dfdSAndroid Build Coastguard Worker
142*387f9dfdSAndroid Build Coastguard Worker    def test_attach1(self):
143*387f9dfdSAndroid Build Coastguard Worker        # enable USDT probe from given PID and verifier generated BPF programs
144*387f9dfdSAndroid Build Coastguard Worker        u = USDT(pid=int(self.app.pid))
145*387f9dfdSAndroid Build Coastguard Worker        u.enable_probe(probe="probe_point_1", fn_name="do_trace1")
146*387f9dfdSAndroid Build Coastguard Worker        u.enable_probe(probe="probe_point_2", fn_name="do_trace2")
147*387f9dfdSAndroid Build Coastguard Worker        u.enable_probe(probe="probe_point_3", fn_name="do_trace3")
148*387f9dfdSAndroid Build Coastguard Worker        u.enable_probe(probe="probe_point_4", fn_name="do_trace4")
149*387f9dfdSAndroid Build Coastguard Worker        u.enable_probe(probe="probe_point_5", fn_name="do_trace5")
150*387f9dfdSAndroid Build Coastguard Worker        b = BPF(text=self.bpf_text, usdt_contexts=[u], debug=4)
151*387f9dfdSAndroid Build Coastguard Worker
152*387f9dfdSAndroid Build Coastguard Worker        # Event states for each event:
153*387f9dfdSAndroid Build Coastguard Worker        # 0 - probe not caught, 1 - probe caught with correct value,
154*387f9dfdSAndroid Build Coastguard Worker        # 2 - probe caught with incorrect value
155*387f9dfdSAndroid Build Coastguard Worker        self.evt_st_1 = 0
156*387f9dfdSAndroid Build Coastguard Worker        self.evt_st_2 = 0
157*387f9dfdSAndroid Build Coastguard Worker        self.evt_st_3 = 0
158*387f9dfdSAndroid Build Coastguard Worker
159*387f9dfdSAndroid Build Coastguard Worker        # define output data structure in Python
160*387f9dfdSAndroid Build Coastguard Worker        class Data1(ct.Structure):
161*387f9dfdSAndroid Build Coastguard Worker            _fields_ = [("v1", ct.c_char),
162*387f9dfdSAndroid Build Coastguard Worker                        ("v2", ct.c_int)]
163*387f9dfdSAndroid Build Coastguard Worker
164*387f9dfdSAndroid Build Coastguard Worker        class Data2(ct.Structure):
165*387f9dfdSAndroid Build Coastguard Worker            _fields_ = [("v1", ct.c_int),
166*387f9dfdSAndroid Build Coastguard Worker                        ("v2", ct.c_char)]
167*387f9dfdSAndroid Build Coastguard Worker
168*387f9dfdSAndroid Build Coastguard Worker        class Data3(ct.Structure):
169*387f9dfdSAndroid Build Coastguard Worker            _fields_ = [("v1", ct.c_int),
170*387f9dfdSAndroid Build Coastguard Worker                        ("v2", ct.c_int)]
171*387f9dfdSAndroid Build Coastguard Worker
172*387f9dfdSAndroid Build Coastguard Worker        class Data4(ct.Structure):
173*387f9dfdSAndroid Build Coastguard Worker            _fields_ = [("v1", ct.c_ulonglong),
174*387f9dfdSAndroid Build Coastguard Worker                        ("v2", ct.c_char * 64)]
175*387f9dfdSAndroid Build Coastguard Worker
176*387f9dfdSAndroid Build Coastguard Worker        class Data5(ct.Structure):
177*387f9dfdSAndroid Build Coastguard Worker            _fields_ = [("v1", ct.c_char * 64),
178*387f9dfdSAndroid Build Coastguard Worker                        ("v2", ct.c_ulonglong)]
179*387f9dfdSAndroid Build Coastguard Worker
180*387f9dfdSAndroid Build Coastguard Worker        def check_event_val(event, event_state, v1, v2, v3, v4):
181*387f9dfdSAndroid Build Coastguard Worker            if ((event.v1 == v1 and event.v2 == v2) or (event.v1 == v3 and event.v2 == v4)):
182*387f9dfdSAndroid Build Coastguard Worker                if (event_state == 0 or event_state == 1):
183*387f9dfdSAndroid Build Coastguard Worker                    return 1
184*387f9dfdSAndroid Build Coastguard Worker            return 2
185*387f9dfdSAndroid Build Coastguard Worker
186*387f9dfdSAndroid Build Coastguard Worker        def print_event1(cpu, data, size):
187*387f9dfdSAndroid Build Coastguard Worker            event = ct.cast(data, ct.POINTER(Data1)).contents
188*387f9dfdSAndroid Build Coastguard Worker            self.evt_st_1 = check_event_val(event, self.evt_st_1, b'\x0d', 40, b'\x08', 200)
189*387f9dfdSAndroid Build Coastguard Worker
190*387f9dfdSAndroid Build Coastguard Worker        def print_event2(cpu, data, size):
191*387f9dfdSAndroid Build Coastguard Worker            event = ct.cast(data, ct.POINTER(Data2)).contents
192*387f9dfdSAndroid Build Coastguard Worker            # pretend we have two identical probe points to simplify the code
193*387f9dfdSAndroid Build Coastguard Worker            self.evt_st_2 = check_event_val(event, self.evt_st_2, 5, b'\x04', 5, b'\x04')
194*387f9dfdSAndroid Build Coastguard Worker
195*387f9dfdSAndroid Build Coastguard Worker        def print_event3(cpu, data, size):
196*387f9dfdSAndroid Build Coastguard Worker            event = ct.cast(data, ct.POINTER(Data3)).contents
197*387f9dfdSAndroid Build Coastguard Worker            self.evt_st_3 = check_event_val(event, self.evt_st_3, 200, 40, 8, 13)
198*387f9dfdSAndroid Build Coastguard Worker
199*387f9dfdSAndroid Build Coastguard Worker        def print_event4(cpu, data, size):
200*387f9dfdSAndroid Build Coastguard Worker            event = ct.cast(data, ct.POINTER(Data4)).contents
201*387f9dfdSAndroid Build Coastguard Worker            print("%s" % event.v2)
202*387f9dfdSAndroid Build Coastguard Worker
203*387f9dfdSAndroid Build Coastguard Worker        def print_event5(cpu, data, size):
204*387f9dfdSAndroid Build Coastguard Worker            event = ct.cast(data, ct.POINTER(Data5)).contents
205*387f9dfdSAndroid Build Coastguard Worker            print("%s" % event.v1)
206*387f9dfdSAndroid Build Coastguard Worker
207*387f9dfdSAndroid Build Coastguard Worker        # loop with callback to print_event
208*387f9dfdSAndroid Build Coastguard Worker        b[b"event1"].open_perf_buffer(print_event1)
209*387f9dfdSAndroid Build Coastguard Worker        b[b"event2"].open_perf_buffer(print_event2)
210*387f9dfdSAndroid Build Coastguard Worker        b[b"event3"].open_perf_buffer(print_event3)
211*387f9dfdSAndroid Build Coastguard Worker        b[b"event4"].open_perf_buffer(print_event4)
212*387f9dfdSAndroid Build Coastguard Worker        b[b"event5"].open_perf_buffer(print_event5)
213*387f9dfdSAndroid Build Coastguard Worker
214*387f9dfdSAndroid Build Coastguard Worker        # three iterations to make sure we get some probes and have time to process them
215*387f9dfdSAndroid Build Coastguard Worker        for i in range(3):
216*387f9dfdSAndroid Build Coastguard Worker            b.perf_buffer_poll()
217*387f9dfdSAndroid Build Coastguard Worker        self.assertTrue(self.evt_st_1 == 1 and self.evt_st_2 == 1 and self.evt_st_3 == 1)
218*387f9dfdSAndroid Build Coastguard Worker
219*387f9dfdSAndroid Build Coastguard Worker    def tearDown(self):
220*387f9dfdSAndroid Build Coastguard Worker        # kill the subprocess, clean the environment
221*387f9dfdSAndroid Build Coastguard Worker        self.app.kill()
222*387f9dfdSAndroid Build Coastguard Worker        self.app.wait()
223*387f9dfdSAndroid Build Coastguard Worker        os.unlink(self.ftemp.name)
224*387f9dfdSAndroid Build Coastguard Worker
225*387f9dfdSAndroid Build Coastguard Workerif __name__ == "__main__":
226*387f9dfdSAndroid Build Coastguard Worker    main()
227