1*387f9dfdSAndroid Build Coastguard Worker#!/usr/bin/env python 2*387f9dfdSAndroid Build Coastguard Worker# 3*387f9dfdSAndroid Build Coastguard Worker# trace Trace a function and print a trace message based on its 4*387f9dfdSAndroid Build Coastguard Worker# parameters, with an optional filter. 5*387f9dfdSAndroid Build Coastguard Worker# 6*387f9dfdSAndroid Build Coastguard Worker# usage: trace [-h] [-p PID] [-L TID] [-v] [-Z STRING_SIZE] [-S] [-c cgroup_path] 7*387f9dfdSAndroid Build Coastguard Worker# [-M MAX_EVENTS] [-s SYMBOLFILES] [-T] [-t] [-K] [-U] [-a] [-I header] 8*387f9dfdSAndroid Build Coastguard Worker# [-A] 9*387f9dfdSAndroid Build Coastguard Worker# probe [probe ...] 10*387f9dfdSAndroid Build Coastguard Worker# 11*387f9dfdSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License") 12*387f9dfdSAndroid Build Coastguard Worker# Copyright (C) 2016 Sasha Goldshtein. 13*387f9dfdSAndroid Build Coastguard Worker 14*387f9dfdSAndroid Build Coastguard Workerfrom __future__ import print_function 15*387f9dfdSAndroid Build Coastguard Workerfrom bcc import BPF, USDT, StrcmpRewrite 16*387f9dfdSAndroid Build Coastguard Workerfrom functools import partial 17*387f9dfdSAndroid Build Coastguard Workerfrom time import strftime 18*387f9dfdSAndroid Build Coastguard Workerimport time 19*387f9dfdSAndroid Build Coastguard Workerimport argparse 20*387f9dfdSAndroid Build Coastguard Workerimport re 21*387f9dfdSAndroid Build Coastguard Workerimport ctypes as ct 22*387f9dfdSAndroid Build Coastguard Workerimport os 23*387f9dfdSAndroid Build Coastguard Workerimport traceback 24*387f9dfdSAndroid Build Coastguard Workerimport sys 25*387f9dfdSAndroid Build Coastguard Worker 26*387f9dfdSAndroid Build Coastguard Workerclass Probe(object): 27*387f9dfdSAndroid Build Coastguard Worker probe_count = 0 28*387f9dfdSAndroid Build Coastguard Worker streq_index = 0 29*387f9dfdSAndroid Build Coastguard Worker max_events = None 30*387f9dfdSAndroid Build Coastguard Worker event_count = 0 31*387f9dfdSAndroid Build Coastguard Worker first_ts = 0 32*387f9dfdSAndroid Build Coastguard Worker first_ts_real = None 33*387f9dfdSAndroid Build Coastguard Worker print_time = False 34*387f9dfdSAndroid Build Coastguard Worker print_unix_timestamp = False 35*387f9dfdSAndroid Build Coastguard Worker use_localtime = True 36*387f9dfdSAndroid Build Coastguard Worker time_field = False 37*387f9dfdSAndroid Build Coastguard Worker print_cpu = False 38*387f9dfdSAndroid Build Coastguard Worker print_address = False 39*387f9dfdSAndroid Build Coastguard Worker tgid = -1 40*387f9dfdSAndroid Build Coastguard Worker pid = -1 41*387f9dfdSAndroid Build Coastguard Worker uid = -1 42*387f9dfdSAndroid Build Coastguard Worker page_cnt = None 43*387f9dfdSAndroid Build Coastguard Worker build_id_enabled = False 44*387f9dfdSAndroid Build Coastguard Worker aggregate = False 45*387f9dfdSAndroid Build Coastguard Worker symcount = {} 46*387f9dfdSAndroid Build Coastguard Worker 47*387f9dfdSAndroid Build Coastguard Worker @classmethod 48*387f9dfdSAndroid Build Coastguard Worker def configure(cls, args): 49*387f9dfdSAndroid Build Coastguard Worker cls.max_events = args.max_events 50*387f9dfdSAndroid Build Coastguard Worker cls.print_time = args.timestamp or args.time 51*387f9dfdSAndroid Build Coastguard Worker cls.print_unix_timestamp = args.unix_timestamp 52*387f9dfdSAndroid Build Coastguard Worker cls.use_localtime = not args.timestamp 53*387f9dfdSAndroid Build Coastguard Worker cls.time_field = cls.print_time and (not cls.use_localtime) 54*387f9dfdSAndroid Build Coastguard Worker cls.print_cpu = args.print_cpu 55*387f9dfdSAndroid Build Coastguard Worker cls.print_address = args.address 56*387f9dfdSAndroid Build Coastguard Worker cls.first_ts = BPF.monotonic_time() 57*387f9dfdSAndroid Build Coastguard Worker cls.first_ts_real = time.time() 58*387f9dfdSAndroid Build Coastguard Worker cls.tgid = args.tgid or -1 59*387f9dfdSAndroid Build Coastguard Worker cls.pid = args.pid or -1 60*387f9dfdSAndroid Build Coastguard Worker cls.uid = args.uid or -1 61*387f9dfdSAndroid Build Coastguard Worker cls.page_cnt = args.buffer_pages 62*387f9dfdSAndroid Build Coastguard Worker cls.bin_cmp = args.bin_cmp 63*387f9dfdSAndroid Build Coastguard Worker cls.build_id_enabled = args.sym_file_list is not None 64*387f9dfdSAndroid Build Coastguard Worker cls.aggregate = args.aggregate 65*387f9dfdSAndroid Build Coastguard Worker if cls.aggregate and cls.max_events is None: 66*387f9dfdSAndroid Build Coastguard Worker raise ValueError("-M/--max-events should be specified" 67*387f9dfdSAndroid Build Coastguard Worker " with -A/--aggregate") 68*387f9dfdSAndroid Build Coastguard Worker 69*387f9dfdSAndroid Build Coastguard Worker def __init__(self, probe, string_size, kernel_stack, user_stack, 70*387f9dfdSAndroid Build Coastguard Worker cgroup_map_name, name, msg_filter): 71*387f9dfdSAndroid Build Coastguard Worker self.usdt = None 72*387f9dfdSAndroid Build Coastguard Worker self.streq_functions = "" 73*387f9dfdSAndroid Build Coastguard Worker self.raw_probe = probe 74*387f9dfdSAndroid Build Coastguard Worker self.string_size = string_size 75*387f9dfdSAndroid Build Coastguard Worker self.kernel_stack = kernel_stack 76*387f9dfdSAndroid Build Coastguard Worker self.user_stack = user_stack 77*387f9dfdSAndroid Build Coastguard Worker self.probe_user_list = set() 78*387f9dfdSAndroid Build Coastguard Worker Probe.probe_count += 1 79*387f9dfdSAndroid Build Coastguard Worker self._parse_probe() 80*387f9dfdSAndroid Build Coastguard Worker self.probe_num = Probe.probe_count 81*387f9dfdSAndroid Build Coastguard Worker self.probe_name = "probe_%s_%d" % \ 82*387f9dfdSAndroid Build Coastguard Worker (self._display_function(), self.probe_num) 83*387f9dfdSAndroid Build Coastguard Worker self.probe_name = re.sub(r'[^A-Za-z0-9_]', '_', 84*387f9dfdSAndroid Build Coastguard Worker self.probe_name) 85*387f9dfdSAndroid Build Coastguard Worker self.cgroup_map_name = cgroup_map_name 86*387f9dfdSAndroid Build Coastguard Worker if name is None: 87*387f9dfdSAndroid Build Coastguard Worker # An empty bytestring is always contained in the command 88*387f9dfdSAndroid Build Coastguard Worker # name so this will always succeed. 89*387f9dfdSAndroid Build Coastguard Worker self.name = b'' 90*387f9dfdSAndroid Build Coastguard Worker else: 91*387f9dfdSAndroid Build Coastguard Worker self.name = name.encode('ascii') 92*387f9dfdSAndroid Build Coastguard Worker self.msg_filter = msg_filter 93*387f9dfdSAndroid Build Coastguard Worker # compiler can generate proper codes for function 94*387f9dfdSAndroid Build Coastguard Worker # signatures with "syscall__" prefix 95*387f9dfdSAndroid Build Coastguard Worker if self.is_syscall_kprobe: 96*387f9dfdSAndroid Build Coastguard Worker self.probe_name = "syscall__" + self.probe_name[6:] 97*387f9dfdSAndroid Build Coastguard Worker 98*387f9dfdSAndroid Build Coastguard Worker def __str__(self): 99*387f9dfdSAndroid Build Coastguard Worker return "%s:%s:%s FLT=%s ACT=%s/%s" % (self.probe_type, 100*387f9dfdSAndroid Build Coastguard Worker self.library, self._display_function(), self.filter, 101*387f9dfdSAndroid Build Coastguard Worker self.types, self.values) 102*387f9dfdSAndroid Build Coastguard Worker 103*387f9dfdSAndroid Build Coastguard Worker def is_default_action(self): 104*387f9dfdSAndroid Build Coastguard Worker return self.python_format == "" 105*387f9dfdSAndroid Build Coastguard Worker 106*387f9dfdSAndroid Build Coastguard Worker def _bail(self, error): 107*387f9dfdSAndroid Build Coastguard Worker raise ValueError("error in probe '%s': %s" % 108*387f9dfdSAndroid Build Coastguard Worker (self.raw_probe, error)) 109*387f9dfdSAndroid Build Coastguard Worker 110*387f9dfdSAndroid Build Coastguard Worker def _parse_probe(self): 111*387f9dfdSAndroid Build Coastguard Worker text = self.raw_probe 112*387f9dfdSAndroid Build Coastguard Worker 113*387f9dfdSAndroid Build Coastguard Worker # There might be a function signature preceding the actual 114*387f9dfdSAndroid Build Coastguard Worker # filter/print part, or not. Find the probe specifier first -- 115*387f9dfdSAndroid Build Coastguard Worker # it ends with either a space or an open paren ( for the 116*387f9dfdSAndroid Build Coastguard Worker # function signature part. 117*387f9dfdSAndroid Build Coastguard Worker # opt. signature 118*387f9dfdSAndroid Build Coastguard Worker # probespec | rest 119*387f9dfdSAndroid Build Coastguard Worker # --------- ---------- -- 120*387f9dfdSAndroid Build Coastguard Worker (spec, sig, rest) = re.match(r'([^ \t\(]+)(\([^\(]*\))?(.*)', 121*387f9dfdSAndroid Build Coastguard Worker text).groups() 122*387f9dfdSAndroid Build Coastguard Worker 123*387f9dfdSAndroid Build Coastguard Worker self._parse_spec(spec) 124*387f9dfdSAndroid Build Coastguard Worker # Remove the parens 125*387f9dfdSAndroid Build Coastguard Worker self.signature = sig[1:-1] if sig else None 126*387f9dfdSAndroid Build Coastguard Worker if self.signature and self.probe_type in ['u', 't']: 127*387f9dfdSAndroid Build Coastguard Worker self._bail("USDT and tracepoint probes can't have " + 128*387f9dfdSAndroid Build Coastguard Worker "a function signature; use arg1, arg2, " + 129*387f9dfdSAndroid Build Coastguard Worker "... instead") 130*387f9dfdSAndroid Build Coastguard Worker 131*387f9dfdSAndroid Build Coastguard Worker text = rest.lstrip() 132*387f9dfdSAndroid Build Coastguard Worker # If we now have a (, wait for the balanced closing ) and that 133*387f9dfdSAndroid Build Coastguard Worker # will be the predicate 134*387f9dfdSAndroid Build Coastguard Worker self.filter = None 135*387f9dfdSAndroid Build Coastguard Worker if len(text) > 0 and text[0] == "(": 136*387f9dfdSAndroid Build Coastguard Worker balance = 1 137*387f9dfdSAndroid Build Coastguard Worker for i in range(1, len(text)): 138*387f9dfdSAndroid Build Coastguard Worker if text[i] == "(": 139*387f9dfdSAndroid Build Coastguard Worker balance += 1 140*387f9dfdSAndroid Build Coastguard Worker if text[i] == ")": 141*387f9dfdSAndroid Build Coastguard Worker balance -= 1 142*387f9dfdSAndroid Build Coastguard Worker if balance == 0: 143*387f9dfdSAndroid Build Coastguard Worker self._parse_filter(text[:i + 1]) 144*387f9dfdSAndroid Build Coastguard Worker text = text[i + 1:] 145*387f9dfdSAndroid Build Coastguard Worker break 146*387f9dfdSAndroid Build Coastguard Worker if self.filter is None: 147*387f9dfdSAndroid Build Coastguard Worker self._bail("unmatched end of predicate") 148*387f9dfdSAndroid Build Coastguard Worker 149*387f9dfdSAndroid Build Coastguard Worker if self.filter is None: 150*387f9dfdSAndroid Build Coastguard Worker self.filter = "1" 151*387f9dfdSAndroid Build Coastguard Worker 152*387f9dfdSAndroid Build Coastguard Worker # The remainder of the text is the printf action 153*387f9dfdSAndroid Build Coastguard Worker self._parse_action(text.lstrip()) 154*387f9dfdSAndroid Build Coastguard Worker 155*387f9dfdSAndroid Build Coastguard Worker def _parse_offset(self, func_and_offset): 156*387f9dfdSAndroid Build Coastguard Worker func, offset_str = func_and_offset.split("+") 157*387f9dfdSAndroid Build Coastguard Worker try: 158*387f9dfdSAndroid Build Coastguard Worker if "x" in offset_str or "X" in offset_str: 159*387f9dfdSAndroid Build Coastguard Worker offset = int(offset_str, 16) 160*387f9dfdSAndroid Build Coastguard Worker else: 161*387f9dfdSAndroid Build Coastguard Worker offset = int(offset_str) 162*387f9dfdSAndroid Build Coastguard Worker except ValueError: 163*387f9dfdSAndroid Build Coastguard Worker self._bail("invalid offset format " + 164*387f9dfdSAndroid Build Coastguard Worker " '%s', must be decimal or hexadecimal" % offset_str) 165*387f9dfdSAndroid Build Coastguard Worker 166*387f9dfdSAndroid Build Coastguard Worker return func, offset 167*387f9dfdSAndroid Build Coastguard Worker 168*387f9dfdSAndroid Build Coastguard Worker def _parse_spec(self, spec): 169*387f9dfdSAndroid Build Coastguard Worker parts = spec.split(":") 170*387f9dfdSAndroid Build Coastguard Worker # Two special cases: 'func' means 'p::func', 'lib:func' means 171*387f9dfdSAndroid Build Coastguard Worker # 'p:lib:func'. Other combinations need to provide an empty 172*387f9dfdSAndroid Build Coastguard Worker # value between delimiters, e.g. 'r::func' for a kretprobe on 173*387f9dfdSAndroid Build Coastguard Worker # the function func. 174*387f9dfdSAndroid Build Coastguard Worker if len(parts) == 1: 175*387f9dfdSAndroid Build Coastguard Worker parts = ["p", "", parts[0]] 176*387f9dfdSAndroid Build Coastguard Worker elif len(parts) == 2: 177*387f9dfdSAndroid Build Coastguard Worker parts = ["p", parts[0], parts[1]] 178*387f9dfdSAndroid Build Coastguard Worker if len(parts[0]) == 0: 179*387f9dfdSAndroid Build Coastguard Worker self.probe_type = "p" 180*387f9dfdSAndroid Build Coastguard Worker elif parts[0] in ["p", "r", "t", "u"]: 181*387f9dfdSAndroid Build Coastguard Worker self.probe_type = parts[0] 182*387f9dfdSAndroid Build Coastguard Worker else: 183*387f9dfdSAndroid Build Coastguard Worker self._bail("probe type must be '', 'p', 't', 'r', " + 184*387f9dfdSAndroid Build Coastguard Worker "or 'u', but got '%s'" % parts[0]) 185*387f9dfdSAndroid Build Coastguard Worker self.offset = 0 186*387f9dfdSAndroid Build Coastguard Worker if "+" in parts[-1]: 187*387f9dfdSAndroid Build Coastguard Worker parts[-1], self.offset = self._parse_offset(parts[-1]) 188*387f9dfdSAndroid Build Coastguard Worker 189*387f9dfdSAndroid Build Coastguard Worker if self.probe_type == "t": 190*387f9dfdSAndroid Build Coastguard Worker self.tp_category = parts[1] 191*387f9dfdSAndroid Build Coastguard Worker self.tp_event = parts[2] 192*387f9dfdSAndroid Build Coastguard Worker self.library = "" # kernel 193*387f9dfdSAndroid Build Coastguard Worker self.function = "" # from TRACEPOINT_PROBE 194*387f9dfdSAndroid Build Coastguard Worker elif self.probe_type == "u": 195*387f9dfdSAndroid Build Coastguard Worker # u:<library>[:<provider>]:<probe> where :<provider> is optional 196*387f9dfdSAndroid Build Coastguard Worker self.library = parts[1] 197*387f9dfdSAndroid Build Coastguard Worker self.usdt_name = ":".join(parts[2:]) 198*387f9dfdSAndroid Build Coastguard Worker self.function = "" # no function, just address 199*387f9dfdSAndroid Build Coastguard Worker # We will discover the USDT provider by matching on 200*387f9dfdSAndroid Build Coastguard Worker # the USDT name in the specified library 201*387f9dfdSAndroid Build Coastguard Worker self._find_usdt_probe() 202*387f9dfdSAndroid Build Coastguard Worker else: 203*387f9dfdSAndroid Build Coastguard Worker self.library = ':'.join(parts[1:-1]) 204*387f9dfdSAndroid Build Coastguard Worker self.function = parts[-1] 205*387f9dfdSAndroid Build Coastguard Worker 206*387f9dfdSAndroid Build Coastguard Worker # only x64 syscalls needs checking, no other syscall wrapper yet. 207*387f9dfdSAndroid Build Coastguard Worker self.is_syscall_kprobe = False 208*387f9dfdSAndroid Build Coastguard Worker if self.probe_type == "p" and len(self.library) == 0 and \ 209*387f9dfdSAndroid Build Coastguard Worker self.function[:10] == "__x64_sys_": 210*387f9dfdSAndroid Build Coastguard Worker self.is_syscall_kprobe = True 211*387f9dfdSAndroid Build Coastguard Worker 212*387f9dfdSAndroid Build Coastguard Worker def _find_usdt_probe(self): 213*387f9dfdSAndroid Build Coastguard Worker target = Probe.pid if Probe.pid and Probe.pid != -1 \ 214*387f9dfdSAndroid Build Coastguard Worker else Probe.tgid 215*387f9dfdSAndroid Build Coastguard Worker self.usdt = USDT(path=self.library, pid=target) 216*387f9dfdSAndroid Build Coastguard Worker 217*387f9dfdSAndroid Build Coastguard Worker parts = self.usdt_name.split(":") 218*387f9dfdSAndroid Build Coastguard Worker if len(parts) == 1: 219*387f9dfdSAndroid Build Coastguard Worker provider_name = None 220*387f9dfdSAndroid Build Coastguard Worker usdt_name = parts[0].encode("ascii") 221*387f9dfdSAndroid Build Coastguard Worker else: 222*387f9dfdSAndroid Build Coastguard Worker provider_name = parts[0].encode("ascii") 223*387f9dfdSAndroid Build Coastguard Worker usdt_name = parts[1].encode("ascii") 224*387f9dfdSAndroid Build Coastguard Worker for probe in self.usdt.enumerate_probes(): 225*387f9dfdSAndroid Build Coastguard Worker if ((not provider_name or probe.provider == provider_name) 226*387f9dfdSAndroid Build Coastguard Worker and probe.name == usdt_name): 227*387f9dfdSAndroid Build Coastguard Worker return # Found it, will enable later 228*387f9dfdSAndroid Build Coastguard Worker self._bail("unrecognized USDT probe %s" % self.usdt_name) 229*387f9dfdSAndroid Build Coastguard Worker 230*387f9dfdSAndroid Build Coastguard Worker def _parse_filter(self, filt): 231*387f9dfdSAndroid Build Coastguard Worker self.filter = self._rewrite_expr(filt) 232*387f9dfdSAndroid Build Coastguard Worker 233*387f9dfdSAndroid Build Coastguard Worker def _parse_types(self, fmt): 234*387f9dfdSAndroid Build Coastguard Worker for match in re.finditer( 235*387f9dfdSAndroid Build Coastguard Worker r'[^%]%(s|u|d|lu|llu|ld|lld|hu|hd|x|lx|llx|c|K|U)', fmt): 236*387f9dfdSAndroid Build Coastguard Worker self.types.append(match.group(1)) 237*387f9dfdSAndroid Build Coastguard Worker fmt = re.sub(r'([^%]%)(u|d|lu|llu|ld|lld|hu|hd)', r'\1d', fmt) 238*387f9dfdSAndroid Build Coastguard Worker fmt = re.sub(r'([^%]%)(x|lx|llx)', r'\1x', fmt) 239*387f9dfdSAndroid Build Coastguard Worker fmt = re.sub('%K|%U', '%s', fmt) 240*387f9dfdSAndroid Build Coastguard Worker self.python_format = fmt.strip('"') 241*387f9dfdSAndroid Build Coastguard Worker 242*387f9dfdSAndroid Build Coastguard Worker def _parse_action(self, action): 243*387f9dfdSAndroid Build Coastguard Worker self.values = [] 244*387f9dfdSAndroid Build Coastguard Worker self.types = [] 245*387f9dfdSAndroid Build Coastguard Worker self.python_format = "" 246*387f9dfdSAndroid Build Coastguard Worker if len(action) == 0: 247*387f9dfdSAndroid Build Coastguard Worker return 248*387f9dfdSAndroid Build Coastguard Worker 249*387f9dfdSAndroid Build Coastguard Worker action = action.strip() 250*387f9dfdSAndroid Build Coastguard Worker match = re.search(r'(\".*?\"),?(.*)', action) 251*387f9dfdSAndroid Build Coastguard Worker if match is None: 252*387f9dfdSAndroid Build Coastguard Worker self._bail("expected format string in \"s") 253*387f9dfdSAndroid Build Coastguard Worker 254*387f9dfdSAndroid Build Coastguard Worker self.raw_format = match.group(1) 255*387f9dfdSAndroid Build Coastguard Worker self._parse_types(self.raw_format) 256*387f9dfdSAndroid Build Coastguard Worker for part in re.split('(?<!"),', match.group(2)): 257*387f9dfdSAndroid Build Coastguard Worker part = self._rewrite_expr(part) 258*387f9dfdSAndroid Build Coastguard Worker if len(part) > 0: 259*387f9dfdSAndroid Build Coastguard Worker self.values.append(part) 260*387f9dfdSAndroid Build Coastguard Worker 261*387f9dfdSAndroid Build Coastguard Worker aliases_arg = { 262*387f9dfdSAndroid Build Coastguard Worker "arg1": "PT_REGS_PARM1(ctx)", 263*387f9dfdSAndroid Build Coastguard Worker "arg2": "PT_REGS_PARM2(ctx)", 264*387f9dfdSAndroid Build Coastguard Worker "arg3": "PT_REGS_PARM3(ctx)", 265*387f9dfdSAndroid Build Coastguard Worker "arg4": "PT_REGS_PARM4(ctx)", 266*387f9dfdSAndroid Build Coastguard Worker "arg5": "PT_REGS_PARM5(ctx)", 267*387f9dfdSAndroid Build Coastguard Worker "arg6": "PT_REGS_PARM6(ctx)", 268*387f9dfdSAndroid Build Coastguard Worker } 269*387f9dfdSAndroid Build Coastguard Worker 270*387f9dfdSAndroid Build Coastguard Worker aliases_indarg = { 271*387f9dfdSAndroid Build Coastguard Worker "arg1": "({u64 _val; struct pt_regs *_ctx = (struct pt_regs *)PT_REGS_PARM1(ctx);" 272*387f9dfdSAndroid Build Coastguard Worker " bpf_probe_read_kernel(&_val, sizeof(_val), &(PT_REGS_PARM1(_ctx))); _val;})", 273*387f9dfdSAndroid Build Coastguard Worker "arg2": "({u64 _val; struct pt_regs *_ctx = (struct pt_regs *)PT_REGS_PARM1(ctx);" 274*387f9dfdSAndroid Build Coastguard Worker " bpf_probe_read_kernel(&_val, sizeof(_val), &(PT_REGS_PARM2(_ctx))); _val;})", 275*387f9dfdSAndroid Build Coastguard Worker "arg3": "({u64 _val; struct pt_regs *_ctx = (struct pt_regs *)PT_REGS_PARM1(ctx);" 276*387f9dfdSAndroid Build Coastguard Worker " bpf_probe_read_kernel(&_val, sizeof(_val), &(PT_REGS_PARM3(_ctx))); _val;})", 277*387f9dfdSAndroid Build Coastguard Worker "arg4": "({u64 _val; struct pt_regs *_ctx = (struct pt_regs *)PT_REGS_PARM1(ctx);" 278*387f9dfdSAndroid Build Coastguard Worker " bpf_probe_read_kernel(&_val, sizeof(_val), &(PT_REGS_PARM4(_ctx))); _val;})", 279*387f9dfdSAndroid Build Coastguard Worker "arg5": "({u64 _val; struct pt_regs *_ctx = (struct pt_regs *)PT_REGS_PARM1(ctx);" 280*387f9dfdSAndroid Build Coastguard Worker " bpf_probe_read_kernel(&_val, sizeof(_val), &(PT_REGS_PARM5(_ctx))); _val;})", 281*387f9dfdSAndroid Build Coastguard Worker "arg6": "({u64 _val; struct pt_regs *_ctx = (struct pt_regs *)PT_REGS_PARM1(ctx);" 282*387f9dfdSAndroid Build Coastguard Worker " bpf_probe_read_kernel(&_val, sizeof(_val), &(PT_REGS_PARM6(_ctx))); _val;})", 283*387f9dfdSAndroid Build Coastguard Worker } 284*387f9dfdSAndroid Build Coastguard Worker 285*387f9dfdSAndroid Build Coastguard Worker aliases_common = { 286*387f9dfdSAndroid Build Coastguard Worker "retval": "PT_REGS_RC(ctx)", 287*387f9dfdSAndroid Build Coastguard Worker "$uid": "(unsigned)(bpf_get_current_uid_gid() & 0xffffffff)", 288*387f9dfdSAndroid Build Coastguard Worker "$gid": "(unsigned)(bpf_get_current_uid_gid() >> 32)", 289*387f9dfdSAndroid Build Coastguard Worker "$pid": "(unsigned)(bpf_get_current_pid_tgid() & 0xffffffff)", 290*387f9dfdSAndroid Build Coastguard Worker "$tgid": "(unsigned)(bpf_get_current_pid_tgid() >> 32)", 291*387f9dfdSAndroid Build Coastguard Worker "$cpu": "bpf_get_smp_processor_id()", 292*387f9dfdSAndroid Build Coastguard Worker "$task": "((struct task_struct *)bpf_get_current_task())" 293*387f9dfdSAndroid Build Coastguard Worker } 294*387f9dfdSAndroid Build Coastguard Worker 295*387f9dfdSAndroid Build Coastguard Worker def _rewrite_expr(self, expr): 296*387f9dfdSAndroid Build Coastguard Worker # Find the occurances of any arg[1-6]@user. Use it later to 297*387f9dfdSAndroid Build Coastguard Worker # identify bpf_probe_read_user 298*387f9dfdSAndroid Build Coastguard Worker for matches in re.finditer(r'(arg[1-6])(@user)', expr): 299*387f9dfdSAndroid Build Coastguard Worker if matches.group(1).strip() not in self.probe_user_list: 300*387f9dfdSAndroid Build Coastguard Worker self.probe_user_list.add(matches.group(1).strip()) 301*387f9dfdSAndroid Build Coastguard Worker # Remove @user occurrences from arg before resolving to its 302*387f9dfdSAndroid Build Coastguard Worker # corresponding aliases. 303*387f9dfdSAndroid Build Coastguard Worker expr = re.sub(r'(arg[1-6])@user', r'\1', expr) 304*387f9dfdSAndroid Build Coastguard Worker rdict = StrcmpRewrite.rewrite_expr(expr, 305*387f9dfdSAndroid Build Coastguard Worker self.bin_cmp, self.library, 306*387f9dfdSAndroid Build Coastguard Worker self.probe_user_list, self.streq_functions, 307*387f9dfdSAndroid Build Coastguard Worker Probe.streq_index) 308*387f9dfdSAndroid Build Coastguard Worker expr = rdict["expr"] 309*387f9dfdSAndroid Build Coastguard Worker self.streq_functions = rdict["streq_functions"] 310*387f9dfdSAndroid Build Coastguard Worker Probe.streq_index = rdict["probeid"] 311*387f9dfdSAndroid Build Coastguard Worker alias_to_check = Probe.aliases_indarg \ 312*387f9dfdSAndroid Build Coastguard Worker if self.is_syscall_kprobe \ 313*387f9dfdSAndroid Build Coastguard Worker else Probe.aliases_arg 314*387f9dfdSAndroid Build Coastguard Worker # For USDT probes, we replace argN values with the 315*387f9dfdSAndroid Build Coastguard Worker # actual arguments for that probe obtained using 316*387f9dfdSAndroid Build Coastguard Worker # bpf_readarg_N macros emitted at BPF construction. 317*387f9dfdSAndroid Build Coastguard Worker if not self.probe_type == "u": 318*387f9dfdSAndroid Build Coastguard Worker for alias, replacement in alias_to_check.items(): 319*387f9dfdSAndroid Build Coastguard Worker expr = expr.replace(alias, replacement) 320*387f9dfdSAndroid Build Coastguard Worker for alias, replacement in Probe.aliases_common.items(): 321*387f9dfdSAndroid Build Coastguard Worker expr = expr.replace(alias, replacement) 322*387f9dfdSAndroid Build Coastguard Worker return expr 323*387f9dfdSAndroid Build Coastguard Worker 324*387f9dfdSAndroid Build Coastguard Worker c_type = {"u": "unsigned int", "d": "int", 325*387f9dfdSAndroid Build Coastguard Worker "lu": "unsigned long", "ld": "long", 326*387f9dfdSAndroid Build Coastguard Worker "llu": "unsigned long long", "lld": "long long", 327*387f9dfdSAndroid Build Coastguard Worker "hu": "unsigned short", "hd": "short", 328*387f9dfdSAndroid Build Coastguard Worker "x": "unsigned int", "lx": "unsigned long", 329*387f9dfdSAndroid Build Coastguard Worker "llx": "unsigned long long", 330*387f9dfdSAndroid Build Coastguard Worker "c": "char", "K": "unsigned long long", 331*387f9dfdSAndroid Build Coastguard Worker "U": "unsigned long long"} 332*387f9dfdSAndroid Build Coastguard Worker fmt_types = c_type.keys() 333*387f9dfdSAndroid Build Coastguard Worker 334*387f9dfdSAndroid Build Coastguard Worker def _generate_field_decl(self, idx): 335*387f9dfdSAndroid Build Coastguard Worker field_type = self.types[idx] 336*387f9dfdSAndroid Build Coastguard Worker if field_type == "s": 337*387f9dfdSAndroid Build Coastguard Worker return "char v%d[%d];\n" % (idx, self.string_size) 338*387f9dfdSAndroid Build Coastguard Worker if field_type in Probe.fmt_types: 339*387f9dfdSAndroid Build Coastguard Worker return "%s v%d;\n" % (Probe.c_type[field_type], idx) 340*387f9dfdSAndroid Build Coastguard Worker self._bail("unrecognized format specifier %s" % field_type) 341*387f9dfdSAndroid Build Coastguard Worker 342*387f9dfdSAndroid Build Coastguard Worker def _generate_data_decl(self): 343*387f9dfdSAndroid Build Coastguard Worker # The BPF program will populate values into the struct 344*387f9dfdSAndroid Build Coastguard Worker # according to the format string, and the Python program will 345*387f9dfdSAndroid Build Coastguard Worker # construct the final display string. 346*387f9dfdSAndroid Build Coastguard Worker self.events_name = "%s_events" % self.probe_name 347*387f9dfdSAndroid Build Coastguard Worker self.struct_name = "%s_data_t" % self.probe_name 348*387f9dfdSAndroid Build Coastguard Worker self.stacks_name = "%s_stacks" % self.probe_name 349*387f9dfdSAndroid Build Coastguard Worker stack_type = "BPF_STACK_TRACE" if self.build_id_enabled is False \ 350*387f9dfdSAndroid Build Coastguard Worker else "BPF_STACK_TRACE_BUILDID" 351*387f9dfdSAndroid Build Coastguard Worker stack_table = "%s(%s, 1024);" % (stack_type, self.stacks_name) \ 352*387f9dfdSAndroid Build Coastguard Worker if (self.kernel_stack or self.user_stack) else "" 353*387f9dfdSAndroid Build Coastguard Worker data_fields = "" 354*387f9dfdSAndroid Build Coastguard Worker for i, field_type in enumerate(self.types): 355*387f9dfdSAndroid Build Coastguard Worker data_fields += " " + \ 356*387f9dfdSAndroid Build Coastguard Worker self._generate_field_decl(i) 357*387f9dfdSAndroid Build Coastguard Worker time_str = "u64 timestamp_ns;" if self.time_field else "" 358*387f9dfdSAndroid Build Coastguard Worker cpu_str = "int cpu;" if self.print_cpu else "" 359*387f9dfdSAndroid Build Coastguard Worker kernel_stack_str = " int kernel_stack_id;" \ 360*387f9dfdSAndroid Build Coastguard Worker if self.kernel_stack else "" 361*387f9dfdSAndroid Build Coastguard Worker user_stack_str = " int user_stack_id;" \ 362*387f9dfdSAndroid Build Coastguard Worker if self.user_stack else "" 363*387f9dfdSAndroid Build Coastguard Worker 364*387f9dfdSAndroid Build Coastguard Worker text = """ 365*387f9dfdSAndroid Build Coastguard Workerstruct %s 366*387f9dfdSAndroid Build Coastguard Worker{ 367*387f9dfdSAndroid Build Coastguard Worker%s 368*387f9dfdSAndroid Build Coastguard Worker%s 369*387f9dfdSAndroid Build Coastguard Worker u32 tgid; 370*387f9dfdSAndroid Build Coastguard Worker u32 pid; 371*387f9dfdSAndroid Build Coastguard Worker char comm[TASK_COMM_LEN]; 372*387f9dfdSAndroid Build Coastguard Worker%s 373*387f9dfdSAndroid Build Coastguard Worker%s 374*387f9dfdSAndroid Build Coastguard Worker%s 375*387f9dfdSAndroid Build Coastguard Worker u32 uid; 376*387f9dfdSAndroid Build Coastguard Worker}; 377*387f9dfdSAndroid Build Coastguard Worker 378*387f9dfdSAndroid Build Coastguard WorkerBPF_PERF_OUTPUT(%s); 379*387f9dfdSAndroid Build Coastguard Worker%s 380*387f9dfdSAndroid Build Coastguard Worker""" 381*387f9dfdSAndroid Build Coastguard Worker return text % (self.struct_name, time_str, cpu_str, data_fields, 382*387f9dfdSAndroid Build Coastguard Worker kernel_stack_str, user_stack_str, 383*387f9dfdSAndroid Build Coastguard Worker self.events_name, stack_table) 384*387f9dfdSAndroid Build Coastguard Worker 385*387f9dfdSAndroid Build Coastguard Worker def _generate_field_assign(self, idx): 386*387f9dfdSAndroid Build Coastguard Worker field_type = self.types[idx] 387*387f9dfdSAndroid Build Coastguard Worker expr = self.values[idx].strip() 388*387f9dfdSAndroid Build Coastguard Worker text = "" 389*387f9dfdSAndroid Build Coastguard Worker if self.probe_type == "u" and expr[0:3] == "arg": 390*387f9dfdSAndroid Build Coastguard Worker arg_index = int(expr[3]) 391*387f9dfdSAndroid Build Coastguard Worker arg_ctype = self.usdt.get_probe_arg_ctype( 392*387f9dfdSAndroid Build Coastguard Worker self.usdt_name, arg_index - 1) 393*387f9dfdSAndroid Build Coastguard Worker text = (" %s %s = 0;\n" + 394*387f9dfdSAndroid Build Coastguard Worker " bpf_usdt_readarg(%s, ctx, &%s);\n") \ 395*387f9dfdSAndroid Build Coastguard Worker % (arg_ctype, expr, expr[3], expr) 396*387f9dfdSAndroid Build Coastguard Worker probe_read_func = "bpf_probe_read_kernel" 397*387f9dfdSAndroid Build Coastguard Worker if field_type == "s": 398*387f9dfdSAndroid Build Coastguard Worker if self.library: 399*387f9dfdSAndroid Build Coastguard Worker probe_read_func = "bpf_probe_read_user" 400*387f9dfdSAndroid Build Coastguard Worker else: 401*387f9dfdSAndroid Build Coastguard Worker alias_to_check = Probe.aliases_indarg \ 402*387f9dfdSAndroid Build Coastguard Worker if self.is_syscall_kprobe \ 403*387f9dfdSAndroid Build Coastguard Worker else Probe.aliases_arg 404*387f9dfdSAndroid Build Coastguard Worker for arg, alias in alias_to_check.items(): 405*387f9dfdSAndroid Build Coastguard Worker if alias == expr and arg in self.probe_user_list: 406*387f9dfdSAndroid Build Coastguard Worker probe_read_func = "bpf_probe_read_user" 407*387f9dfdSAndroid Build Coastguard Worker break 408*387f9dfdSAndroid Build Coastguard Worker return text + """ 409*387f9dfdSAndroid Build Coastguard Worker if (%s != 0) { 410*387f9dfdSAndroid Build Coastguard Worker void *__tmp = (void *)%s; 411*387f9dfdSAndroid Build Coastguard Worker %s(&__data.v%d, sizeof(__data.v%d), __tmp); 412*387f9dfdSAndroid Build Coastguard Worker } 413*387f9dfdSAndroid Build Coastguard Worker """ % (expr, expr, probe_read_func, idx, idx) 414*387f9dfdSAndroid Build Coastguard Worker if field_type in Probe.fmt_types: 415*387f9dfdSAndroid Build Coastguard Worker return text + " __data.v%d = (%s)%s;\n" % \ 416*387f9dfdSAndroid Build Coastguard Worker (idx, Probe.c_type[field_type], expr) 417*387f9dfdSAndroid Build Coastguard Worker self._bail("unrecognized field type %s" % field_type) 418*387f9dfdSAndroid Build Coastguard Worker 419*387f9dfdSAndroid Build Coastguard Worker def _generate_usdt_filter_read(self): 420*387f9dfdSAndroid Build Coastguard Worker text = "" 421*387f9dfdSAndroid Build Coastguard Worker if self.probe_type != "u": 422*387f9dfdSAndroid Build Coastguard Worker return text 423*387f9dfdSAndroid Build Coastguard Worker for arg, _ in Probe.aliases_arg.items(): 424*387f9dfdSAndroid Build Coastguard Worker if not (arg in self.filter): 425*387f9dfdSAndroid Build Coastguard Worker continue 426*387f9dfdSAndroid Build Coastguard Worker arg_index = int(arg.replace("arg", "")) 427*387f9dfdSAndroid Build Coastguard Worker arg_ctype = self.usdt.get_probe_arg_ctype( 428*387f9dfdSAndroid Build Coastguard Worker self.usdt_name, arg_index - 1) 429*387f9dfdSAndroid Build Coastguard Worker if not arg_ctype: 430*387f9dfdSAndroid Build Coastguard Worker self._bail("Unable to determine type of {} " 431*387f9dfdSAndroid Build Coastguard Worker "in the filter".format(arg)) 432*387f9dfdSAndroid Build Coastguard Worker text += """ 433*387f9dfdSAndroid Build Coastguard Worker {} {}_filter; 434*387f9dfdSAndroid Build Coastguard Worker bpf_usdt_readarg({}, ctx, &{}_filter); 435*387f9dfdSAndroid Build Coastguard Worker """.format(arg_ctype, arg, arg_index, arg) 436*387f9dfdSAndroid Build Coastguard Worker self.filter = self.filter.replace( 437*387f9dfdSAndroid Build Coastguard Worker arg, "{}_filter".format(arg)) 438*387f9dfdSAndroid Build Coastguard Worker return text 439*387f9dfdSAndroid Build Coastguard Worker 440*387f9dfdSAndroid Build Coastguard Worker def generate_program(self, include_self): 441*387f9dfdSAndroid Build Coastguard Worker data_decl = self._generate_data_decl() 442*387f9dfdSAndroid Build Coastguard Worker if Probe.pid != -1: 443*387f9dfdSAndroid Build Coastguard Worker pid_filter = """ 444*387f9dfdSAndroid Build Coastguard Worker if (__pid != %d) { return 0; } 445*387f9dfdSAndroid Build Coastguard Worker """ % Probe.pid 446*387f9dfdSAndroid Build Coastguard Worker # uprobes can have a built-in tgid filter passed to 447*387f9dfdSAndroid Build Coastguard Worker # attach_uprobe, hence the check here -- for kprobes, we 448*387f9dfdSAndroid Build Coastguard Worker # need to do the tgid test by hand: 449*387f9dfdSAndroid Build Coastguard Worker elif len(self.library) == 0 and Probe.tgid != -1: 450*387f9dfdSAndroid Build Coastguard Worker pid_filter = """ 451*387f9dfdSAndroid Build Coastguard Worker if (__tgid != %d) { return 0; } 452*387f9dfdSAndroid Build Coastguard Worker """ % Probe.tgid 453*387f9dfdSAndroid Build Coastguard Worker elif not include_self: 454*387f9dfdSAndroid Build Coastguard Worker pid_filter = """ 455*387f9dfdSAndroid Build Coastguard Worker if (__tgid == %d) { return 0; } 456*387f9dfdSAndroid Build Coastguard Worker """ % os.getpid() 457*387f9dfdSAndroid Build Coastguard Worker else: 458*387f9dfdSAndroid Build Coastguard Worker pid_filter = "" 459*387f9dfdSAndroid Build Coastguard Worker 460*387f9dfdSAndroid Build Coastguard Worker if Probe.uid != -1: 461*387f9dfdSAndroid Build Coastguard Worker uid_filter = """ 462*387f9dfdSAndroid Build Coastguard Worker if (__uid != %d) { return 0; } 463*387f9dfdSAndroid Build Coastguard Worker """ % Probe.uid 464*387f9dfdSAndroid Build Coastguard Worker else: 465*387f9dfdSAndroid Build Coastguard Worker uid_filter = "" 466*387f9dfdSAndroid Build Coastguard Worker 467*387f9dfdSAndroid Build Coastguard Worker if self.cgroup_map_name is not None: 468*387f9dfdSAndroid Build Coastguard Worker cgroup_filter = """ 469*387f9dfdSAndroid Build Coastguard Worker if (%s.check_current_task(0) <= 0) { return 0; } 470*387f9dfdSAndroid Build Coastguard Worker """ % self.cgroup_map_name 471*387f9dfdSAndroid Build Coastguard Worker else: 472*387f9dfdSAndroid Build Coastguard Worker cgroup_filter = "" 473*387f9dfdSAndroid Build Coastguard Worker 474*387f9dfdSAndroid Build Coastguard Worker prefix = "" 475*387f9dfdSAndroid Build Coastguard Worker signature = "struct pt_regs *ctx" 476*387f9dfdSAndroid Build Coastguard Worker if self.signature: 477*387f9dfdSAndroid Build Coastguard Worker signature += ", " + self.signature 478*387f9dfdSAndroid Build Coastguard Worker 479*387f9dfdSAndroid Build Coastguard Worker data_fields = "" 480*387f9dfdSAndroid Build Coastguard Worker for i, expr in enumerate(self.values): 481*387f9dfdSAndroid Build Coastguard Worker data_fields += self._generate_field_assign(i) 482*387f9dfdSAndroid Build Coastguard Worker 483*387f9dfdSAndroid Build Coastguard Worker if self.probe_type == "t": 484*387f9dfdSAndroid Build Coastguard Worker heading = "TRACEPOINT_PROBE(%s, %s)" % \ 485*387f9dfdSAndroid Build Coastguard Worker (self.tp_category, self.tp_event) 486*387f9dfdSAndroid Build Coastguard Worker ctx_name = "args" 487*387f9dfdSAndroid Build Coastguard Worker else: 488*387f9dfdSAndroid Build Coastguard Worker heading = "int %s(%s)" % (self.probe_name, signature) 489*387f9dfdSAndroid Build Coastguard Worker ctx_name = "ctx" 490*387f9dfdSAndroid Build Coastguard Worker 491*387f9dfdSAndroid Build Coastguard Worker time_str = """ 492*387f9dfdSAndroid Build Coastguard Worker __data.timestamp_ns = bpf_ktime_get_ns();""" if self.time_field else "" 493*387f9dfdSAndroid Build Coastguard Worker cpu_str = """ 494*387f9dfdSAndroid Build Coastguard Worker __data.cpu = bpf_get_smp_processor_id();""" if self.print_cpu else "" 495*387f9dfdSAndroid Build Coastguard Worker stack_trace = "" 496*387f9dfdSAndroid Build Coastguard Worker if self.user_stack: 497*387f9dfdSAndroid Build Coastguard Worker stack_trace += """ 498*387f9dfdSAndroid Build Coastguard Worker __data.user_stack_id = %s.get_stackid( 499*387f9dfdSAndroid Build Coastguard Worker %s, BPF_F_USER_STACK 500*387f9dfdSAndroid Build Coastguard Worker );""" % (self.stacks_name, ctx_name) 501*387f9dfdSAndroid Build Coastguard Worker if self.kernel_stack: 502*387f9dfdSAndroid Build Coastguard Worker stack_trace += """ 503*387f9dfdSAndroid Build Coastguard Worker __data.kernel_stack_id = %s.get_stackid( 504*387f9dfdSAndroid Build Coastguard Worker %s, 0 505*387f9dfdSAndroid Build Coastguard Worker );""" % (self.stacks_name, ctx_name) 506*387f9dfdSAndroid Build Coastguard Worker 507*387f9dfdSAndroid Build Coastguard Worker text = heading + """ 508*387f9dfdSAndroid Build Coastguard Worker{ 509*387f9dfdSAndroid Build Coastguard Worker u64 __pid_tgid = bpf_get_current_pid_tgid(); 510*387f9dfdSAndroid Build Coastguard Worker u32 __tgid = __pid_tgid >> 32; 511*387f9dfdSAndroid Build Coastguard Worker u32 __pid = __pid_tgid; // implicit cast to u32 for bottom half 512*387f9dfdSAndroid Build Coastguard Worker u32 __uid = bpf_get_current_uid_gid(); 513*387f9dfdSAndroid Build Coastguard Worker %s 514*387f9dfdSAndroid Build Coastguard Worker %s 515*387f9dfdSAndroid Build Coastguard Worker %s 516*387f9dfdSAndroid Build Coastguard Worker %s 517*387f9dfdSAndroid Build Coastguard Worker %s 518*387f9dfdSAndroid Build Coastguard Worker if (!(%s)) return 0; 519*387f9dfdSAndroid Build Coastguard Worker 520*387f9dfdSAndroid Build Coastguard Worker struct %s __data = {0}; 521*387f9dfdSAndroid Build Coastguard Worker %s 522*387f9dfdSAndroid Build Coastguard Worker %s 523*387f9dfdSAndroid Build Coastguard Worker __data.tgid = __tgid; 524*387f9dfdSAndroid Build Coastguard Worker __data.pid = __pid; 525*387f9dfdSAndroid Build Coastguard Worker __data.uid = __uid; 526*387f9dfdSAndroid Build Coastguard Worker bpf_get_current_comm(&__data.comm, sizeof(__data.comm)); 527*387f9dfdSAndroid Build Coastguard Worker%s 528*387f9dfdSAndroid Build Coastguard Worker%s 529*387f9dfdSAndroid Build Coastguard Worker %s.perf_submit(%s, &__data, sizeof(__data)); 530*387f9dfdSAndroid Build Coastguard Worker return 0; 531*387f9dfdSAndroid Build Coastguard Worker} 532*387f9dfdSAndroid Build Coastguard Worker""" 533*387f9dfdSAndroid Build Coastguard Worker text = text % (pid_filter, uid_filter, cgroup_filter, prefix, 534*387f9dfdSAndroid Build Coastguard Worker self._generate_usdt_filter_read(), self.filter, 535*387f9dfdSAndroid Build Coastguard Worker self.struct_name, time_str, cpu_str, data_fields, 536*387f9dfdSAndroid Build Coastguard Worker stack_trace, self.events_name, ctx_name) 537*387f9dfdSAndroid Build Coastguard Worker 538*387f9dfdSAndroid Build Coastguard Worker return self.streq_functions + data_decl + "\n" + text 539*387f9dfdSAndroid Build Coastguard Worker 540*387f9dfdSAndroid Build Coastguard Worker @classmethod 541*387f9dfdSAndroid Build Coastguard Worker def _time_off_str(cls, timestamp_ns): 542*387f9dfdSAndroid Build Coastguard Worker offset = 1e-9 * (timestamp_ns - cls.first_ts) 543*387f9dfdSAndroid Build Coastguard Worker if cls.print_unix_timestamp: 544*387f9dfdSAndroid Build Coastguard Worker return "%.6f" % (offset + cls.first_ts_real) 545*387f9dfdSAndroid Build Coastguard Worker else: 546*387f9dfdSAndroid Build Coastguard Worker return "%.6f" % offset 547*387f9dfdSAndroid Build Coastguard Worker 548*387f9dfdSAndroid Build Coastguard Worker def _display_function(self): 549*387f9dfdSAndroid Build Coastguard Worker if self.probe_type == 'p' or self.probe_type == 'r': 550*387f9dfdSAndroid Build Coastguard Worker return self.function 551*387f9dfdSAndroid Build Coastguard Worker elif self.probe_type == 'u': 552*387f9dfdSAndroid Build Coastguard Worker return self.usdt_name 553*387f9dfdSAndroid Build Coastguard Worker else: # self.probe_type == 't' 554*387f9dfdSAndroid Build Coastguard Worker return self.tp_event 555*387f9dfdSAndroid Build Coastguard Worker 556*387f9dfdSAndroid Build Coastguard Worker def _stack_to_string(self, bpf, stack_id, tgid): 557*387f9dfdSAndroid Build Coastguard Worker if stack_id < 0: 558*387f9dfdSAndroid Build Coastguard Worker return (" %d" % stack_id) 559*387f9dfdSAndroid Build Coastguard Worker 560*387f9dfdSAndroid Build Coastguard Worker stackstr = '' 561*387f9dfdSAndroid Build Coastguard Worker stack = list(bpf.get_table(self.stacks_name).walk(stack_id)) 562*387f9dfdSAndroid Build Coastguard Worker for addr in stack: 563*387f9dfdSAndroid Build Coastguard Worker stackstr += ' ' 564*387f9dfdSAndroid Build Coastguard Worker if Probe.print_address: 565*387f9dfdSAndroid Build Coastguard Worker stackstr += ("%16x " % addr) 566*387f9dfdSAndroid Build Coastguard Worker symstr = bpf.sym(addr, tgid, show_module=True, show_offset=True) 567*387f9dfdSAndroid Build Coastguard Worker stackstr += ('%s\n' % (symstr.decode('utf-8'))) 568*387f9dfdSAndroid Build Coastguard Worker 569*387f9dfdSAndroid Build Coastguard Worker return stackstr 570*387f9dfdSAndroid Build Coastguard Worker 571*387f9dfdSAndroid Build Coastguard Worker def _format_message(self, bpf, tgid, values): 572*387f9dfdSAndroid Build Coastguard Worker # Replace each %K with kernel sym and %U with user sym in tgid 573*387f9dfdSAndroid Build Coastguard Worker kernel_placeholders = [i for i, t in enumerate(self.types) 574*387f9dfdSAndroid Build Coastguard Worker if t == 'K'] 575*387f9dfdSAndroid Build Coastguard Worker user_placeholders = [i for i, t in enumerate(self.types) 576*387f9dfdSAndroid Build Coastguard Worker if t == 'U'] 577*387f9dfdSAndroid Build Coastguard Worker string_placeholders = [i for i, t in enumerate(self.types) 578*387f9dfdSAndroid Build Coastguard Worker if t == 's'] 579*387f9dfdSAndroid Build Coastguard Worker for kp in kernel_placeholders: 580*387f9dfdSAndroid Build Coastguard Worker values[kp] = bpf.ksym(values[kp], show_offset=True) 581*387f9dfdSAndroid Build Coastguard Worker for up in user_placeholders: 582*387f9dfdSAndroid Build Coastguard Worker values[up] = bpf.sym(values[up], tgid, 583*387f9dfdSAndroid Build Coastguard Worker show_module=True, show_offset=True) 584*387f9dfdSAndroid Build Coastguard Worker for sp in string_placeholders: 585*387f9dfdSAndroid Build Coastguard Worker values[sp] = values[sp].decode('utf-8', 'replace') 586*387f9dfdSAndroid Build Coastguard Worker return self.python_format % tuple(values) 587*387f9dfdSAndroid Build Coastguard Worker 588*387f9dfdSAndroid Build Coastguard Worker def print_aggregate_events(self): 589*387f9dfdSAndroid Build Coastguard Worker for k, v in sorted(self.symcount.items(), key=lambda item: \ 590*387f9dfdSAndroid Build Coastguard Worker item[1], reverse=True): 591*387f9dfdSAndroid Build Coastguard Worker print("%s-->COUNT %d\n\n" % (k, v), end="") 592*387f9dfdSAndroid Build Coastguard Worker 593*387f9dfdSAndroid Build Coastguard Worker def print_event(self, bpf, cpu, data, size): 594*387f9dfdSAndroid Build Coastguard Worker event = bpf[self.events_name].event(data) 595*387f9dfdSAndroid Build Coastguard Worker if self.name not in event.comm: 596*387f9dfdSAndroid Build Coastguard Worker return 597*387f9dfdSAndroid Build Coastguard Worker values = list(map(lambda i: getattr(event, "v%d" % i), 598*387f9dfdSAndroid Build Coastguard Worker range(0, len(self.values)))) 599*387f9dfdSAndroid Build Coastguard Worker msg = self._format_message(bpf, event.tgid, values) 600*387f9dfdSAndroid Build Coastguard Worker if self.msg_filter and self.msg_filter not in msg: 601*387f9dfdSAndroid Build Coastguard Worker return 602*387f9dfdSAndroid Build Coastguard Worker eventstr = '' 603*387f9dfdSAndroid Build Coastguard Worker if Probe.print_time: 604*387f9dfdSAndroid Build Coastguard Worker time = strftime("%H:%M:%S") if Probe.use_localtime else \ 605*387f9dfdSAndroid Build Coastguard Worker Probe._time_off_str(event.timestamp_ns) 606*387f9dfdSAndroid Build Coastguard Worker if Probe.print_unix_timestamp: 607*387f9dfdSAndroid Build Coastguard Worker eventstr += ("%-17s " % time[:17]) 608*387f9dfdSAndroid Build Coastguard Worker else: 609*387f9dfdSAndroid Build Coastguard Worker eventstr += ("%-8s " % time[:8]) 610*387f9dfdSAndroid Build Coastguard Worker if Probe.print_cpu: 611*387f9dfdSAndroid Build Coastguard Worker eventstr += ("%-3s " % event.cpu) 612*387f9dfdSAndroid Build Coastguard Worker eventstr += ("%-7d %-7d %-15s %-16s %s\n" % 613*387f9dfdSAndroid Build Coastguard Worker (event.tgid, event.pid, 614*387f9dfdSAndroid Build Coastguard Worker event.comm.decode('utf-8', 'replace'), 615*387f9dfdSAndroid Build Coastguard Worker self._display_function(), msg)) 616*387f9dfdSAndroid Build Coastguard Worker 617*387f9dfdSAndroid Build Coastguard Worker if self.kernel_stack: 618*387f9dfdSAndroid Build Coastguard Worker eventstr += self._stack_to_string(bpf, event.kernel_stack_id, -1) 619*387f9dfdSAndroid Build Coastguard Worker if self.user_stack: 620*387f9dfdSAndroid Build Coastguard Worker eventstr += self._stack_to_string(bpf, event.user_stack_id, event.tgid) 621*387f9dfdSAndroid Build Coastguard Worker 622*387f9dfdSAndroid Build Coastguard Worker if self.aggregate is False: 623*387f9dfdSAndroid Build Coastguard Worker print(eventstr, end="") 624*387f9dfdSAndroid Build Coastguard Worker if self.kernel_stack or self.user_stack: 625*387f9dfdSAndroid Build Coastguard Worker print("") 626*387f9dfdSAndroid Build Coastguard Worker else: 627*387f9dfdSAndroid Build Coastguard Worker if eventstr in self.symcount: 628*387f9dfdSAndroid Build Coastguard Worker self.symcount[eventstr] += 1 629*387f9dfdSAndroid Build Coastguard Worker else: 630*387f9dfdSAndroid Build Coastguard Worker self.symcount[eventstr] = 1 631*387f9dfdSAndroid Build Coastguard Worker 632*387f9dfdSAndroid Build Coastguard Worker Probe.event_count += 1 633*387f9dfdSAndroid Build Coastguard Worker if Probe.max_events is not None and \ 634*387f9dfdSAndroid Build Coastguard Worker Probe.event_count >= Probe.max_events: 635*387f9dfdSAndroid Build Coastguard Worker if self.aggregate: 636*387f9dfdSAndroid Build Coastguard Worker self.print_aggregate_events() 637*387f9dfdSAndroid Build Coastguard Worker sys.stdout.flush() 638*387f9dfdSAndroid Build Coastguard Worker exit() 639*387f9dfdSAndroid Build Coastguard Worker 640*387f9dfdSAndroid Build Coastguard Worker def attach(self, bpf, verbose): 641*387f9dfdSAndroid Build Coastguard Worker if len(self.library) == 0: 642*387f9dfdSAndroid Build Coastguard Worker self._attach_k(bpf) 643*387f9dfdSAndroid Build Coastguard Worker else: 644*387f9dfdSAndroid Build Coastguard Worker self._attach_u(bpf) 645*387f9dfdSAndroid Build Coastguard Worker callback = partial(self.print_event, bpf) 646*387f9dfdSAndroid Build Coastguard Worker bpf[self.events_name].open_perf_buffer(callback, 647*387f9dfdSAndroid Build Coastguard Worker page_cnt=self.page_cnt) 648*387f9dfdSAndroid Build Coastguard Worker 649*387f9dfdSAndroid Build Coastguard Worker def _attach_k(self, bpf): 650*387f9dfdSAndroid Build Coastguard Worker if self.probe_type == "r": 651*387f9dfdSAndroid Build Coastguard Worker bpf.attach_kretprobe(event=self.function, 652*387f9dfdSAndroid Build Coastguard Worker fn_name=self.probe_name) 653*387f9dfdSAndroid Build Coastguard Worker elif self.probe_type == "p": 654*387f9dfdSAndroid Build Coastguard Worker bpf.attach_kprobe(event=self.function, 655*387f9dfdSAndroid Build Coastguard Worker fn_name=self.probe_name, 656*387f9dfdSAndroid Build Coastguard Worker event_off=self.offset) 657*387f9dfdSAndroid Build Coastguard Worker # Note that tracepoints don't need an explicit attach 658*387f9dfdSAndroid Build Coastguard Worker 659*387f9dfdSAndroid Build Coastguard Worker def _attach_u(self, bpf): 660*387f9dfdSAndroid Build Coastguard Worker libpath = BPF.find_library(self.library) 661*387f9dfdSAndroid Build Coastguard Worker if libpath is None: 662*387f9dfdSAndroid Build Coastguard Worker # This might be an executable (e.g. 'bash') 663*387f9dfdSAndroid Build Coastguard Worker libpath = BPF.find_exe(self.library) 664*387f9dfdSAndroid Build Coastguard Worker if libpath is None or len(libpath) == 0: 665*387f9dfdSAndroid Build Coastguard Worker self._bail("unable to find library %s" % self.library) 666*387f9dfdSAndroid Build Coastguard Worker 667*387f9dfdSAndroid Build Coastguard Worker if self.probe_type == "u": 668*387f9dfdSAndroid Build Coastguard Worker pass # Was already enabled by the BPF constructor 669*387f9dfdSAndroid Build Coastguard Worker elif self.probe_type == "r": 670*387f9dfdSAndroid Build Coastguard Worker bpf.attach_uretprobe(name=libpath, 671*387f9dfdSAndroid Build Coastguard Worker sym=self.function, 672*387f9dfdSAndroid Build Coastguard Worker fn_name=self.probe_name, 673*387f9dfdSAndroid Build Coastguard Worker pid=Probe.tgid) 674*387f9dfdSAndroid Build Coastguard Worker else: 675*387f9dfdSAndroid Build Coastguard Worker bpf.attach_uprobe(name=libpath, 676*387f9dfdSAndroid Build Coastguard Worker sym=self.function, 677*387f9dfdSAndroid Build Coastguard Worker fn_name=self.probe_name, 678*387f9dfdSAndroid Build Coastguard Worker pid=Probe.tgid, 679*387f9dfdSAndroid Build Coastguard Worker sym_off=self.offset) 680*387f9dfdSAndroid Build Coastguard Worker 681*387f9dfdSAndroid Build Coastguard Workerclass Tool(object): 682*387f9dfdSAndroid Build Coastguard Worker DEFAULT_PERF_BUFFER_PAGES = 64 683*387f9dfdSAndroid Build Coastguard Worker examples = """ 684*387f9dfdSAndroid Build Coastguard WorkerEXAMPLES: 685*387f9dfdSAndroid Build Coastguard Worker 686*387f9dfdSAndroid Build Coastguard Workertrace do_sys_open 687*387f9dfdSAndroid Build Coastguard Worker Trace the open syscall and print a default trace message when entered 688*387f9dfdSAndroid Build Coastguard Workertrace kfree_skb+0x12 689*387f9dfdSAndroid Build Coastguard Worker Trace the kfree_skb kernel function after the instruction on the 0x12 offset 690*387f9dfdSAndroid Build Coastguard Workertrace 'do_sys_open "%s", arg2@user' 691*387f9dfdSAndroid Build Coastguard Worker Trace the open syscall and print the filename being opened @user is 692*387f9dfdSAndroid Build Coastguard Worker added to arg2 in kprobes to ensure that char * should be copied from 693*387f9dfdSAndroid Build Coastguard Worker the userspace stack to the bpf stack. If not specified, previous 694*387f9dfdSAndroid Build Coastguard Worker behaviour is expected. 695*387f9dfdSAndroid Build Coastguard Worker 696*387f9dfdSAndroid Build Coastguard Workertrace 'do_sys_open "%s", arg2@user' -n main 697*387f9dfdSAndroid Build Coastguard Worker Trace the open syscall and only print event that process names containing "main" 698*387f9dfdSAndroid Build Coastguard Workertrace 'do_sys_open "%s", arg2@user' --uid 1001 699*387f9dfdSAndroid Build Coastguard Worker Trace the open syscall and only print event that processes with user ID 1001 700*387f9dfdSAndroid Build Coastguard Workertrace 'do_sys_open "%s", arg2@user' -f config 701*387f9dfdSAndroid Build Coastguard Worker Trace the open syscall and print the filename being opened filtered by "config" 702*387f9dfdSAndroid Build Coastguard Workertrace 'sys_read (arg3 > 20000) "read %d bytes", arg3' 703*387f9dfdSAndroid Build Coastguard Worker Trace the read syscall and print a message for reads >20000 bytes 704*387f9dfdSAndroid Build Coastguard Workertrace 'r::do_sys_open "%llx", retval' 705*387f9dfdSAndroid Build Coastguard Worker Trace the return from the open syscall and print the return value 706*387f9dfdSAndroid Build Coastguard Workertrace 'c:open (arg2 == 42) "%s %d", arg1, arg2' 707*387f9dfdSAndroid Build Coastguard Worker Trace the open() call from libc only if the flags (arg2) argument is 42 708*387f9dfdSAndroid Build Coastguard Workertrace 'c:malloc "size = %d", arg1' 709*387f9dfdSAndroid Build Coastguard Worker Trace malloc calls and print the size being allocated 710*387f9dfdSAndroid Build Coastguard Workertrace 'p:c:write (arg1 == 1) "writing %d bytes to STDOUT", arg3' 711*387f9dfdSAndroid Build Coastguard Worker Trace the write() call from libc to monitor writes to STDOUT 712*387f9dfdSAndroid Build Coastguard Workertrace 'r::__kmalloc (retval == 0) "kmalloc failed!"' 713*387f9dfdSAndroid Build Coastguard Worker Trace returns from __kmalloc which returned a null pointer 714*387f9dfdSAndroid Build Coastguard Workertrace 'r:c:malloc (retval) "allocated = %x", retval' 715*387f9dfdSAndroid Build Coastguard Worker Trace returns from malloc and print non-NULL allocated buffers 716*387f9dfdSAndroid Build Coastguard Workertrace 't:block:block_rq_complete "sectors=%d", args->nr_sector' 717*387f9dfdSAndroid Build Coastguard Worker Trace the block_rq_complete kernel tracepoint and print # of tx sectors 718*387f9dfdSAndroid Build Coastguard Workertrace 'u:pthread:pthread_create (arg4 != 0)' 719*387f9dfdSAndroid Build Coastguard Worker Trace the USDT probe pthread_create when its 4th argument is non-zero 720*387f9dfdSAndroid Build Coastguard Workertrace 'u:pthread:libpthread:pthread_create (arg4 != 0)' 721*387f9dfdSAndroid Build Coastguard Worker Ditto, but the provider name "libpthread" is specified. 722*387f9dfdSAndroid Build Coastguard Workertrace 'p::SyS_nanosleep(struct timespec *ts) "sleep for %lld ns", ts->tv_nsec' 723*387f9dfdSAndroid Build Coastguard Worker Trace the nanosleep syscall and print the sleep duration in ns 724*387f9dfdSAndroid Build Coastguard Workertrace -c /sys/fs/cgroup/system.slice/workload.service '__x64_sys_nanosleep' '__x64_sys_clone' 725*387f9dfdSAndroid Build Coastguard Worker Trace nanosleep/clone syscall calls only under workload.service 726*387f9dfdSAndroid Build Coastguard Worker cgroup hierarchy. 727*387f9dfdSAndroid Build Coastguard Workertrace -I 'linux/fs.h' \\ 728*387f9dfdSAndroid Build Coastguard Worker 'p::uprobe_register(struct inode *inode) "a_ops = %llx", inode->i_mapping->a_ops' 729*387f9dfdSAndroid Build Coastguard Worker Trace the uprobe_register inode mapping ops, and the symbol can be found 730*387f9dfdSAndroid Build Coastguard Worker in /proc/kallsyms 731*387f9dfdSAndroid Build Coastguard Workertrace -I 'kernel/sched/sched.h' \\ 732*387f9dfdSAndroid Build Coastguard Worker 'p::__account_cfs_rq_runtime(struct cfs_rq *cfs_rq) "%d", cfs_rq->runtime_remaining' 733*387f9dfdSAndroid Build Coastguard Worker Trace the cfs scheduling runqueue remaining runtime. The struct cfs_rq is defined 734*387f9dfdSAndroid Build Coastguard Worker in kernel/sched/sched.h which is in kernel source tree and not in kernel-devel 735*387f9dfdSAndroid Build Coastguard Worker package. So this command needs to run at the kernel source tree root directory 736*387f9dfdSAndroid Build Coastguard Worker so that the added header file can be found by the compiler. 737*387f9dfdSAndroid Build Coastguard Workertrace -I 'net/sock.h' \\ 738*387f9dfdSAndroid Build Coastguard Worker 'udpv6_sendmsg(struct sock *sk) (sk->sk_dport == 13568)' 739*387f9dfdSAndroid Build Coastguard Worker Trace udpv6 sendmsg calls only if socket's destination port is equal 740*387f9dfdSAndroid Build Coastguard Worker to 53 (DNS; 13568 in big endian order) 741*387f9dfdSAndroid Build Coastguard Workertrace -I 'linux/fs_struct.h' 'mntns_install "users = %d", $task->fs->users' 742*387f9dfdSAndroid Build Coastguard Worker Trace the number of users accessing the file system of the current task 743*387f9dfdSAndroid Build Coastguard Workertrace -s /lib/x86_64-linux-gnu/libc.so.6,/bin/ping 'p:c:inet_pton' -U 744*387f9dfdSAndroid Build Coastguard Worker Trace inet_pton system call and use the specified libraries/executables for 745*387f9dfdSAndroid Build Coastguard Worker symbol resolution. 746*387f9dfdSAndroid Build Coastguard Worker""" 747*387f9dfdSAndroid Build Coastguard Worker 748*387f9dfdSAndroid Build Coastguard Worker def __init__(self): 749*387f9dfdSAndroid Build Coastguard Worker parser = argparse.ArgumentParser(description="Attach to " + 750*387f9dfdSAndroid Build Coastguard Worker "functions and print trace messages.", 751*387f9dfdSAndroid Build Coastguard Worker formatter_class=argparse.RawDescriptionHelpFormatter, 752*387f9dfdSAndroid Build Coastguard Worker epilog=Tool.examples) 753*387f9dfdSAndroid Build Coastguard Worker parser.add_argument("-b", "--buffer-pages", type=int, 754*387f9dfdSAndroid Build Coastguard Worker default=Tool.DEFAULT_PERF_BUFFER_PAGES, 755*387f9dfdSAndroid Build Coastguard Worker help="number of pages to use for perf_events ring buffer " 756*387f9dfdSAndroid Build Coastguard Worker "(default: %(default)d)") 757*387f9dfdSAndroid Build Coastguard Worker # we'll refer to the userspace concepts of "pid" and "tid" by 758*387f9dfdSAndroid Build Coastguard Worker # their kernel names -- tgid and pid -- inside the script 759*387f9dfdSAndroid Build Coastguard Worker parser.add_argument("-p", "--pid", type=int, metavar="PID", 760*387f9dfdSAndroid Build Coastguard Worker dest="tgid", help="id of the process to trace (optional)") 761*387f9dfdSAndroid Build Coastguard Worker parser.add_argument("-L", "--tid", type=int, metavar="TID", 762*387f9dfdSAndroid Build Coastguard Worker dest="pid", help="id of the thread to trace (optional)") 763*387f9dfdSAndroid Build Coastguard Worker parser.add_argument("--uid", type=int, metavar="UID", 764*387f9dfdSAndroid Build Coastguard Worker dest="uid", help="id of the user to trace (optional)") 765*387f9dfdSAndroid Build Coastguard Worker parser.add_argument("-v", "--verbose", action="store_true", 766*387f9dfdSAndroid Build Coastguard Worker help="print resulting BPF program code before executing") 767*387f9dfdSAndroid Build Coastguard Worker parser.add_argument("-Z", "--string-size", type=int, 768*387f9dfdSAndroid Build Coastguard Worker default=80, help="maximum size to read from strings") 769*387f9dfdSAndroid Build Coastguard Worker parser.add_argument("-S", "--include-self", 770*387f9dfdSAndroid Build Coastguard Worker action="store_true", 771*387f9dfdSAndroid Build Coastguard Worker help="do not filter trace's own pid from the trace") 772*387f9dfdSAndroid Build Coastguard Worker parser.add_argument("-M", "--max-events", type=int, 773*387f9dfdSAndroid Build Coastguard Worker help="number of events to print before quitting") 774*387f9dfdSAndroid Build Coastguard Worker parser.add_argument("-t", "--timestamp", action="store_true", 775*387f9dfdSAndroid Build Coastguard Worker help="print timestamp column (offset from trace start)") 776*387f9dfdSAndroid Build Coastguard Worker parser.add_argument("-u", "--unix-timestamp", action="store_true", 777*387f9dfdSAndroid Build Coastguard Worker help="print UNIX timestamp instead of offset from trace start, requires -t") 778*387f9dfdSAndroid Build Coastguard Worker parser.add_argument("-T", "--time", action="store_true", 779*387f9dfdSAndroid Build Coastguard Worker help="print time column") 780*387f9dfdSAndroid Build Coastguard Worker parser.add_argument("-C", "--print_cpu", action="store_true", 781*387f9dfdSAndroid Build Coastguard Worker help="print CPU id") 782*387f9dfdSAndroid Build Coastguard Worker parser.add_argument("-c", "--cgroup-path", type=str, 783*387f9dfdSAndroid Build Coastguard Worker metavar="CGROUP_PATH", dest="cgroup_path", 784*387f9dfdSAndroid Build Coastguard Worker help="cgroup path") 785*387f9dfdSAndroid Build Coastguard Worker parser.add_argument("-n", "--name", type=str, 786*387f9dfdSAndroid Build Coastguard Worker help="only print process names containing this name") 787*387f9dfdSAndroid Build Coastguard Worker parser.add_argument("-f", "--msg-filter", type=str, dest="msg_filter", 788*387f9dfdSAndroid Build Coastguard Worker help="only print the msg of event containing this string") 789*387f9dfdSAndroid Build Coastguard Worker parser.add_argument("-B", "--bin_cmp", action="store_true", 790*387f9dfdSAndroid Build Coastguard Worker help="allow to use STRCMP with binary values") 791*387f9dfdSAndroid Build Coastguard Worker parser.add_argument('-s', "--sym_file_list", type=str, 792*387f9dfdSAndroid Build Coastguard Worker metavar="SYM_FILE_LIST", dest="sym_file_list", 793*387f9dfdSAndroid Build Coastguard Worker help="comma separated list of symbol files to use \ 794*387f9dfdSAndroid Build Coastguard Worker for symbol resolution") 795*387f9dfdSAndroid Build Coastguard Worker parser.add_argument("-K", "--kernel-stack", 796*387f9dfdSAndroid Build Coastguard Worker action="store_true", help="output kernel stack trace") 797*387f9dfdSAndroid Build Coastguard Worker parser.add_argument("-U", "--user-stack", 798*387f9dfdSAndroid Build Coastguard Worker action="store_true", help="output user stack trace") 799*387f9dfdSAndroid Build Coastguard Worker parser.add_argument("-a", "--address", action="store_true", 800*387f9dfdSAndroid Build Coastguard Worker help="print virtual address in stacks") 801*387f9dfdSAndroid Build Coastguard Worker parser.add_argument(metavar="probe", dest="probes", nargs="+", 802*387f9dfdSAndroid Build Coastguard Worker help="probe specifier (see examples)") 803*387f9dfdSAndroid Build Coastguard Worker parser.add_argument("-I", "--include", action="append", 804*387f9dfdSAndroid Build Coastguard Worker metavar="header", 805*387f9dfdSAndroid Build Coastguard Worker help="additional header files to include in the BPF program " 806*387f9dfdSAndroid Build Coastguard Worker "as either full path, " 807*387f9dfdSAndroid Build Coastguard Worker "or relative to current working directory, " 808*387f9dfdSAndroid Build Coastguard Worker "or relative to default kernel header search path") 809*387f9dfdSAndroid Build Coastguard Worker parser.add_argument("-A", "--aggregate", action="store_true", 810*387f9dfdSAndroid Build Coastguard Worker help="aggregate amount of each trace") 811*387f9dfdSAndroid Build Coastguard Worker parser.add_argument("--ebpf", action="store_true", 812*387f9dfdSAndroid Build Coastguard Worker help=argparse.SUPPRESS) 813*387f9dfdSAndroid Build Coastguard Worker self.args = parser.parse_args() 814*387f9dfdSAndroid Build Coastguard Worker if self.args.tgid and self.args.pid: 815*387f9dfdSAndroid Build Coastguard Worker parser.error("only one of -p and -L may be specified") 816*387f9dfdSAndroid Build Coastguard Worker if self.args.cgroup_path is not None: 817*387f9dfdSAndroid Build Coastguard Worker self.cgroup_map_name = "__cgroup" 818*387f9dfdSAndroid Build Coastguard Worker else: 819*387f9dfdSAndroid Build Coastguard Worker self.cgroup_map_name = None 820*387f9dfdSAndroid Build Coastguard Worker 821*387f9dfdSAndroid Build Coastguard Worker def _create_probes(self): 822*387f9dfdSAndroid Build Coastguard Worker Probe.configure(self.args) 823*387f9dfdSAndroid Build Coastguard Worker self.probes = [] 824*387f9dfdSAndroid Build Coastguard Worker for probe_spec in self.args.probes: 825*387f9dfdSAndroid Build Coastguard Worker self.probes.append(Probe( 826*387f9dfdSAndroid Build Coastguard Worker probe_spec, self.args.string_size, 827*387f9dfdSAndroid Build Coastguard Worker self.args.kernel_stack, self.args.user_stack, 828*387f9dfdSAndroid Build Coastguard Worker self.cgroup_map_name, self.args.name, self.args.msg_filter)) 829*387f9dfdSAndroid Build Coastguard Worker 830*387f9dfdSAndroid Build Coastguard Worker def _generate_program(self): 831*387f9dfdSAndroid Build Coastguard Worker self.program = """ 832*387f9dfdSAndroid Build Coastguard Worker#include <linux/ptrace.h> 833*387f9dfdSAndroid Build Coastguard Worker#include <linux/sched.h> /* For TASK_COMM_LEN */ 834*387f9dfdSAndroid Build Coastguard Worker 835*387f9dfdSAndroid Build Coastguard Worker""" 836*387f9dfdSAndroid Build Coastguard Worker for include in (self.args.include or []): 837*387f9dfdSAndroid Build Coastguard Worker if include.startswith((".", "/")): 838*387f9dfdSAndroid Build Coastguard Worker include = os.path.abspath(include) 839*387f9dfdSAndroid Build Coastguard Worker self.program += "#include \"%s\"\n" % include 840*387f9dfdSAndroid Build Coastguard Worker else: 841*387f9dfdSAndroid Build Coastguard Worker self.program += "#include <%s>\n" % include 842*387f9dfdSAndroid Build Coastguard Worker self.program += BPF.generate_auto_includes( 843*387f9dfdSAndroid Build Coastguard Worker map(lambda p: p.raw_probe, self.probes)) 844*387f9dfdSAndroid Build Coastguard Worker if self.cgroup_map_name is not None: 845*387f9dfdSAndroid Build Coastguard Worker self.program += "BPF_CGROUP_ARRAY(%s, 1);\n" % \ 846*387f9dfdSAndroid Build Coastguard Worker self.cgroup_map_name 847*387f9dfdSAndroid Build Coastguard Worker for probe in self.probes: 848*387f9dfdSAndroid Build Coastguard Worker self.program += probe.generate_program( 849*387f9dfdSAndroid Build Coastguard Worker self.args.include_self) 850*387f9dfdSAndroid Build Coastguard Worker 851*387f9dfdSAndroid Build Coastguard Worker if self.args.verbose or self.args.ebpf: 852*387f9dfdSAndroid Build Coastguard Worker print(self.program) 853*387f9dfdSAndroid Build Coastguard Worker if self.args.ebpf: 854*387f9dfdSAndroid Build Coastguard Worker exit() 855*387f9dfdSAndroid Build Coastguard Worker 856*387f9dfdSAndroid Build Coastguard Worker def _attach_probes(self): 857*387f9dfdSAndroid Build Coastguard Worker usdt_contexts = [] 858*387f9dfdSAndroid Build Coastguard Worker for probe in self.probes: 859*387f9dfdSAndroid Build Coastguard Worker if probe.usdt: 860*387f9dfdSAndroid Build Coastguard Worker # USDT probes must be enabled before the BPF object 861*387f9dfdSAndroid Build Coastguard Worker # is initialized, because that's where the actual 862*387f9dfdSAndroid Build Coastguard Worker # uprobe is being attached. 863*387f9dfdSAndroid Build Coastguard Worker probe.usdt.enable_probe( 864*387f9dfdSAndroid Build Coastguard Worker probe.usdt_name, probe.probe_name) 865*387f9dfdSAndroid Build Coastguard Worker if self.args.verbose: 866*387f9dfdSAndroid Build Coastguard Worker print(probe.usdt.get_text()) 867*387f9dfdSAndroid Build Coastguard Worker usdt_contexts.append(probe.usdt) 868*387f9dfdSAndroid Build Coastguard Worker self.bpf = BPF(text=self.program, usdt_contexts=usdt_contexts) 869*387f9dfdSAndroid Build Coastguard Worker if self.args.sym_file_list is not None: 870*387f9dfdSAndroid Build Coastguard Worker print("Note: Kernel bpf will report stack map with ip/build_id") 871*387f9dfdSAndroid Build Coastguard Worker map(lambda x: self.bpf.add_module(x), self.args.sym_file_list.split(',')) 872*387f9dfdSAndroid Build Coastguard Worker 873*387f9dfdSAndroid Build Coastguard Worker # if cgroup filter is requested, update the cgroup array map 874*387f9dfdSAndroid Build Coastguard Worker if self.cgroup_map_name is not None: 875*387f9dfdSAndroid Build Coastguard Worker cgroup_array = self.bpf.get_table(self.cgroup_map_name) 876*387f9dfdSAndroid Build Coastguard Worker cgroup_array[0] = self.args.cgroup_path 877*387f9dfdSAndroid Build Coastguard Worker 878*387f9dfdSAndroid Build Coastguard Worker for probe in self.probes: 879*387f9dfdSAndroid Build Coastguard Worker if self.args.verbose: 880*387f9dfdSAndroid Build Coastguard Worker print(probe) 881*387f9dfdSAndroid Build Coastguard Worker probe.attach(self.bpf, self.args.verbose) 882*387f9dfdSAndroid Build Coastguard Worker 883*387f9dfdSAndroid Build Coastguard Worker def _main_loop(self): 884*387f9dfdSAndroid Build Coastguard Worker all_probes_trivial = all(map(Probe.is_default_action, 885*387f9dfdSAndroid Build Coastguard Worker self.probes)) 886*387f9dfdSAndroid Build Coastguard Worker 887*387f9dfdSAndroid Build Coastguard Worker # Print header 888*387f9dfdSAndroid Build Coastguard Worker if self.args.timestamp or self.args.time: 889*387f9dfdSAndroid Build Coastguard Worker col_fmt = "%-17s " if self.args.unix_timestamp else "%-8s " 890*387f9dfdSAndroid Build Coastguard Worker print(col_fmt % "TIME", end="") 891*387f9dfdSAndroid Build Coastguard Worker if self.args.print_cpu: 892*387f9dfdSAndroid Build Coastguard Worker print("%-3s " % "CPU", end="") 893*387f9dfdSAndroid Build Coastguard Worker print("%-7s %-7s %-15s %-16s %s" % 894*387f9dfdSAndroid Build Coastguard Worker ("PID", "TID", "COMM", "FUNC", 895*387f9dfdSAndroid Build Coastguard Worker "-" if not all_probes_trivial else "")) 896*387f9dfdSAndroid Build Coastguard Worker sys.stdout.flush() 897*387f9dfdSAndroid Build Coastguard Worker 898*387f9dfdSAndroid Build Coastguard Worker while True: 899*387f9dfdSAndroid Build Coastguard Worker self.bpf.perf_buffer_poll() 900*387f9dfdSAndroid Build Coastguard Worker 901*387f9dfdSAndroid Build Coastguard Worker def run(self): 902*387f9dfdSAndroid Build Coastguard Worker try: 903*387f9dfdSAndroid Build Coastguard Worker self._create_probes() 904*387f9dfdSAndroid Build Coastguard Worker self._generate_program() 905*387f9dfdSAndroid Build Coastguard Worker self._attach_probes() 906*387f9dfdSAndroid Build Coastguard Worker self._main_loop() 907*387f9dfdSAndroid Build Coastguard Worker except: 908*387f9dfdSAndroid Build Coastguard Worker exc_info = sys.exc_info() 909*387f9dfdSAndroid Build Coastguard Worker sys_exit = exc_info[0] is SystemExit 910*387f9dfdSAndroid Build Coastguard Worker if self.args.verbose: 911*387f9dfdSAndroid Build Coastguard Worker traceback.print_exc() 912*387f9dfdSAndroid Build Coastguard Worker elif not sys_exit: 913*387f9dfdSAndroid Build Coastguard Worker print(exc_info[1]) 914*387f9dfdSAndroid Build Coastguard Worker exit(0 if sys_exit else 1) 915*387f9dfdSAndroid Build Coastguard Worker 916*387f9dfdSAndroid Build Coastguard Workerif __name__ == "__main__": 917*387f9dfdSAndroid Build Coastguard Worker Tool().run() 918