
    fu
                    l   d dl mZ d dlZd dlZd dlZd dlZd dlZd dlZd dl	Z	d dl
Z
d dlZddlmZmZmZmZmZ ddlmZmZmZmZmZ ddlmZ ddlmZmZmZmZmZ ddl m!Z! dd	l"m#Z#m$Z$ dd
l%m&Z&m'Z' 	 e( dZ+d a,d Z-dZ.ej^                  ja                  e.d      Z1ej^                  je                  e1      sdZ1dZ3dZ4dZ5dZ6dZ7dZ8 G d de9      Z: G d d      Z; G d d      Z< G d d      Z= G d d      Z> G d d       Z? G d! d"      Z@ G d# d$      ZA G d% d&      ZB G d' d(e9      ZCy# e)$ r e*Z(Y w xY w))    )print_functionN   )lib
bcc_symbolbcc_symbol_optionbcc_stacktrace_build_id_SYM_CB_TYPE)TablePerfEventArrayRingBufBPF_MAP_TYPE_QUEUEBPF_MAP_TYPE_STACK)Perf)get_online_cpusprintb_assert_is_bytes	ArgStringStrcmpRewrite)__version__)disassemble_prog
decode_map)USDTUSDTExceptioni  c                      t         S N)_num_open_probes     ./usr/lib/python3/dist-packages/bcc/__init__.py_get_num_open_probesr    +   s    r   z/sys/kernel/debugtracingz/sys/kernel/tracing                c                       e Zd Zd Zd Zd Zy)SymbolCachec           	          t        j                  |t        j                  d t        j                  t
                          | _        y r   )r   bcc_symcache_newctcastPOINTERr   cache)selfpids     r   __init__zSymbolCache.__init__D   s/    ))RWWT2::.?#@AC
r   c                    t               }|r5t        j                  | j                  |t	        j
                  |            }n4t        j                  | j                  |t	        j
                  |            }|dk  rb|j                  rQ|j                  rEd|j                  t	        j                  |j                  t        j                        j                  fS d|dfS |r5|j                  }t        j                  t	        j
                  |             n|j                  }||j                  t	        j                  |j                  t        j                        j                  fS )a  
        Return a tuple of the symbol (function), its offset from the beginning
        of the function, and the module in which it lies. For example:
            ("start_thread", 0x202, "/usr/lib/.../libpthread-2.24.so")
        If the symbol cannot be found but we know which module it is in,
        return the module name and the offset from the beginning of the
        module. If we don't even know the module, return the absolute
        address as the offset.
        r   N)r   r   bcc_symcache_resolver.   r+   byref bcc_symcache_resolve_no_demanglemoduleoffsetr,   c_char_pvaluedemangle_namebcc_symbol_free_demangle_namename)r/   addrdemanglesymresname_ress         r   resolvezSymbolCache.resolveH   s     l**4::tRXXc]KC66tzz479xx}FC7zzcjjcjj

