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