Back to home page

OSCL-LXR

 
 

    


0001 .. SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
0002 
0003 ==============
0004 BPF drgn tools
0005 ==============
0006 
0007 drgn scripts is a convenient and easy to use mechanism to retrieve arbitrary
0008 kernel data structures. drgn is not relying on kernel UAPI to read the data.
0009 Instead it's reading directly from ``/proc/kcore`` or vmcore and pretty prints
0010 the data based on DWARF debug information from vmlinux.
0011 
0012 This document describes BPF related drgn tools.
0013 
0014 See `drgn/tools`_ for all tools available at the moment and `drgn/doc`_ for
0015 more details on drgn itself.
0016 
0017 bpf_inspect.py
0018 --------------
0019 
0020 Description
0021 ===========
0022 
0023 `bpf_inspect.py`_ is a tool intended to inspect BPF programs and maps. It can
0024 iterate over all programs and maps in the system and print basic information
0025 about these objects, including id, type and name.
0026 
0027 The main use-case `bpf_inspect.py`_ covers is to show BPF programs of types
0028 ``BPF_PROG_TYPE_EXT`` and ``BPF_PROG_TYPE_TRACING`` attached to other BPF
0029 programs via ``freplace``/``fentry``/``fexit`` mechanisms, since there is no
0030 user-space API to get this information.
0031 
0032 Getting started
0033 ===============
0034 
0035 List BPF programs (full names are obtained from BTF)::
0036 
0037     % sudo bpf_inspect.py prog
0038         27: BPF_PROG_TYPE_TRACEPOINT         tracepoint__tcp__tcp_send_reset
0039       4632: BPF_PROG_TYPE_CGROUP_SOCK_ADDR   tw_ipt_bind
0040      49464: BPF_PROG_TYPE_RAW_TRACEPOINT     raw_tracepoint__sched_process_exit
0041 
0042 List BPF maps::
0043 
0044       % sudo bpf_inspect.py map
0045         2577: BPF_MAP_TYPE_HASH                tw_ipt_vips
0046         4050: BPF_MAP_TYPE_STACK_TRACE         stack_traces
0047         4069: BPF_MAP_TYPE_PERCPU_ARRAY        ned_dctcp_cntr
0048 
0049 Find BPF programs attached to BPF program ``test_pkt_access``::
0050 
0051       % sudo bpf_inspect.py p | grep test_pkt_access
0052          650: BPF_PROG_TYPE_SCHED_CLS          test_pkt_access
0053          654: BPF_PROG_TYPE_TRACING            test_main                        linked:[650->25: BPF_TRAMP_FEXIT test_pkt_access->test_pkt_access()]
0054          655: BPF_PROG_TYPE_TRACING            test_subprog1                    linked:[650->29: BPF_TRAMP_FEXIT test_pkt_access->test_pkt_access_subprog1()]
0055          656: BPF_PROG_TYPE_TRACING            test_subprog2                    linked:[650->31: BPF_TRAMP_FEXIT test_pkt_access->test_pkt_access_subprog2()]
0056          657: BPF_PROG_TYPE_TRACING            test_subprog3                    linked:[650->21: BPF_TRAMP_FEXIT test_pkt_access->test_pkt_access_subprog3()]
0057          658: BPF_PROG_TYPE_EXT                new_get_skb_len                  linked:[650->16: BPF_TRAMP_REPLACE test_pkt_access->get_skb_len()]
0058          659: BPF_PROG_TYPE_EXT                new_get_skb_ifindex              linked:[650->23: BPF_TRAMP_REPLACE test_pkt_access->get_skb_ifindex()]
0059          660: BPF_PROG_TYPE_EXT                new_get_constant                 linked:[650->19: BPF_TRAMP_REPLACE test_pkt_access->get_constant()]
0060 
0061 It can be seen that there is a program ``test_pkt_access``, id 650 and there
0062 are multiple other tracing and ext programs attached to functions in
0063 ``test_pkt_access``.
0064 
0065 For example the line::
0066 
0067          658: BPF_PROG_TYPE_EXT                new_get_skb_len                  linked:[650->16: BPF_TRAMP_REPLACE test_pkt_access->get_skb_len()]
0068 
0069 , means that BPF program id 658, type ``BPF_PROG_TYPE_EXT``, name
0070 ``new_get_skb_len`` replaces (``BPF_TRAMP_REPLACE``) function ``get_skb_len()``
0071 that has BTF id 16 in BPF program id 650, name ``test_pkt_access``.
0072 
0073 Getting help:
0074 
0075 .. code-block:: none
0076 
0077     % sudo bpf_inspect.py
0078     usage: bpf_inspect.py [-h] {prog,p,map,m} ...
0079 
0080     drgn script to list BPF programs or maps and their properties
0081     unavailable via kernel API.
0082 
0083     See https://github.com/osandov/drgn/ for more details on drgn.
0084 
0085     optional arguments:
0086       -h, --help      show this help message and exit
0087 
0088     subcommands:
0089       {prog,p,map,m}
0090         prog (p)      list BPF programs
0091         map (m)       list BPF maps
0092 
0093 Customization
0094 =============
0095 
0096 The script is intended to be customized by developers to print relevant
0097 information about BPF programs, maps and other objects.
0098 
0099 For example, to print ``struct bpf_prog_aux`` for BPF program id 53077:
0100 
0101 .. code-block:: none
0102 
0103     % git diff
0104     diff --git a/tools/bpf_inspect.py b/tools/bpf_inspect.py
0105     index 650e228..aea2357 100755
0106     --- a/tools/bpf_inspect.py
0107     +++ b/tools/bpf_inspect.py
0108     @@ -112,7 +112,9 @@ def list_bpf_progs(args):
0109              if linked:
0110                  linked = f" linked:[{linked}]"
0111 
0112     -        print(f"{id_:>6}: {type_:32} {name:32} {linked}")
0113     +        if id_ == 53077:
0114     +            print(f"{id_:>6}: {type_:32} {name:32}")
0115     +            print(f"{bpf_prog.aux}")
0116 
0117 
0118      def list_bpf_maps(args):
0119 
0120 It produces the output::
0121 
0122     % sudo bpf_inspect.py p
0123      53077: BPF_PROG_TYPE_XDP                tw_xdp_policer
0124     *(struct bpf_prog_aux *)0xffff8893fad4b400 = {
0125             .refcnt = (atomic64_t){
0126                     .counter = (long)58,
0127             },
0128             .used_map_cnt = (u32)1,
0129             .max_ctx_offset = (u32)8,
0130             .max_pkt_offset = (u32)15,
0131             .max_tp_access = (u32)0,
0132             .stack_depth = (u32)8,
0133             .id = (u32)53077,
0134             .func_cnt = (u32)0,
0135             .func_idx = (u32)0,
0136             .attach_btf_id = (u32)0,
0137             .linked_prog = (struct bpf_prog *)0x0,
0138             .verifier_zext = (bool)0,
0139             .offload_requested = (bool)0,
0140             .attach_btf_trace = (bool)0,
0141             .func_proto_unreliable = (bool)0,
0142             .trampoline_prog_type = (enum bpf_tramp_prog_type)BPF_TRAMP_FENTRY,
0143             .trampoline = (struct bpf_trampoline *)0x0,
0144             .tramp_hlist = (struct hlist_node){
0145                     .next = (struct hlist_node *)0x0,
0146                     .pprev = (struct hlist_node **)0x0,
0147             },
0148             .attach_func_proto = (const struct btf_type *)0x0,
0149             .attach_func_name = (const char *)0x0,
0150             .func = (struct bpf_prog **)0x0,
0151             .jit_data = (void *)0x0,
0152             .poke_tab = (struct bpf_jit_poke_descriptor *)0x0,
0153             .size_poke_tab = (u32)0,
0154             .ksym_tnode = (struct latch_tree_node){
0155                     .node = (struct rb_node [2]){
0156                             {
0157                                     .__rb_parent_color = (unsigned long)18446612956263126665,
0158                                     .rb_right = (struct rb_node *)0x0,
0159                                     .rb_left = (struct rb_node *)0xffff88a0be3d0088,
0160                             },
0161                             {
0162                                     .__rb_parent_color = (unsigned long)18446612956263126689,
0163                                     .rb_right = (struct rb_node *)0x0,
0164                                     .rb_left = (struct rb_node *)0xffff88a0be3d00a0,
0165                             },
0166                     },
0167             },
0168             .ksym_lnode = (struct list_head){
0169                     .next = (struct list_head *)0xffff88bf481830b8,
0170                     .prev = (struct list_head *)0xffff888309f536b8,
0171             },
0172             .ops = (const struct bpf_prog_ops *)xdp_prog_ops+0x0 = 0xffffffff820fa350,
0173             .used_maps = (struct bpf_map **)0xffff889ff795de98,
0174             .prog = (struct bpf_prog *)0xffffc9000cf2d000,
0175             .user = (struct user_struct *)root_user+0x0 = 0xffffffff82444820,
0176             .load_time = (u64)2408348759285319,
0177             .cgroup_storage = (struct bpf_map *[2]){},
0178             .name = (char [16])"tw_xdp_policer",
0179             .security = (void *)0xffff889ff795d548,
0180             .offload = (struct bpf_prog_offload *)0x0,
0181             .btf = (struct btf *)0xffff8890ce6d0580,
0182             .func_info = (struct bpf_func_info *)0xffff889ff795d240,
0183             .func_info_aux = (struct bpf_func_info_aux *)0xffff889ff795de20,
0184             .linfo = (struct bpf_line_info *)0xffff888a707afc00,
0185             .jited_linfo = (void **)0xffff8893fad48600,
0186             .func_info_cnt = (u32)1,
0187             .nr_linfo = (u32)37,
0188             .linfo_idx = (u32)0,
0189             .num_exentries = (u32)0,
0190             .extable = (struct exception_table_entry *)0xffffffffa032d950,
0191             .stats = (struct bpf_prog_stats *)0x603fe3a1f6d0,
0192             .work = (struct work_struct){
0193                     .data = (atomic_long_t){
0194                             .counter = (long)0,
0195                     },
0196                     .entry = (struct list_head){
0197                             .next = (struct list_head *)0x0,
0198                             .prev = (struct list_head *)0x0,
0199                     },
0200                     .func = (work_func_t)0x0,
0201             },
0202             .rcu = (struct callback_head){
0203                     .next = (struct callback_head *)0x0,
0204                     .func = (void (*)(struct callback_head *))0x0,
0205             },
0206     }
0207 
0208 
0209 .. Links
0210 .. _drgn/doc: https://drgn.readthedocs.io/en/latest/
0211 .. _drgn/tools: https://github.com/osandov/drgn/tree/master/tools
0212 .. _bpf_inspect.py:
0213    https://github.com/osandov/drgn/blob/master/tools/bpf_inspect.py