BKK8>>@ @$%%((H--bhhsm<xxH#**bggcjj"++&F&L&LMMr   c                     t        |      }t        |      }t        j                         }t        j                  | j
                  ||t        j                  |            dk  ry|j                  S )Nr   )r   r+   c_ulonglongr   bcc_symcache_resolve_namer.   r4   r9   )r/   r6   r<   r=   s       r   resolve_namezSymbolCache.resolve_namee   sZ    !&)%~~((VT "#$zzr   N)__name__
__module____qualname__r1   rB   rG   r   r   r   r(   r(   C   s    CN:r   r(   c                   $    e Zd ZdZdZdZdZdZdZy)PerfTyper   r   r"      r#      N)	rH   rI   rJ   HARDWARESOFTWARE
TRACEPOINTHW_CACHERAW
BREAKPOINTr   r   r   rL   rL   n   s     HHJH
CJr   rL   c                   4    e Zd ZdZdZdZdZdZdZdZ	dZ
d	Zd
Zy)PerfHWConfigr   r   r"   rM   r#   rN         r$   	   N)rH   rI   rJ   
CPU_CYCLESINSTRUCTIONSCACHE_REFERENCESCACHE_MISSESBRANCH_INSTRUCTIONSBRANCH_MISSES
BUS_CYCLESSTALLED_CYCLES_FRONTENDSTALLED_CYCLES_BACKENDREF_CPU_CYCLESr   r   r   rV   rV   w   s8    JLLMJNr   rV   c                   8    e Zd ZdZdZdZdZdZdZdZ	dZ
d	Zd
ZdZy)PerfSWConfigr   r   r"   rM   r#   rN   rW   rX   r$   rY   
   N)rH   rI   rJ   	CPU_CLOCK
TASK_CLOCKPAGE_FAULTSCONTEXT_SWITCHESCPU_MIGRATIONSPAGE_FAULTS_MINPAGE_FAULTS_MAJALIGNMENT_FAULTSEMULATION_FAULTSDUMMY
BPF_OUTPUTr   r   r   re   re      s<    IJKNOOEJr   re   c                   p    e Zd ZdZdZdZdZdZdZdZ	dZ
d	Zd
ZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZy)PerfEventSampleFormatr   r"   r#   r$   r%   r&   @         i      i   i   i    i @  i   i   i   i   i   i   i    i  @ i   i   N)rH   rI   rJ   IPTIDTIMEADDRREAD	CALLCHAINIDCPUPERIOD	STREAM_IDrS   BRANCH_STACK	REGS_USER
STACK_USERWEIGHTDATA_SRC
IDENTIFIERTRANSACTION	REGS_INTR	PHYS_ADDRAUXCGROUPDATA_PAGE_SIZECODE_PAGE_SIZEWEIGHT_STRUCTr   r   r   rs   rs      s    
BCDDDI
BCFICLIJFHJKIICFNNMr   rs   c                   `    e Zd ZdZdZdZdZdZdZdZ	dZ
d	Zd
ZdZdZdZdZdZdZdZdZdZdZdZy)BPFProgTyper   r"   rM   r#   rN   rW   rX   r$   rY   rf                  r%                  N)rH   rI   rJ   SOCKET_FILTERKPROBE	SCHED_CLS	SCHED_ACTrQ   XDP
PERF_EVENT
CGROUP_SKBCGROUP_SOCKLWT_INLWT_OUTLWT_XMITSOCK_OPSSK_SKBCGROUP_DEVICESK_MSGRAW_TRACEPOINTCGROUP_SOCK_ADDRCGROUP_SOCKOPTTRACINGLSMr   r   r   r   r      sl    MFIIJ
CJJKFGHHFMFNNG
Cr   r   c                       e Zd ZdZdZdZdZdZdZdZ	dZ
d	Zd
ZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZ dZ!d Z"d!Z#d"Z$d#Z%d$Z&d%Z'd&Z(d'Z)y())BPFAttachTyper   r   r"   rM   r#   rN   rW   rX   r$   rY   rf   r   r   r   r   r   r%   r   r                     r   r         r         r&   !   "   #   $   %   &   N)*rH   rI   rJ   CGROUP_INET_INGRESSCGROUP_INET_EGRESSCGROUP_INET_SOCK_CREATECGROUP_SOCK_OPSSK_SKB_STREAM_PARSERSK_SKB_STREAM_VERDICTr   SK_MSG_VERDICTCGROUP_INET4_BINDCGROUP_INET6_BINDCGROUP_INET4_CONNECTCGROUP_INET6_CONNECTCGROUP_INET4_POST_BINDCGROUP_INET6_POST_BINDCGROUP_UDP4_SENDMSGCGROUP_UDP6_SENDMSG
LIRC_MODE2FLOW_DISSECTORCGROUP_SYSCTLCGROUP_UDP4_RECVMSGCGROUP_UDP6_RECVMSGCGROUP_GETSOCKOPTCGROUP_SETSOCKOPTTRACE_RAW_TPTRACE_FENTRYTRACE_FEXITMODIFY_RETURNLSM_MAC
TRACE_ITERCGROUP_INET4_GETPEERNAMECGROUP_INET6_GETPEERNAMECGROUP_INET4_GETSOCKNAMECGROUP_INET6_GETSOCKNAME
XDP_DEVMAPCGROUP_INET_SOCK_RELEASE
XDP_CPUMAP	SK_LOOKUPr   SK_SKB_VERDICTr   r   r   r   r      s    OMNJNMLLKMGJ!!!!J!JI
CNr   r   c                        e Zd ZdZdZdZdZdZy)	XDPActionr   r   r"   rM   r#   N)rH   rI   rJ   XDP_ABORTEDXDP_DROPXDP_PASSXDP_TXXDP_REDIRECTr   r   r   r   r      s    KHHFLr   r   c                        e Zd ZdZdZdZdZdZy)XDPFlagsr   r"   r#   r$   r%   N)rH   rI   rJ   UPDATE_IF_NOEXISTSKB_MODEDRV_MODEHW_MODEREPLACEr   r   r   r   r      s      HHGGr   r   c            	       	   e Zd Zej                  Zej
                  Zej                  Zej                  Zej                  Zej                  Z	ej                  Z
ej                  Zej                  Zej                  Zej                  Zej                  Zej                   Zej"                  Zej$                  Zej&                  Zej(                  Zej*                  Zej,                  Zej.                  Zej2                  Zej4                  Zej6                  Zej8                  Zej:                  Zej>                  Z ejB                  Z"ejF                  Z$ejJ                  Z&ejN                  Z( e)jT                  d      Z+i Z, e-j\                         Z/dgddgddgdgdd	gd
Z0g dZ1dZ2 G d de3jh                        Z5 e3jl                  dd      Z7e7jp                  Z9e3jt                   e3jv                  e5      ge9_<        e=d        Z>e=d        Z?e@Z@ G d deA      ZBeCd        ZDeCd        ZEddddg g dddf	dZFefdZGddZHd ZId  ZJdd!ZKi d"e3j                  d#e3j                  d$e3j                  d%e3j                  d&e3j                  d'e3j                  d(e3jt                  d)e3j                  d*e3j                  d+e3j                  d,e3j                  d-e3j                  d.e3j                  d/e3j                  d0e3j                  d1e3j                  d2z  d3e3j                  d2z  Z\eCd4        Z]dd5Z^d6 Z_d7 Z`d8 Zad9 Zbd: ZceCdd;       ZdeCd<        ZeeCd=        ZfeCd>        Zgd? ZheCd@        ZidA ZjdB ZkdC ZldD ZmdE ZndF ZodG ZpddHZqddIZrdJ ZsdK ZtddLZuddMZveCddN       ZweCddO       Zxe=ddP       ZyeCdQ        ZzeCdR        Z{eCdS        Z|ddTZ}ddUZ~ddVZeCdW        ZeCdX        ZeCdY        ZddZZdd[Zdd\Zdd]Zdd^Zdd_ZeCd`        ZeCda        ZeCdb        ZddcZdd Z	 	 ddeZdf ZddgZddhZeCdi        ZeCdj        ZeCdk        Zdl Z	 	 ddmZ	 	 ddnZdo ZddpZddqZdr ZddsZddtZdduZddvZeCdw        ZeCddx       ZeCddy       ZeCdz        Zd{ Zd| Zd} Zdd~Zd ZddZddZddZd Zd ZeCd        Zd Zd Zd Zd Zd Zy)BPFs   [^a-zA-Z0-9_]timefsfilebiorequestallocsk_buff
net_device)zlinux/time.hz
linux/fs.hzlinux/blkdev.hzlinux/slab.hzlinux/netdevice.h)s   sys_s
   __x64_sys_s   __x32_compat_sys_s   __ia32_compat_sys_s   __arm64_sys_s   __s390x_sys_s   __s390_sys_r   c                   D    e Zd Zdej                  fdej                  fgZy)BPF.timespectv_sectv_nsecN)rH   rI   rJ   r+   c_long_fields_r   r   r   timespecr   C  s    ryy)Iryy+ABr   r  z
librt.so.1T)	use_errnoc                 $   | j                         }| j                  | j                  t        j                  |            dk7  r3t        j
                         }t        |t        j                  |            |j                  dz  |j                  z   S )zmonotonic_time()
        Returns the system monotonic time from clock_gettime, using the
        CLOCK_MONOTONIC constant. The time returned is in nanoseconds.
        r   g    eA)r  _clock_gettimeCLOCK_MONOTONICr+   r4   	get_errnoOSErrorosstrerrorr  r  )clsterrnos      r   monotonic_timezBPF.monotonic_timeJ  sj     LLNc11288A;?1DLLNE%U!344xx#~		))r   c                     d}| j                   j                         D ]%  \  }}|D ]  }|D ]  }||v s||vs|d|z  z  }  ' |S )a1  
        Generates #include statements automatically based on a set of
        recognized types such as sk_buff and bio. The input is all the words
        that appear in the BPF program, and the output is a (possibly empty)
        string of #include statements, such as "#include <linux/fs.h>".
         z#include <%s>
)_auto_includesitems)r  program_wordsheadersheaderkeywordskeywordwords          r   generate_auto_includeszBPF.generate_auto_includesV  so      # 2 2 8 8 : 	>FH# >) >D$6+@#4v#==>>	>
 r   c                       e Zd Zd Zy)BPF.Functionc                 .    || _         || _        || _        y r   )bpfr<   fd)r/   r   r<   r!  s       r   r1   zBPF.Function.__init__j  s    DHDIDGr   N)rH   rI   rJ   r1   r   r   r   Functionr  i  s    	r   r"  c                    | rt         j                  j                  |       st        t        j
                  d         }dj                  t         j                  j                  t         j                  j                  |j                                     | g      }t         j                  j                  |      r|} | S t        d| z        | S )z1 If filename is invalid, search in ./ of argv[0] r      /zCould not find file %s)r  pathisfiler   sysargvjoinabspathdirname	__bytes__	Exception)filenameargv0r  s      r   
_find_filezBPF._find_fileo  s     77>>(+!#((1+.IIrwwrwwu?P/QRT\]^77>>!$ H  $$<x$GHHr   c                 h   d }t         j                  j                  |       \  }}|r ||       r| S yt         j                  d   j                  t         j                        D ]M  }|j                  d      }t         j                  j                  |j                         |       } ||      sK|c S  y)a  
        find_exe(bin_path)

        Traverses the PATH environment variable, looking for the first
        directory that contains an executable file named bin_path, and
        returns the full path to that file, or None if no such file
        can be found. This is meant to replace invocations of the
        "which" shell utility, which doesn't have portable semantics
        for skipping aliases.
        c                     t         j                  j                  |       xr$ t        j                  | t         j                        S r   )r  r%  r&  accessX_OK)fpaths    r   is_exezBPF.find_exe.<locals>.is_exe  s.    77>>%( *		%)*r   PATH"N)r  r%  splitenvironpathsepstripr)  encode)bin_pathr6  r5  fnamer%  exe_files         r   find_exezBPF.find_exe|  s    	* ww}}X.uh  

6*00< $zz#77<<x@(##O	$
 r   r   Nr   Fc
                    t        |      }t        |      }t        |      }|r|rJ i | _        i | _        i | _        i | _        i | _        i | _        i | _        i | _        i | _	        d| _
        d| _        t        j                  | j                         || _        i | _        i | _        d| _        t'        j(                  t+        |      z         }
t-        |      D ]  \  }}t/        t1        |            |
|<    |r*t2        j5                  |      }t2        j5                  |      }|r&t7        |d      5 }|j9                         }ddd       t'        j:                  t+        |      z         }t-        |      D ]+  \  }}t'        j:                  |j=                               ||<   - t?        j@                  |t+        |            }|tC        d      ||z   }t?        jD                  || j                  |
t+        |
      ||      | _        | j$                  stC        d|xs dz        |D ]  }|jG                  | |	        | jI                          y# 1 sw Y   xY w)aZ  Create a new BPF module with the given source code.

        Note:
            All fields are marked as optional, but either `src_file` or `text`
            must be supplied, and not both.

        Args:
            src_file (Optional[str]): Path to a source file for the module
            hdr_file (Optional[str]): Path to a helper header file for the `src_file`
            text (Optional[str]): Contents of a source file for the module
            debug (Optional[int]): Flags used for debug prints, can be |'d together
                                   See "Debug flags" for explanation
        Nrb)modezycan't generate USDT probe arguments; possible cause is missing pid when a probe in a shared object has multiple locationszFailed to compile BPF module %sz<text>)%r   
kprobe_fds
uprobe_fdstracepoint_fdsraw_tracepoint_fdskfunc_entry_fdskfunc_exit_fdslsm_fdsperf_buffersopen_perf_events_ringbuf_manager	tracefileatexitregistercleanupdebugfuncstablesr6   r+   r8   len	enumeratebytesr   r   r0  openreadc_void_pget_contextr   bcc_usdt_genargsr-  bpf_module_create_c_from_stringattach_uprobes_trace_autoload)r/   src_filehdr_filetextrS  cflagsusdt_contextsallow_rlimitdeviceattach_usdt_ignore_pidcflags_arrayisr   	ctx_arrayusdt	usdt_textusdt_contexts                     r   r1   zBPF.__init__  s9   " $H-#H-%X&& "$!  " $%

c&k14f%LDAqy|9L|AL~~h/H~~h/H hT* #dyy{# [[3}#558	 / 	;GAt;;t'7'7'9:IaL	;((C4FG	 ( ) ) 4 99$:>**:FLHY:FP {{=AUXVWW) 	FL''.DE	F 	9# #s   5IIc                     g }t        dt        j                  | j                              D ]C  }t        j                  | j                  |      }|j                  | j                  ||             E |S )zload_funcs(prog_type=KPROBE)

        Load all functions in this BPF module with the given type.
        Returns a list of the function handles.r   )ranger   bpf_num_functionsr6   bpf_function_nameappend	load_func)r/   	prog_typefnsrj  	func_names        r   
load_funcszBPF.load_funcs  sb     q#//<= 	=A--dkk1=IJJt~~i;<	= 
r   c                    t        |      }|| j                  v r| j                  |   S t        j                  | j                  |      st        d|z        d}| j                  t        z  rd}n| j                  t        z  rd}t        j                  | j                  ||t        j                  | j                  |      t        j                  | j                  |      t        j                  | j                        t        j                  | j                        |d d||      }|dk  rt        j                  | j                         t!        j"                         t$        j&                  k(  rt        d      t)        j*                  t!        j"                               }t        d|d|      t,        j/                  | ||      }|| j                  |<   |S )NUnknown program %sr   r"   r   z!Need super-user privileges to runzFailed to load BPF program : )r   rT  r   bpf_function_startr6   r-  rS  DEBUG_BPF_REGISTER_STATE	DEBUG_BPFbcc_func_loadbpf_function_sizebpf_module_licensebpf_module_kern_versionrP  rQ  	donothingr+   r
  r  EPERMr  r  r   r"  )	r/   rx  rv  rg  attach_type	log_levelr!  errstrfns	            r   ru  zBPF.load_func  sn   $Y/	

"::i((%%dkk9=09<==	JJ11Ijj9$It{{Iy&&t{{I>%%dkk9=&&t{{3++DKK84FK9 6OODNN+||~, CDD[[0F&0 1 1 \\$	2. "

9	r   c                     t        |      }t        j                  | j                  |      st	        d|z        t        j                  | j                  |      }t        j
                  | j                  |      }t        j                  ||      S )zR
        Return the eBPF bytecodes for the specified function as a string
        r{  )r   r   r}  r6   r-  r  r+   	string_at)r/   rx  startsizes       r   	dump_funczBPF.dump_func  sp     %Y/	%%dkk9=09<==''Y?%%dkk9=||E4((r   c                 <    | j                  |      }t        ||      S r   )r  r   )r/   rx  bpfstrs      r   disassemble_funczBPF.disassemble_func"  s    	*	622r   c                 ~    | |   }t        j                  | j                  |j                        }t	        ||||      S )N)sizeinfo)r   bpf_table_type_idr6   map_idr   )r/   
table_namer  	table_obj
table_types        r   decode_tablezBPF.decode_table&  s9    $	**4;;	8H8HI
*ihOOr   _Boolcharwchar_tzunsigned charshortzunsigned shortintzunsigned intlongzunsigned longz	long longzunsigned long longfloatdoublezlong double__int128r"   zunsigned __int128c           	         t        | t              rt        j                  |    S g }g }| d   D ]  }t	        |      dk(  r-|j                  |d   t        j                  |d         f       ?t	        |      dk(  r t        |d   t              r6|j                  |d   t        j                  |d         |d   d   z  f       t        |d   t              r1|j                  |d   t        j                  |d         |d   f       t        |d   t              ri|d   dk(  s|d   dk(  s|d   dk(  rQ|d   }|dk(  rd	t	        |      z  }|j                  |       |j                  |t        j                  |      f       Wt        d
t        |      z        t        d
t        |      z         t        j                  }d}t	        |       dkD  rL| d   dk(  rt        j                  }n3| d   dk(  rt        j                  }n| d   dk(  rt        j                  }d}|r(t        t        | d         |ft        |d|            }|S t        t        | d         |ft        ||            }|S )Nr   r"   r   rM   unionstructstruct_packedr  z__anon%dzFailed to decode type %sFT)_anonymous__pack_r  )r  r  )
isinstance
basestringr   	str2ctyperV  rt  _decode_table_typelistr  r-  strr+   	StructureUniontypedict)descanonfieldsr  r<   base	is_packedr  s           r   r  zBPF._decode_table_type>  sH   dJ'==&&a 	EA1v{qtS%;%;AaD%ABCQ1adD)MM1Q4)?)?!)E!Q)O"PQ!c*MM1Q4)?)?!)Eqt"LM!j1!(AaDI,=! 00Q4Drz)CI5D)MM4)?)?)B"CD#$>Q$GHH :SV CDD'	E( ||	t9q=Aw("xxaI%||a,,|| 	s47|dWdtA/! "C
 
 s47|dWdt/! "C
r   c           	         t        |      }t        j                  | j                  |      }t        j                  | j                  |      }t        j
                  | j                  |      t        t        fv }|dk  rt        |si|sgt        j                  | j                  |      j                  d      }|st        d|z        t        j                  t        j                  |            }|sgt        j                   | j                  |      j                  d      }	|	st        d|z        t        j                  t        j                  |	            }t#        | ||||||      S )Nr   zutf-8z$Failed to load BPF Table %s key descz%Failed to load BPF Table %s leaf desc)reducer)r   r   bpf_table_idr6   bpf_table_fdr  r   r   KeyErrorbpf_table_key_descdecoder-  r   r  jsonloadsbpf_table_leaf_descr
   )
r/   r<   keytypeleaftyper  r  map_fdis_queuestackkey_desc	leaf_descs
             r   	get_tablezBPF.get_tablej  s!   %!!$++t4!!$++t4--dkk6BGY[mFnnA:N}--dkk4@GGPH F MNN,,TZZ-ABG//TBII'RI G$ NOO--djj.CDHT667HdGTTr   c                 x    || j                   vr| j                  |      | j                   |<   | j                   |   S r   )rU  r  r/   keys     r   __getitem__zBPF.__getitem__}  s4    dkk!#~~c2DKK{{3r   c                 "    || j                   |<   y r   rU  )r/   r  leafs      r   __setitem__zBPF.__setitem__  s    Cr   c                 ,    t        | j                        S r   )rV  rU  r/   s    r   __len__zBPF.__len__  s    4;;r   c                     | j                   |= y r   r  r  s     r   __delitem__zBPF.__delitem__  s    KKr   c                 6    | j                   j                         S r   )rU  __iter__r  s    r   r  zBPF.__iter__  s    {{##%%r   c                     t        | t        j                        st        d      t	        j
                  | j                  |||      }|dk  r/t        dj                  |t        j                  |                   y )N"arg 1 must be of type BPF.Functionr   z7Failed to attach BPF function with attach_type {0}: {1})
r  r   r"  r-  r   bpf_prog_attachr!  formatr  r  )r  attachable_fdr  flagsr@   s        r   attach_funczBPF.attach_func  sm    "cll+@AA!!"%%UK7 ''-vk2;;t;L'MO O r   c                     t        | t        j                        st        d      t	        j
                  | j                  ||      }|dk  r/t        dj                  |t        j                  |                   y )Nr  r   z7Failed to detach BPF function with attach_type {0}: {1})
r  r   r"  r-  r   bpf_prog_detach2r!  r  r  r  )r  r  r  r@   s       r   detach_funczBPF.detach_func  sk    "cll+@AA""255-E7 ''-vk2;;t;L'MO O r   c                    t        |      }t        | t        j                        st	        d      t        j                  |      }|dk  r8t        j                  t        j                               }t	        d|d|      t        j                  || j                        }|dk  r8t        j                  t        j                               }t	        d|d|      || _        y )Nr  r   zFailed to open raw device r|  Failed to attach BPF to device )r   r  r   r"  r-  r   bpf_open_raw_sockr  r  r+   r
  bpf_attach_socketr!  sock)r  devr  r  r@   s        r   attach_raw_socketzBPF.attach_raw_socket  s    s#"cll+@AA$$S)!8[[0F#vNOO##D"%%07[[0FF$ % %r   c                 <   dt         z  }	 t        |d      5 }t        |D cg c]#  }|j                         j	                         d   % c}      }d d d        dt         z  }	 t        |d      5 }t        |D cg c]#  }|j                         j	                         d   % c}      }d d d        g }	d}
d}t        dd      5 }|D ]  }|j                         j	                         dd \  }}|
dk(  r|dk(  rd}
5|
dk(  r|d	k(  rd
}
B|dk(  r|dk(  rd}O|dk(  rd
}W|dk(  r|dk(  rd
}d|j                  d      rv|j                  d      s|j                  d      r|j                  d      rt        j                  d|      r|j                         dv st        j                  | |      s|vs|v s|	j                  |       	 	 d d d        t        |	      S c c}w # 1 sw Y   xY w# t
        $ r5}|j                  t        j                  k7  r|t        g       }Y d }~d }~ww xY wc c}w # 1 sw Y   xY w# t
        $ r5}|j                  t        j                  k7  r|t        g       }Y d }~d }~ww xY w# 1 sw Y   t        |	      S xY w)Nz%s/kprobes/blacklistrC  r   z%%s/tracing/available_filter_functionsr   /proc/kallsymsrM   s   __init_begins
   __init_endr"   s   __irqentry_text_starts   __irqentry_text_ends
   _kbl_addr_s   __perfs   perf_s   __SCT__s   ^.*.cold(.d+)?$)   t   w)DEBUGFSrY  setrstripr9  IOErrorr  r  
startswithrematchlower	fullmatchrt  )event_reblacklist_fileblacklist_fline	blacklisteavail_filter_fileavail_filter_favail_filterrw  in_init_sectionin_irq_section
avail_filer  r  s                  r   get_kprobe_functionszBPF.get_kprobe_functions  s   /'9	 nd+ T{k Rd!4!4!6q!9 RS	T DgM	#'. Z."#XDKKM$7$7$9!$<#XYZ "D) 1	#Z" 0#++---/!4B #a'_,*+ $)]**+ "Q&55)*  55)* #q(33)*
 ==/ ]]9-x1H ]]:.XX0"5GGI-2<<"3M)+l*JJrNa0#1	#d 3xK !ST T 	 ww%++%BI	  $YZ Z 	#ww%++%r7L	#1	#d 3xs   G4 
G'(G"
	G'G4 "I .
H:8(H5
 H:'I CJJ0J5J:J"G''G1,G4 4	H2=*H--H25H::I?I 	J*J  JJc                 V    t         |z   t        j                         kD  rt        d      y )Nz/Number of open probes would exceed global quota)r   r   get_probe_limitr-  )r/   num_new_probess     r   _check_probe_quotazBPF._check_probe_quota  s*    n,s/B/B/DDMNN Er   c                      t         j                  j                  d      } | r| j                         rt	        |       S t
        S )NBCC_PROBE_LIMIT)r  r:  getisdigitr  _default_probe_limit)env_probe_limits    r   r  zBPF.get_probe_limit  s4    **..):;668''''r   c                 t    || j                   vri | j                   |<   || j                   |   |<   t        dz  ay Nr   rE  r   )r/   ev_namefn_namer!  s       r   _add_kprobe_fdzBPF._add_kprobe_fd  s:    $//)')DOOG$,. )Ar   c                 6    | j                   |   |= t        dz  ay r  r  )r/   r  r  s      r   _del_kprobe_fdzBPF._del_kprobe_fd  s    OOG$W-Ar   c                 4    || j                   |<   t        dz  ay r  rF  r   )r/   r<   r!  s      r   _add_uprobe_fdzBPF._add_uprobe_fd  s     "Ar   c                 0    | j                   |= t        dz  ay r  r  r/   r<   s     r   _del_uprobe_fdzBPF._del_uprobe_fd  s    OOD!Ar   c                 x    | j                   D ]  }| j                  d|z        dk7  s|c S  | j                   d   S )Ns   %sbpfrD   r   )_syscall_prefixesksymname)r/   prefixs     r   get_syscall_prefixzBPF.get_syscall_prefix$  sE    ,, 	F}}X./25	 %%a((r   c                 >    t        |      }| j                         |z   S r   )r   r  r  s     r   get_syscall_fnnamezBPF.get_syscall_fnname-  s     %&&(4//r   c                     t        |      }| j                  D ]2  }|j                  |      s| j                  |t	        |      d        c S  |S r   )r   r  r  r!  rV  )r/   r<   r  s      r   fix_syscall_fnnamezBPF.fix_syscall_fnname4  sR    %,, 	CFv&..tCKL/ABB	C r   c                    t        |      }t        |      }t        |      }|r~t        j                  |      }| j                  t	        |             d}g }|D ]  }	 | j                  ||        |t	        |      k(  r!t        d|ddj                  |      d      y | j                  d       | j                  |t        j                        }	d|j                  d	d
      j                  dd
      z   }
t        j                  |	j                  d|
||d      }|dk  rt        d|d|d      | j                  |
||       | S #  |dz  }|j                  |       Y 
xY w)Nr   eventr  r   Failed to attach BPF program z to kprobe /K, it's not traceable (either non-existing, inlined, or marked as "notrace")   p_   +   _   .)r   r   r  r  rV  attach_kprobert  r-  r)  ru  r   replacer   bpf_attach_kprober!  r  )r/   r&  	event_offr  r  matchesfailedprobesr  r  r  r!  s               r   r.  zBPF.attach_kprobe;  s`    '"7+#H- ..x8G##CL1FF ((&&T7&C( W%!(#((6*:!< = = "^^GSZZ0%--d3;;D$GG""255!WeYJ6$e- . . 	GWb1%(aKFMM$'s   EE#c                    t        |      }t        |      }t        |      }|ret        j                  |      }d}g }|D ]  }	 | j                  |||        |t        |      k(  r!t        d|ddj                  |      d      y | j                  d       | j                  |t        j                        }	d|j                  d	d
      j                  dd
      z   }
