1*387f9dfdSAndroid Build Coastguard Worker#!/usr/bin/env python3 2*387f9dfdSAndroid Build Coastguard Worker# 3*387f9dfdSAndroid Build Coastguard Worker# USAGE: test_usdt2.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 <stdlib.h> 23*387f9dfdSAndroid Build Coastguard Worker#include <unistd.h> 24*387f9dfdSAndroid Build Coastguard Worker#include "folly/tracing/StaticTracepoint.h" 25*387f9dfdSAndroid Build Coastguard Worker 26*387f9dfdSAndroid Build Coastguard Workerint main(int argc, char **argv) { 27*387f9dfdSAndroid Build Coastguard Worker int t = atoi(argv[1]); 28*387f9dfdSAndroid Build Coastguard Worker while (1) { 29*387f9dfdSAndroid Build Coastguard Worker FOLLY_SDT(test, probe_point_1, t); 30*387f9dfdSAndroid Build Coastguard Worker FOLLY_SDT(test, probe_point_2, t + 1); 31*387f9dfdSAndroid Build Coastguard Worker FOLLY_SDT(test, probe_point_3, t + 2); 32*387f9dfdSAndroid Build Coastguard Worker sleep(1); 33*387f9dfdSAndroid Build Coastguard Worker } 34*387f9dfdSAndroid Build Coastguard Worker return 1; 35*387f9dfdSAndroid Build Coastguard Worker} 36*387f9dfdSAndroid Build Coastguard Worker""" 37*387f9dfdSAndroid Build Coastguard Worker # BPF program 38*387f9dfdSAndroid Build Coastguard Worker self.bpf_text = b""" 39*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/ptrace.h> 40*387f9dfdSAndroid Build Coastguard Worker 41*387f9dfdSAndroid Build Coastguard WorkerBPF_PERF_OUTPUT(event1); 42*387f9dfdSAndroid Build Coastguard WorkerBPF_PERF_OUTPUT(event2); 43*387f9dfdSAndroid Build Coastguard WorkerBPF_PERF_OUTPUT(event3); 44*387f9dfdSAndroid Build Coastguard WorkerBPF_PERF_OUTPUT(event4); 45*387f9dfdSAndroid Build Coastguard WorkerBPF_PERF_OUTPUT(event5); 46*387f9dfdSAndroid Build Coastguard WorkerBPF_PERF_OUTPUT(event6); 47*387f9dfdSAndroid Build Coastguard Worker 48*387f9dfdSAndroid Build Coastguard Workerint do_trace1(struct pt_regs *ctx) { 49*387f9dfdSAndroid Build Coastguard Worker u32 pid = bpf_get_current_pid_tgid(); 50*387f9dfdSAndroid Build Coastguard Worker int result = 0; 51*387f9dfdSAndroid Build Coastguard Worker bpf_usdt_readarg(1, ctx, &result); 52*387f9dfdSAndroid Build Coastguard Worker if (FILTER) 53*387f9dfdSAndroid Build Coastguard Worker event1.perf_submit(ctx, &result, sizeof(result)); 54*387f9dfdSAndroid Build Coastguard Worker else 55*387f9dfdSAndroid Build Coastguard Worker event4.perf_submit(ctx, &result, sizeof(result)); 56*387f9dfdSAndroid Build Coastguard Worker return 0; 57*387f9dfdSAndroid Build Coastguard Worker}; 58*387f9dfdSAndroid Build Coastguard Workerint do_trace2(struct pt_regs *ctx) { 59*387f9dfdSAndroid Build Coastguard Worker u32 pid = bpf_get_current_pid_tgid(); 60*387f9dfdSAndroid Build Coastguard Worker int result = 0; 61*387f9dfdSAndroid Build Coastguard Worker bpf_usdt_readarg(1, ctx, &result); 62*387f9dfdSAndroid Build Coastguard Worker if (FILTER) 63*387f9dfdSAndroid Build Coastguard Worker event2.perf_submit(ctx, &result, sizeof(result)); 64*387f9dfdSAndroid Build Coastguard Worker else 65*387f9dfdSAndroid Build Coastguard Worker event5.perf_submit(ctx, &result, sizeof(result)); 66*387f9dfdSAndroid Build Coastguard Worker return 0; 67*387f9dfdSAndroid Build Coastguard Worker} 68*387f9dfdSAndroid Build Coastguard Workerint do_trace3(struct pt_regs *ctx) { 69*387f9dfdSAndroid Build Coastguard Worker u32 pid = bpf_get_current_pid_tgid(); 70*387f9dfdSAndroid Build Coastguard Worker int result = 0; 71*387f9dfdSAndroid Build Coastguard Worker bpf_usdt_readarg(1, ctx, &result); 72*387f9dfdSAndroid Build Coastguard Worker if (FILTER) 73*387f9dfdSAndroid Build Coastguard Worker event3.perf_submit(ctx, &result, sizeof(result)); 74*387f9dfdSAndroid Build Coastguard Worker else 75*387f9dfdSAndroid Build Coastguard Worker event6.perf_submit(ctx, &result, sizeof(result)); 76*387f9dfdSAndroid Build Coastguard Worker return 0; 77*387f9dfdSAndroid Build Coastguard Worker} 78*387f9dfdSAndroid Build Coastguard Worker""" 79*387f9dfdSAndroid Build Coastguard Worker 80*387f9dfdSAndroid Build Coastguard Worker # Compile and run the application 81*387f9dfdSAndroid Build Coastguard Worker self.ftemp = NamedTemporaryFile(delete=False) 82*387f9dfdSAndroid Build Coastguard Worker self.ftemp.close() 83*387f9dfdSAndroid Build Coastguard Worker comp = Popen(["gcc", "-I", "%s/include" % os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))), 84*387f9dfdSAndroid Build Coastguard Worker "-x", "c++", "-o", self.ftemp.name, "-"], 85*387f9dfdSAndroid Build Coastguard Worker stdin=PIPE) 86*387f9dfdSAndroid Build Coastguard Worker comp.stdin.write(app_text) 87*387f9dfdSAndroid Build Coastguard Worker comp.stdin.close() 88*387f9dfdSAndroid Build Coastguard Worker self.assertEqual(comp.wait(), 0) 89*387f9dfdSAndroid Build Coastguard Worker 90*387f9dfdSAndroid Build Coastguard Worker # create 3 applications, 2 applications will have usdt attached and 91*387f9dfdSAndroid Build Coastguard Worker # the third one does not, and the third one should not call into 92*387f9dfdSAndroid Build Coastguard Worker # bpf program. 93*387f9dfdSAndroid Build Coastguard Worker self.app = Popen([self.ftemp.name, "1"]) 94*387f9dfdSAndroid Build Coastguard Worker self.app2 = Popen([self.ftemp.name, "11"]) 95*387f9dfdSAndroid Build Coastguard Worker self.app3 = Popen([self.ftemp.name, "21"]) 96*387f9dfdSAndroid Build Coastguard Worker 97*387f9dfdSAndroid Build Coastguard Worker def test_attach1(self): 98*387f9dfdSAndroid Build Coastguard Worker # Enable USDT probe from given PID and verifier generated BPF programs. 99*387f9dfdSAndroid Build Coastguard Worker u = USDT(pid=int(self.app.pid)) 100*387f9dfdSAndroid Build Coastguard Worker u.enable_probe(probe="probe_point_1", fn_name="do_trace1") 101*387f9dfdSAndroid Build Coastguard Worker u.enable_probe(probe="probe_point_2", fn_name="do_trace2") 102*387f9dfdSAndroid Build Coastguard Worker u2 = USDT(pid=int(self.app2.pid)) 103*387f9dfdSAndroid Build Coastguard Worker u2.enable_probe(probe="probe_point_2", fn_name="do_trace2") 104*387f9dfdSAndroid Build Coastguard Worker u2.enable_probe(probe="probe_point_3", fn_name="do_trace3") 105*387f9dfdSAndroid Build Coastguard Worker self.bpf_text = self.bpf_text.replace(b"FILTER", b"pid == %d" % self.app.pid) 106*387f9dfdSAndroid Build Coastguard Worker b = BPF(text=self.bpf_text, usdt_contexts=[u, u2]) 107*387f9dfdSAndroid Build Coastguard Worker 108*387f9dfdSAndroid Build Coastguard Worker # Event states for each event: 109*387f9dfdSAndroid Build Coastguard Worker # 0 - probe not caught, 1 - probe caught with correct value, 110*387f9dfdSAndroid Build Coastguard Worker # 2 - probe caught with incorrect value 111*387f9dfdSAndroid Build Coastguard Worker self.evt_st_1 = 0 112*387f9dfdSAndroid Build Coastguard Worker self.evt_st_2 = 0 113*387f9dfdSAndroid Build Coastguard Worker self.evt_st_3 = 0 114*387f9dfdSAndroid Build Coastguard Worker self.evt_st_4 = 0 115*387f9dfdSAndroid Build Coastguard Worker self.evt_st_5 = 0 116*387f9dfdSAndroid Build Coastguard Worker self.evt_st_6 = 0 117*387f9dfdSAndroid Build Coastguard Worker 118*387f9dfdSAndroid Build Coastguard Worker def check_event_val(data, event_state, expected_val): 119*387f9dfdSAndroid Build Coastguard Worker result = ct.cast(data, ct.POINTER(ct.c_int)).contents 120*387f9dfdSAndroid Build Coastguard Worker if result.value == expected_val: 121*387f9dfdSAndroid Build Coastguard Worker if (event_state == 0 or event_state == 1): 122*387f9dfdSAndroid Build Coastguard Worker return 1 123*387f9dfdSAndroid Build Coastguard Worker return 2 124*387f9dfdSAndroid Build Coastguard Worker 125*387f9dfdSAndroid Build Coastguard Worker def print_event1(cpu, data, size): 126*387f9dfdSAndroid Build Coastguard Worker self.evt_st_1 = check_event_val(data, self.evt_st_1, 1) 127*387f9dfdSAndroid Build Coastguard Worker 128*387f9dfdSAndroid Build Coastguard Worker def print_event2(cpu, data, size): 129*387f9dfdSAndroid Build Coastguard Worker self.evt_st_2 = check_event_val(data, self.evt_st_2, 2) 130*387f9dfdSAndroid Build Coastguard Worker 131*387f9dfdSAndroid Build Coastguard Worker def print_event3(cpu, data, size): 132*387f9dfdSAndroid Build Coastguard Worker self.evt_st_3 = check_event_val(data, self.evt_st_3, 3) 133*387f9dfdSAndroid Build Coastguard Worker 134*387f9dfdSAndroid Build Coastguard Worker def print_event4(cpu, data, size): 135*387f9dfdSAndroid Build Coastguard Worker self.evt_st_4 = check_event_val(data, self.evt_st_4, 11) 136*387f9dfdSAndroid Build Coastguard Worker 137*387f9dfdSAndroid Build Coastguard Worker def print_event5(cpu, data, size): 138*387f9dfdSAndroid Build Coastguard Worker self.evt_st_5 = check_event_val(data, self.evt_st_5, 12) 139*387f9dfdSAndroid Build Coastguard Worker 140*387f9dfdSAndroid Build Coastguard Worker def print_event6(cpu, data, size): 141*387f9dfdSAndroid Build Coastguard Worker self.evt_st_6 = check_event_val(data, self.evt_st_6, 13) 142*387f9dfdSAndroid Build Coastguard Worker 143*387f9dfdSAndroid Build Coastguard Worker # loop with callback to print_event 144*387f9dfdSAndroid Build Coastguard Worker b[b"event1"].open_perf_buffer(print_event1) 145*387f9dfdSAndroid Build Coastguard Worker b[b"event2"].open_perf_buffer(print_event2) 146*387f9dfdSAndroid Build Coastguard Worker b[b"event3"].open_perf_buffer(print_event3) 147*387f9dfdSAndroid Build Coastguard Worker b[b"event4"].open_perf_buffer(print_event4) 148*387f9dfdSAndroid Build Coastguard Worker b[b"event5"].open_perf_buffer(print_event5) 149*387f9dfdSAndroid Build Coastguard Worker b[b"event6"].open_perf_buffer(print_event6) 150*387f9dfdSAndroid Build Coastguard Worker 151*387f9dfdSAndroid Build Coastguard Worker # three iterations to make sure we get some probes and have time to process them 152*387f9dfdSAndroid Build Coastguard Worker for i in range(5): 153*387f9dfdSAndroid Build Coastguard Worker b.perf_buffer_poll() 154*387f9dfdSAndroid Build Coastguard Worker 155*387f9dfdSAndroid Build Coastguard Worker # note that event1 and event4 do not really fire, so their state should be 0 156*387f9dfdSAndroid Build Coastguard Worker # use separate asserts so that if test fails we know which one is the culprit 157*387f9dfdSAndroid Build Coastguard Worker self.assertTrue(self.evt_st_1 == 1) 158*387f9dfdSAndroid Build Coastguard Worker self.assertTrue(self.evt_st_2 == 1) 159*387f9dfdSAndroid Build Coastguard Worker self.assertTrue(self.evt_st_3 == 0) 160*387f9dfdSAndroid Build Coastguard Worker self.assertTrue(self.evt_st_4 == 0) 161*387f9dfdSAndroid Build Coastguard Worker self.assertTrue(self.evt_st_5 == 1) 162*387f9dfdSAndroid Build Coastguard Worker self.assertTrue(self.evt_st_6 == 1) 163*387f9dfdSAndroid Build Coastguard Worker 164*387f9dfdSAndroid Build Coastguard Worker def tearDown(self): 165*387f9dfdSAndroid Build Coastguard Worker # kill the subprocess, clean the environment 166*387f9dfdSAndroid Build Coastguard Worker self.app.kill() 167*387f9dfdSAndroid Build Coastguard Worker self.app.wait() 168*387f9dfdSAndroid Build Coastguard Worker self.app2.kill() 169*387f9dfdSAndroid Build Coastguard Worker self.app2.wait() 170*387f9dfdSAndroid Build Coastguard Worker self.app3.kill() 171*387f9dfdSAndroid Build Coastguard Worker self.app3.wait() 172*387f9dfdSAndroid Build Coastguard Worker os.unlink(self.ftemp.name) 173*387f9dfdSAndroid Build Coastguard Worker 174*387f9dfdSAndroid Build Coastguard Workerif __name__ == "__main__": 175*387f9dfdSAndroid Build Coastguard Worker main() 176