t        j                  |	j                  d|
|d|      }|dk  rt        d|d|d      | j                  |
||       | S #  |dz  }|j	                  |       Y xY w)Nr   )r&  r  	maxactiver   r'  z to kretprobe r(  r)     r_r+  r,  r-  )r   r   r  attach_kretprobert  rV  r-  r)  r  ru  r   r/  r   r0  r!  r  )r/   r&  r  r  r6  r2  r3  r4  r  r  r  r!  s               r   r8  zBPF.attach_kretprobe]  sU    '"7+#H- ..x8GFF (())g4= * ?( W%!(#((6*:!< = = "^^GSZZ0%--d3;;D$GG""255!WeQ	J6$e- . . 	GWb1%(aKFMM$'s   D//E
c                     t        |      }t        | j                  |   j                               }|D ]  }| j	                  ||        y r   )r   r  rE  keysdetach_kprobe_event_by_fn)r/   r  fn_namesr  s       r   detach_kprobe_eventzBPF.detach_kprobe_event  sG    "7+05578 	=G**7G<	=r   c                 x   t        |      }t        |      }|| j                  vrt        d|z        t        j                  | j                  |   |         }|dk  rt        d      | j                  ||       t        | j                  |         dk(  r&t        j                  |      }|dk  rt        d      y y )NzKprobe %s is not attachedr   zFailed to close kprobe FDz Failed to detach BPF from kprobe)r   rE  r-  r   bpf_close_perf_event_fdr  rV  bpf_detach_kprobe)r/   r  r  r@   s       r   r;  zBPF.detach_kprobe_event_by_fn  s    "7+"7+$//)7'ABB))$//'*B7*KL7788GW-tw'(A-''0CQw BCC  .r   c                     t        |      }d|j                  dd      j                  dd      z   }|rt        |      }| j                  ||       y | j                  |       y )Nr*  r+  r,  r-  r   r/  r;  r=  r/   r&  r  r  s       r   detach_kprobezBPF.detach_kprobe  Y     '%--d3;;D$GG&w/G**7G<$$W-r   c                     t        |      }d|j                  dd      j                  dd      z   }|rt        |      }| j                  ||       y | j                  |       y )Nr7  r+  r,  r-  rB  rC  s       r   detach_kretprobezBPF.detach_kretprobe  rE  r   c                 `   t        |       } t        |t        j                        st	        d      t        j                  | |j                  |      }|dk  rXt        j                         }|t        j                  k(  rt	        d      t        j                  |      }t	        d| d|      y)zt
            This function attaches a BPF function to a device on the device
            driver level (XDP)
        r  r   zMInternal error while attaching BPF to device, try increasing the debug level!r  r|  N)r   r  r   r"  r-  r   bpf_attach_xdpr!  r+   r
  r  EBADMSGr  r  )r  r  r  r@   err_nor  s         r   
attach_xdpzBPF.attach_xdp  s     s#"cll+@AA  beeU37\\^F& !7 8 8 V,"F!, - - r   c                     t        |       } t        j                  | d|      }|dk  r8t        j                  t        j                               }t        d| d|      y)zw
            This function removes any BPF function from a device on the
            device driver level (XDP)
        rD   r   z!Failed to detach BPF from device r|  N)r   r   rI  r  r  r+   r
  r-  )r  r  r@   r  s       r   
remove_xdpzBPF.remove_xdp  sY     s#  b%07[[0F"F, - - r   c                 @   t        |      }t        |      }t               }|dk(  rdn|}t        j                  |||xs d|t	        j
                  d t	        j                  t                    t	        j                  |            dk  r-t        d|j                         d|j                               |j                  |z   }t	        j
                  |j                  t        j                        j                  }	t        j                  |j                         |	|fS )NrD   r   z&could not determine address of symbol z in )r   r   r   bcc_resolve_symnamer+   r,   r-   r   r4   r-  r  r7   r6   r8   r9   bcc_procutils_free)
r  r6   symnamer=   r0   sym_offr?   c_pidnew_addrmodule_paths
             r   _check_path_symbolzBPF._check_path_symbol  s    !&)"7+lBYC""GKCGGD"**%678HHSM	

  &~~/B C C::'ggcjj"++6<<szz*H$$r   c                     t        |       } t        j                  | d      }|sy t        j                  |t        j
                        j                  }t        j                  |       |S Nr   )r   r   bcc_procutils_which_sor+   r,   r8   r9   rQ  )libnamer@   libpaths      r   find_libraryzBPF.find_library  sQ    "7+((!4''#r{{+11s#r   c                 P   g }t         j                  j                  t        d      }t        j                  |      D ]  }t         j                  j                  ||      }t         j                  j                  |      sCt        j                  |      D ]  }t         j                  j                  ||      }t         j                  j                  |      sC|d|}t        j                  | j                         |      so|j                  |j                                  |S )Nevents:)r  r%  r)  TRACEFSlistdirisdirr  r  r  rt  r=  )tp_reresults
events_dircategorycat_dirr&  evt_dirtps           r   get_tracepointszBPF.get_tracepoints  s    WW\\'84


:. 		4Hggll:x8G77==)G, 4'',,w677==)%-u5Bxx3ryy{34			4 r   c                     t         j                  j                  t        d| |      }t         j                  j	                  |      S )Nr_  )r  r%  r)  ra  rc  )rg  r&  ri  s      r   tracepoint_existszBPF.tracepoint_exists  s-    '',,w(EBww}}W%%r   c                    t        |      }t        |      }t        |      }|r.t        j                  |      D ]  }| j                  ||        y| j	                  |t        j
                        }|j                  d      \  }}t        j                  |j                  ||      }|dk  rt        d|d|      || j                  |<   | S )a  attach_tracepoint(tp="", tp_re="", fn_name="")

        Run the bpf function denoted by fn_name every time the kernel tracepoint
        specified by 'tp' is hit. The optional parameters pid, cpu, and group_fd
        can be used to filter the probe. The tracepoint specification is simply
        the tracepoint category and the tracepoint name, separated by a colon.
        For example: sched:sched_switch, syscalls:sys_enter_bind, etc.

        Instead of a tracepoint name, a regular expression can be provided in
        tp_re. The program will then attach to tracepoints that match the
        provided regular expression.

        To obtain a list of kernel tracepoints, use the tplist tool or cat the
        file /sys/kernel/debug/tracing/available_events.

        Examples:
            BPF(text).attach_tracepoint(tp="sched:sched_switch", fn_name="on_switch")
            BPF(text).attach_tracepoint(tp_re="sched:.*", fn_name="on_switch")
        rj  r  N   :r   r'  z to tracepoint )r   r   rk  attach_tracepointru  rQ   r9  r   bpf_attach_tracepointr!  r-  rG  )r/   rj  rd  r  r  tp_categorytp_namer!  s           r   rq  zBPF.attach_tracepoint  s    * b! '"7+))%0 ?&&"g&>?^^GS^^4!#$g&&ruuk7C6$b* + +"$Br   c                 (   t        |      }|| j                  v rt        d|z        t        |      }| j                  |t        j
                        }t        j                  |j                  |      }|dk  rt        d      || j                  |<   | S )a  attach_raw_tracepoint(self, tp=b"", fn_name=b"")

        Run the bpf function denoted by fn_name every time the kernel tracepoint
        specified by 'tp' is hit. The bpf function should be loaded as a
        RAW_TRACEPOINT type. The fn_name is the kernel tracepoint name,
        e.g., sched_switch, sys_enter_bind, etc.

        Examples:
            BPF(text).attach_raw_tracepoint(tp="sched_switch", fn_name="on_switch")
        z#Raw tracepoint %s has been attachedr   z&Failed to attach BPF to raw tracepoint)	r   rH  r-  ru  r   r   r   bpf_attach_raw_tracepointr!  )r/   rj  r  r  r!  s        r   attach_raw_tracepointzBPF.attach_raw_tracepoint  s     b!(((ABFGG"7+^^GS%7%78**255"56DEE&(#r   c                     t        |      }|| j                  vrt        d|z        t        j                  | j                  |          | j                  |= y)zdetach_raw_tracepoint(tp="")

        Stop running the bpf function that is attached to the kernel tracepoint
        specified by 'tp'.

        Example: bpf.detach_raw_tracepoint("sched_switch")
        z!Raw tracepoint %s is not attachedN)r   rH  r-  r  close)r/   rj  s     r   detach_raw_tracepointzBPF.detach_raw_tracepoint6  sR     b!T,,,?"DEE
((,-##B'r   c                 2    |j                  |       s| |z   }|S r   )r  )r  r<   s     r   
add_prefixzBPF.add_prefixE  s    v&D=Dr   c                      t        j                         dk7  ryt        j                         syt        j                  d      dk7  ryy)Nx86_64Fbpf_trampoline_link_progrD   T)platformmachiner   bpf_has_kernel_btfr   r  r   r   r   support_kfunczBPF.support_kfuncK  s?     )%%'<<23r9r   c                  `    t        j                         syt        j                  d      dk7  ryy)NFs   bpf_lsm_bpfrD   T)r   r  r   r  r   r   r   support_lsmzBPF.support_lsmW  s(    %%'<<'2-r   c                     t        |      }t        j                  d|      }|| j                  vrt	        d|z        t        j                  | j                  |          | j                  |= y )N   kfunc__z$Kernel entry func %s is not attached)r   r   r|  rI  r-  r  ry  r/   r  s     r   detach_kfunczBPF.detach_kfunc`  s`    "7+..W5$...BWLMM
%%g./  )r   c                     t        |      }t        j                  d|      }|| j                  vrt	        d|z        t        j                  | j                  |          | j                  |= y )N
   kretfunc__z#Kernel exit func %s is not attached)r   r   r|  rJ  r-  r  ry  r  s     r   detach_kretfunczBPF.detach_kretfunci  s`    "7+..8$---AGKLL
$$W-.(r   c                 <   t        |      }t        j                  d|      }|| j                  v rt	        d|z        | j                  |t        j                        }t        j                  |j                        }|dk  rt	        d      || j                  |<   | S )Nr  z&Kernel entry func %s has been attachedr   z)Failed to attach BPF to entry kernel func)
r   r   r|  rI  r-  ru  r   r   bpf_attach_kfuncr!  r/   r  r  r!  s       r   attach_kfunczBPF.attach_kfuncr  s    "7+..W5d***DwNOO^^GS[[1!!"%%(6GHH(*W%r   c                 <   t        |      }t        j                  d|      }|| j                  v rt	        d|z        | j                  |t        j                        }t        j                  |j                        }|dk  rt	        d      || j                  |<   | S )Nr  z%Kernel exit func %s has been attachedr   z(Failed to attach BPF to exit kernel func)
r   r   r|  rJ  r-  ru  r   r   r  r!  r  s       r   attach_kretfunczBPF.attach_kretfunc  s    "7+..8d)))CgMNN^^GS[[1!!"%%(6FGG')G$r   c                     t        |      }t        j                  d|      }|| j                  vrt	        d|z        t        j                  | j                  |          | j                  |= y )N   lsm__zLSM %s is not attached)r   r   r|  rK  r-  r  ry  r  s     r   
detach_lsmzBPF.detach_lsm  sZ    "7+..73$,,&4w>??
g&'LL!r   c                 <   t        |      }t        j                  d|      }|| j                  v rt	        d|z        | j                  |t        j                        }t        j                  |j                        }|dk  rt	        d      || j                  |<   | S )Nr  zLSM %s has been attachedr   zFailed to attach LSM)
r   r   r|  rK  r-  ru  r   r   bpf_attach_lsmr!  r  s       r   
attach_lsmzBPF.attach_lsm  s    "7+..73dll"6@AA^^GSWW-&6233 "Wr   c                  f    t         j                  d      dk7  st         j                  d      dk7  ryy)Nbpf_find_raw_tracepointrD   bpf_get_raw_tracepointTF)r   r  r   r   r   support_raw_tracepointzBPF.support_raw_tracepoint  s.     <<12b8<<01R7r   c                      d} t        |       5 }|D ]I  }|j                         j                  dd      \  }}}|j                  d      d   }|dk(  sA d d d        y 	 d d d        y# 1 sw Y   y xY w)	Nr   r"   	r   bpf_trace_modulesTF)rY  r  r9  )kallsymssymsr  _r<   s        r    support_raw_tracepoint_in_modulez$BPF.support_raw_tracepoint_in_module  s     $(^ 	t  #{{}223:Atzz$'*..	 	 
 	 	 	s   AA'A'A''A0c                 Z    t        |       } t        |      }t        j                  | |      S r   )r   r   kernel_struct_has_field)struct_name
field_names     r   r  zBPF.kernel_struct_has_field  s)    &{3%j1
**;
CCr   c                 D   t        |      }|| j                  vrt        d|z        t        j                  | j                  |         }|dk  rt        d      |j                  d      \  }}t        j                  ||      }|dk  rt        d      | j                  |= y)zdetach_tracepoint(tp="")

        Stop running a bpf function that is attached to the kernel tracepoint
        specified by 'tp'.

        Example: bpf.detach_tracepoint("sched:sched_switch")
        zTracepoint %s is not attachedr   z$Failed to detach BPF from tracepointrp  N)r   rG  r-  r   r?  r9  bpf_detach_tracepoint)r/   rj  r@   rs  rt  s        r   detach_tracepointzBPF.detach_tracepoint  s     b!T(((;b@AA))$*=*=b*AB7BCC!#$g''W=7BCC#r   c	           
      ^    t        j                  ||||||||      }	|	dk  rt        d      |	S )Nr   z"Failed to attach BPF to perf event)r   bpf_attach_perf_eventr-  )
r/   progfdev_type	ev_configsample_periodsample_freqr0   cpugroup_fdr@   s
             r   _attach_perf_eventzBPF._attach_perf_event  s<    ''{Ch@7@AA
r   c	                 >   t        |      }| j                  |t        j                        }	i }
|dk\  r&| j	                  |	j
                  |||||||      |
|<   n4t               D ]'  }| j	                  |	j
                  |||||||      |
|<   ) |
| j                  ||f<   y rY  )r   ru  r   r   r  r!  r   rM  )r/   r  r  r  r  r  r0   r  r  r  r@   rj  s               r   attach_perf_eventzBPF.attach_perf_event  s    "7+^^GS^^4!8..ruugy!;S(DCH %& F00%{CHFAF 7:w	23r   c                     t        j                  |t        j                  |      |||d      }|dk  rt	        d      |S )Nr   z&Failed to attach BPF to perf raw event)r   bpf_attach_perf_event_rawr+   r4   r-  )r/   r  attrr0   r  r  r@   s          r   _attach_perf_event_rawzBPF._attach_perf_event_raw  s?    ++FBHHTNCXq"7DEE
r   c                 Z   t        |      }| j                  |t        j                        }i }|dk\  r#| j	                  |j
                  ||||      ||<   n1t               D ]$  }| j	                  |j
                  ||||      ||<   & || j                  |j                  |j                  f<   y rY  )
r   ru  r   r   r  r!  r   rM  r  config)	r/   r  r  r0   r  r  r  r@   rj  s	            r   attach_perf_event_rawzBPF.attach_perf_event_raw  s    "7+^^GS^^4!822255$h(CH %& *44RUUDQ*A* ;>tyy$++67r   c                    	 | j                   ||f   }d}|j	                         D ]  }t        j                  |      xs |} |dk7  rt        d      | j                   ||f= y # t        $ r t        dj                  ||            w xY w)Nz)Perf event type {} config {} not attachedr   z$Failed to detach BPF from perf event)rM  r  r-  r  valuesr   r?  )r/   r  r  fdsr@   r!  s         r   detach_perf_eventzBPF.detach_perf_event  s    	%'')(<=C
 **, 	9B--b18SC	9!8BCC!!7I"67  	%GNN$ % %	%s   A# #%Bc                 r    t        t        j                  | |      D  cg c]  \  } }| 	 c}}       S c c}} w r   r  r    get_user_functions_and_addresses)r<   sym_rer  s      r   get_user_functionszBPF.get_user_functions  s<    88vFHYdAD H I 	I H   3
c                 r    t        t        j                  | |      D cg c]  \  }}|	 c}}      S c c}}w )a  
        We are returning addresses here instead of symbol names because it
        turns out that the same name may appear multiple times with different
        addresses, and the same address may appear multiple times with the same
        name. We can't attach a uprobe to the same address more than once, so
        it makes sense to return the unique set of addresses that are mapped to
        a symbol that matches the provided regular expression.
        r  )r<   r  r  addresss       r   get_user_addresseszBPF.get_user_addresses  s>     88vFHGG H I 	I Hr  c                     t        |       } t              g fd}t        j                  | t        |            }|dk  rt	        d|| fz        S )Nc                 \    | }t        j                  |      rj                  ||f       yrY  )r  r  rt  )sym_namer=   dname	addressesr  s      r   sym_cbz4BPF.get_user_functions_and_addresses.<locals>.sym_cb#  s+    Exx&  %/r   r   z"Error %d enumerating symbols in %s)r   r   bcc_foreach_function_symbolr	   r-  )r<   r  r  r@   r  s    `  @r   r  z$BPF.get_user_functions_and_addresses  s\    %!&)		 --dL4HI7@C;NOOr   c                     |dk(  r"d|| j                   j                  d|      |fz  S d|| j                   j                  d|      ||fz  S )NrD   s
   %s_%s_0x%xr,  s   %s_%s_0x%x_%d)_probe_replsub)r/   r  r%  r=   r0   s        r   _get_uprobe_evnamezBPF._get_uprobe_evname.  sY    "9 FD,<,<,@,@t,Ld#SSS $vt/?/?/C/CD$/OQUWZ&[[[r   c                 t   |dk\  sJ ||dk(  sJ d       t        |      }t        |      }t        |      }t        |      }|rMt        j                  ||      }| j                  t	        |             |D ]  }	| j                  ||	||        yt        j                  |||||      \  }
}| j                  d       | j                  |t        j                        }| j                  d|
||      }t        j                  |j                  d||
||      }|dk  rt        d      | j                  ||       | S )a  attach_uprobe(name="", sym="", sym_re="", addr=None, fn_name=""
                         pid=-1, sym_off=0)

        Run the bpf function denoted by fn_name every time the symbol sym in
        the library or binary 'name' is encountered. Optional parameters pid,
        cpu, and group_fd can be used to filter the probe.

        If sym_off is given, attach uprobe to offset within the symbol.

        The real address addr may be supplied in place of sym, in which case sym
        must be set to its default value. If the file is a non-PIE executable,
        addr must be a virtual address, otherwise it must be an offset relative
        to the file load address.

        Instead of a symbol name, a regular expression can be provided in
        sym_re. The uprobe will then attach to symbols that match the provided
        regular expression.

        Libraries can be given in the name argument without the lib prefix, or
        with the full path (/usr/lib/...). Binaries can be given only with the
        full path (/bin/sh). If a PID is given, the uprobe will attach to the
        version of the library used by the process.

        Example: BPF(text).attach_uprobe("c", "malloc")
                 BPF(text).attach_uprobe("/usr/bin/python", "main")
        r   Nz!offset with addr is not supportedr<   r=   r  r0   r      pzFailed to attach BPF to uprobe)r   r   r  r  rV  attach_uproberW  ru  r   r  r   bpf_attach_uprober!  r-  r  )r/   r<   r?   r  r=   r  r0   rS  r  sym_addrr%  r  r  r!  s                 r   r  zBPF.attach_uprobe6  sA   : !||a<D!DD<%s#!&)"7+..tV<I##C	N3% =""8+2 # == --dCsGLt"^^GSZZ0))$dC@""255!WdD#F6<==GR(r   c                    t        |      }t        |      }t        |      }t        |      }|r1t        j                  ||      D ]  }| j                  ||||        yt        j	                  ||||      \  }}| j                  d       | j                  |t        j                        }	| j                  d|||      }
t        j                  |	j                  d|
|||      }|dk  rt        d      | j                  |
|       | S )a6  attach_uretprobe(name="", sym="", sym_re="", addr=None, fn_name=""
                            pid=-1)

        Run the bpf function denoted by fn_name every time the symbol sym in
        the library or binary 'name' finishes execution. See attach_uprobe for
        meaning of additional parameters.
        r  Nr      rr   z!Failed to attach BPF to uretprobe)r   r   r  attach_uretproberW  r  ru  r   r  r   r  r!  r-  r  )r/   r<   r?   r  r=   r  r0   r  r%  r  r  r!  s               r   r  zBPF.attach_uretprobeo  s     %s#!&)"7+224@ @%%4h.53 & @@ --dCsCt"^^GSZZ0))$dC@""255!WdD#F6?@@GR(r   c                    || j                   vrt        d|z        t        j                  | j                   |         }|dk  rt        d      t        j                  |      }|dk  rt        d      | j                  |       y )NzUprobe %s is not attachedr   z Failed to detach BPF from uprobe)rF  r-  r   r?  bpf_detach_uprober  )r/   r  r@   s      r   detach_uprobe_eventzBPF.detach_uprobe_event  s|    $//)7'ABB))$//'*BC7>??##G,7>??G$r   c                     t        |      }t        |      }t        j                  |||||      \  }}| j                  d|||      }| j	                  |       y)zdetach_uprobe(name="", sym="", addr=None, pid=-1)

        Stop running a bpf function that is attached to symbol 'sym' in library
        or binary 'name'.
        r  Nr   r   rW  r  r  )r/   r<   r?   r=   r0   rS  r%  r  s           r   detach_uprobezBPF.detach_uprobe  sX      %s#--dCsGLt))$dC@  )r   c                     t        |      }t        |      }t        j                  ||||      \  }}| j                  d|||      }| j	                  |       y)zdetach_uretprobe(name="", sym="", addr=None, pid=-1)

        Stop running a bpf function that is attached to symbol 'sym' in library
        or binary 'name'.
        r  Nr  )r/   r<   r?   r=   r0   r%  r  s          r   detach_uretprobezBPF.detach_uretprobe  sV      %s#--dCsCt))$dC@  )r   c                    t        dt        j                  | j                              D ]4  }t        j                  | j                  |      }|j                  d      rP| j                  |t        j                        }| j                  | j                  |dd        |j                         |j                  d      rP| j                  |t        j                        }| j                  | j                  |dd        |j                         |j                  d      rg| j                  |t        j                        }|j                  t        d      d  j                  dd	      }| j!                  ||j                  
       ^|j                  d      rW| j                  |t        j"                        }|j                  t        d      d  }| j%                  ||j                  
       |j                  d      r| j'                  |       |j                  d      r| j)                  |       |j                  d      s#| j+                  |       7 y )Nr   s   kprobe__r$   r%  s   kretprobe__r   s   tracepoint__s   __rp  ro  s   raw_tracepoint__r  )r  r  r  )rq  r   rr  r6   rs  r  ru  r   r   r.  r#  r<   r8  rQ   rV  r/  rq  r   rw  r  r  r  )r/   rj  rx  r  rj  s        r   r`  zBPF._trace_autoload  s   q#//<= 	3A--dkk1=I##K0^^Iszz:""11)AB-@GG # % %%n5^^Iszz:%%11)BC.AGG & % %%o6^^Is~~>WWS123;;E4H&&"bgg&>%%&9:^^Is/A/ABWWS!4567**b"''*B%%j1!!)!4%%m4$$Y$7%%h/	23	3r   c                 N   | j                   st        dt        z  d      | _         |rt| j                   j                         }t	        j                  |t        j
                        }t	        j                  |t        j                  |t        j                  z         | j                   S )zWtrace_open(nonblocking=False)

        Open the trace_pipe if not already open
        z%s/trace_piperC  )	rO  rY  ra  filenofcntlF_GETFLF_SETFLr  
O_NONBLOCK)r/   nonblockingr!  fls       r   
trace_openzBPF.trace_open  sn    
 ~~!/G";TBDN^^**,[[U]]3BrBMM/AB~~r   c                    	 | j                  |      }|s|ry|j                  d      r)|dd j                         }|dd }|j                  d      }	 |d| j	                         \  }}}}|dd }||dz   d }|j                  d      }
||
d	z   d }	 |t        |      t        |      |t        |      |fS # t
        $ r
}	Y d}	~	d}	~	ww xY w# t
        $ r
}	Y d}	~	y
d}	~	ww xY w)ztrace_fields(nonblocking=False)

        Read from the kernel debug trace pipe and return a tuple of the
        fields (task, pid, cpu, flags, timestamp, msg) or None if no
        line was read (nonblocking=True)
        )NNNNNNs   CPU:Nr%   r   rp  r   rD   r"   )Unknownr   r   r  g        r  )trace_readliner  lstripfindr9  r-  r  r  )r/   r  r  taskts_endr0   r  r  tsr  sym_endmsgs               r   trace_fieldszBPF.trace_fields  s    &&{3DKw'9##%D9DYYt_F&*7Fm&9&9&;#S% a)C 
$DiioGw{|$CDc#hC%rCHH    DCDs$   B6 "C 6	C	C		CCc                     | j                  |      }d}	 |j                  d      j                         }|S # t        $ r Y |S w xY w)ztrace_readline(nonblocking=False)

        Read from the kernel debug trace pipe and return one line
        If nonblocking is False, this will block until ctrl-C is pressed.
        Nrw   )r  readliner  r  )r/   r  tracer  s       r   r  zBPF.trace_readline  sS     ,	>>$'..0D   		s   6 	AAc                     	 |r%| j                  d      }|s |j                  | }n| j                  d      }t        |       t        j
                  j                          c)a  trace_print(self, fmt=None)

        Read from the kernel debug trace pipe and print on stdout.
        If fmt is specified, apply as a format string to the output. See
        trace_fields for the members of the tuple
        example: trace_print(fmt="pid {1}, msg = {5}")
        F)r  )r  r  r  printr'  stdoutflush)r/   fmtr  r  s       r   trace_printzBPF.trace_print  sa     **u*=x!szz6***u*=$KJJ r   c                     | dk  r| dk7  rd} | t         j                  vrt        |       t         j                  | <   t         j                  |    S )z_sym_cache(pid)

        Returns a symbol cache for the specified PID.
        The kernel symbol cache is accessed by providing any PID less than zero.
        r   rD   )r   _sym_cachesr(   )r0   s    r   
_sym_cachezBPF._sym_cache$  sD     7sbyCcoo%#.s#3COOC s##r   c                    t        t        |             }|j                  d      dk7  rXt               }t	               }| j
                  |_        | j                  |_        | j                  |j                  _        t        j                  t        j                  t        j                  |      t        j                  |            }|dk  rf|j                  rS|j                  rGd|j                  t        j                   |j                  t        j"                        j$                  }}
}	nd| d}}
}	nz|j&                  |j                  t        j                   |j                  t        j"                        j$                  }}
}	n)t        j)                  |      j+                  | |      \  }	}
}|r|	d|
z  nd}
|	xs d}	|	|
z   }	|r$|"dt,        j.                  j1                  |      z  nd}|	|z   S )	ay  sym(addr, pid, show_module=False, show_offset=False)

        Translate a memory address into a function name for a pid, which is
        returned. When show_module is True, the module name is also included.
        When show_offset is True, the instruction offset as a hexadecimal
        number is also included in the string.

        A pid of less than zero will access the kernel symbol cache.

        Example output when both show_module and show_offset are True:
            "start_thread+0x202 [libpthread-2.24.so]"

        Example output when both show_module and show_offset are False:
            "start_thread"
        bpf_stack_build_idrD   r   Ns   +0x%xr   s	   [unknown]s    [%s])r  r  r  r   r   statusbuild_idr7   ur   bcc_buildsymcache_resolver   
_bsymcacher+   r4   r6   r,   r8   r9   r<   r  rB   r  r%  basename)r=   r0   show_moduleshow_offsetr>   
typeofaddrr?   br@   r<   r7   r6   s               r   r?   zBPF.sym1  s   ( d_
??/0B6#%'![[!(}}!*{{!##*--cnn.0hhqk.0hhsm=# 1Wzzcjj$(#**

BKK8>> !6d '+D$FFd$'HHcjj$&GGCJJ$D$J$J !&D "%!4!<!<T8!L
$&1d6FF"C#|f}v1 BGG,,V447: 	f}r   c                 4    t         j                  | d||d      S )a  ksym(addr)

        Translate a kernel memory address into a kernel function name, which is
        returned. When show_module is True, the module name ("kernel") is also
        included. When show_offset is true, the instruction offset as a
        hexadecimal number is also included in the string.

        Example output when both show_module and show_offset are True:
            "default_idle+0x0 [kernel]"
        rD   F)r   r?   )r=   r  r  s      r   ksymzBPF.ksymb  s     wwtRk5AAr   c                 L    t         j                  d      j                  d|       S )zksymname(name)

        Translate a kernel name into an address. This is the reverse of
        ksym. Returns -1 when the function name is unknown.rD   N)r   r  rG   )r<   s    r   r  zBPF.ksymnamep  s      ~~b!..tT::r   c                 ,    t        | j                        S )znum_open_kprobes()

        Get the number of open K[ret]probes. Can be useful for scenarios where
        event_re is used while attaching and detaching probes.
        )rV  rE  r  s    r   num_open_kprobeszBPF.num_open_kprobesx  s     4??##r   c                 ,    t        | j                        S )zInum_open_uprobes()

        Get the number of open U[ret]probes.
        )rV  rF  r  s    r   num_open_uprobeszBPF.num_open_uprobes  s    
 4??##r   c                 ,    t        | j                        S )zLnum_open_tracepoints()

        Get the number of open tracepoints.
        )rV  rG  r  s    r   num_open_tracepointszBPF.num_open_tracepoints  s    
 4&&''r   c                     t        j                  t        | j                        z         }t	        | j                  j                               D ]
  \  }}|||<    t        j                  t        |      ||       y)zperf_buffer_poll(self)

        Poll from all open perf ring buffers, calling the callback that was
        provided when calling open_perf_buffer for each entry.
        N)r+   r[  rV  rL  rW  r  r   perf_reader_poll)r/   timeoutreadersrj  vs        r   perf_buffer_pollzBPF.perf_buffer_poll  sf     ;;T%6%6!77:d//6689 	DAqGAJ	S\7G<r   c                     t        j                  t        | j                        z         }t	        | j                  j                               D ]
  \  }}|||<    t        j                  t        |      |       y)zperf_buffer_consume(self)

        Consume all open perf buffers, regardless of whether or not
        they currently contain events data. Necessary to catch 'remainder'
        events when wakeup_events > 1 is set in open_perf_buffer
        N)r+   r[  rV  rL  rW  r  r   perf_reader_consume)r/   r!  rj  r"  s       r   perf_buffer_consumezBPF.perf_buffer_consume  sd     ;;T%6%6!77:d//6689 	DAqGAJ	Gg6r   c                 &    | j                  |       y)zMkprobe_poll(self)

        Deprecated. Use perf_buffer_poll instead.
        N)r#  r/   r   s     r   kprobe_pollzBPF.kprobe_poll  s    
 	g&r   c                     | j                   s4t        j                  |||      | _         | j                   st        d      y t        j                  | j                   |||      }|dk  rt        d      y )NzCould not open ring bufferr   )rN  r   bpf_new_ringbufr-  bpf_add_ringbuf)r/   r  r  ctxrets        r   _open_ring_bufferzBPF._open_ring_buffer  sr    $$$'$7$7C$HD!(( <== ) %%d&;&;VRMCQw <== r   c                 r    | j                   st        d      t        j                  | j                   |       y)zring_buffer_poll(self)

        Poll from all open ringbuf buffers, calling the callback that was
        provided when calling open_ring_buffer for each entry.
        No ring buffers to pollN)rN  r-  r   bpf_poll_ringbufr(  s     r   ring_buffer_pollzBPF.ring_buffer_poll  s/     $$566T22G<r   c                 p    | j                   st        d      t        j                  | j                          y)a/  ring_buffer_consume(self)

        Consume all open ringbuf buffers, regardless of whether or not
        they currently contain events data. This is best for use cases
        where low latency is desired, but it can impact performance.
        If you are unsure, use ring_buffer_poll instead.
        r1  N)rN  r-  r   bpf_consume_ringbufr  s    r   ring_buffer_consumezBPF.ring_buffer_consume  s-     $$566 5 56r   c                 *    t        j                         S r   )r   bcc_free_memoryr  s    r   free_bcc_memoryzBPF.free_bcc_memory  s    ""$$r   c                     	 t        j                  t        j                  | j	                                y# t
        $ r!}t        dt        |      z          Y d}~yd}~ww xY w)zJadd_module(modname)

        Add a library or exe to buildsym cache
      z&Error adding module to build sym cacheN)r   bcc_buildsymcache_add_moduler   r  r=  r-  r  r  )modnamer  s     r   
add_modulezBPF.add_module  sG    ?((9IJ ?6s1v=>>?s   25 	AAAc                      y)zthe do nothing exit handlerNr   r  s    r   r  zBPF.donothing  s    r   c                    t        | j                  j                               D ]1  \  }}t        j                  |j
                         | j                  |= 3 | j                  r't        j                  | j                         d| _        yy)zvclose(self)

        Closes all associated files descriptors. Attached BPF programs are not
        detached.
        N)	r  rT  r  r  ry  r!  r6   r   bpf_module_destroy)r/   r<   r  s      r   ry  z	BPF.close  sk     TZZ--/0 	!HD"HHRUUO

4 	! ;;""4;;/DK r   c                 P   t        | j                  j                               D ]  \  }}| j                  |        t        | j                  j                               D ]  \  }}| j                  |        t        | j                  j                               D ]  \  }}| j                  |        t        | j                  j                               D ]  \  }}| j                  |        t        | j                  j                               D ]  \  }}| j                  |        t        | j                  j                               D ]  \  }}| j                  |        t        | j                  j                               D ]  \  }}| j                  |        t        | j                   j#                               }|D ]-  }t%        | j                   |   t&              s!| j                   |= / t        | j(                  j#                               D ]  \  }}| j+                  ||        | j,                  r!| j,                  j/                          d | _        | j/                          | j0                  r't3        j4                  | j0                         d | _        y y r   )r  rE  r  r=  rF  r  rG  r  rH  rz  rI  r  rJ  r  rK  r  rU  r:  r  r   rM  r  rO  ry  rN  r   bpf_free_ringbuf)r/   kr"  
table_keysr  r  r  s          r   rR  zBPF.cleanup  sA   ..01 	(DAq$$Q'	(..01 	(DAq$$Q'	(,,2245 	&DAq""1%	&006689 	*DAq&&q)	*--3356 	!DAqa 	!,,2245 	$DAq  #	$++-. 	DAqOOA	 $++**,-
 	%C$++c*N;KK$	% %))>)>)C)C)E$F 	7 Wi""7I6	7>>NN  "!DN

     !6!67$(D! !r   c                     | S r   r   r  s    r   	__enter__zBPF.__enter__  s    r   c                 $    | j                          y r   )rR  )r/   exc_typeexc_valexc_tbs       r   __exit__zBPF.__exit__  s    r   )NrD   )F)NNN)r   )r   r   r   r   )r   r   r   r   r   )r   r   r   )r   r   )r   )rD   rD   r   r   r   rD   rD   rD   )rD   r   rD   rD   rD   )rD   rD   )r   r   r   Nr   rD   r   )r   r   r   Nr   rD   )r   r   NrD   r   )r   r   NrD   )FFT)FF)rD   )rH   rI   rJ   r   r   r   r   r   rQ   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   XDP_FLAGS_UPDATE_IF_NOEXISTr   XDP_FLAGS_SKB_MODEr   XDP_FLAGS_DRV_MODEr   XDP_FLAGS_HW_MODEr   XDP_FLAGS_REPLACEr  compiler  r  r   bcc_buildsymcache_newr  r  r  r	  r+   r  r  CDLL_librtclock_gettimer  c_intr-   argtypesclassmethodr  r  r
   objectr"  staticmethodr0  rA  r1   ry  ru  r  r  r  c_boolc_charc_wcharc_ubytec_shortc_ushortc_uintr  c_ulong
c_longlongrE   c_floatc_doublec_longdoublec_int64c_uint64r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r!  r#  r.  r8  r=  r;  rD  rG  rL  rN  rW  r]  rk  rm  rq  rw  rz  r|  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r`  r  r  r  r  r  r?   r  r  r  r  r  r#  r&  r)  r/  r3  r6  r9  r=  r  ry  rR  rF  rK  r   r   r   r   r     s,     --MF%%I%%I''J
//C''J''J))KF!!G##H##HF--MF //N"33!!G
//C''K!!H!!HF))L"*"<"<!**!** (( (( "**-.KK***,J  Vn ), 	'6N OC2<< C RWW\T2F))N!xxH)=>N	* 	*    E6  
 
  8 !$cARd4#(N` $* @
)3P
")) 	BJJ 	"**	
 	"** 	2;; 	 	 	 	"** 	bmm 	r~~ 	"** 	2;; 	  	RZZ!^!" 	bkkAo#I& ) )VU& 
  & O O O O   I IVO
 ( (

)0 D D=D.. - -& 
- 
- % %$     & &$L0(  
 	 	  *)"   	 	 D D
$* CFEG:>8 I I 
I 
I  \ AE)*7r DH@	%**38!DF & 
$ 
$ . .` B B ; ;$$(	=
7'>=
7% ? ?*!)Fr   r   )D
__future__r   rP  ctypesr+   r  r  r  r  r  r'  r  libbccr   r   r   r   r	   tabler
   r   r   r   r   perfr   utilsr   r   r   r   r   versionr   disassemblerr   r   rm  r   r   r  	NameErrorr  r  r   r    r  r%  r)  ra  existsDEBUG_LLVM_IRr  DEBUG_PREPROCESSORDEBUG_SOURCEr~  	DEBUG_BTFrY  r(   rL   rV   re   rs   r   r   r   r   r   r   r   r   <module>rw     s3   &     	 	  
  ] ] Y Y  V V   6 %    
'',,w	
*	ww~~g#G
 	  	)& )V    8 0( (T  P& P}  Js   2D) )D32D3