drgn.rst 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. .. SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
  2. ==============
  3. BPF drgn tools
  4. ==============
  5. drgn scripts is a convenient and easy to use mechanism to retrieve arbitrary
  6. kernel data structures. drgn is not relying on kernel UAPI to read the data.
  7. Instead it's reading directly from ``/proc/kcore`` or vmcore and pretty prints
  8. the data based on DWARF debug information from vmlinux.
  9. This document describes BPF related drgn tools.
  10. See `drgn/tools`_ for all tools available at the moment and `drgn/doc`_ for
  11. more details on drgn itself.
  12. bpf_inspect.py
  13. --------------
  14. Description
  15. ===========
  16. `bpf_inspect.py`_ is a tool intended to inspect BPF programs and maps. It can
  17. iterate over all programs and maps in the system and print basic information
  18. about these objects, including id, type and name.
  19. The main use-case `bpf_inspect.py`_ covers is to show BPF programs of types
  20. ``BPF_PROG_TYPE_EXT`` and ``BPF_PROG_TYPE_TRACING`` attached to other BPF
  21. programs via ``freplace``/``fentry``/``fexit`` mechanisms, since there is no
  22. user-space API to get this information.
  23. Getting started
  24. ===============
  25. List BPF programs (full names are obtained from BTF)::
  26. % sudo bpf_inspect.py prog
  27. 27: BPF_PROG_TYPE_TRACEPOINT tracepoint__tcp__tcp_send_reset
  28. 4632: BPF_PROG_TYPE_CGROUP_SOCK_ADDR tw_ipt_bind
  29. 49464: BPF_PROG_TYPE_RAW_TRACEPOINT raw_tracepoint__sched_process_exit
  30. List BPF maps::
  31. % sudo bpf_inspect.py map
  32. 2577: BPF_MAP_TYPE_HASH tw_ipt_vips
  33. 4050: BPF_MAP_TYPE_STACK_TRACE stack_traces
  34. 4069: BPF_MAP_TYPE_PERCPU_ARRAY ned_dctcp_cntr
  35. Find BPF programs attached to BPF program ``test_pkt_access``::
  36. % sudo bpf_inspect.py p | grep test_pkt_access
  37. 650: BPF_PROG_TYPE_SCHED_CLS test_pkt_access
  38. 654: BPF_PROG_TYPE_TRACING test_main linked:[650->25: BPF_TRAMP_FEXIT test_pkt_access->test_pkt_access()]
  39. 655: BPF_PROG_TYPE_TRACING test_subprog1 linked:[650->29: BPF_TRAMP_FEXIT test_pkt_access->test_pkt_access_subprog1()]
  40. 656: BPF_PROG_TYPE_TRACING test_subprog2 linked:[650->31: BPF_TRAMP_FEXIT test_pkt_access->test_pkt_access_subprog2()]
  41. 657: BPF_PROG_TYPE_TRACING test_subprog3 linked:[650->21: BPF_TRAMP_FEXIT test_pkt_access->test_pkt_access_subprog3()]
  42. 658: BPF_PROG_TYPE_EXT new_get_skb_len linked:[650->16: BPF_TRAMP_REPLACE test_pkt_access->get_skb_len()]
  43. 659: BPF_PROG_TYPE_EXT new_get_skb_ifindex linked:[650->23: BPF_TRAMP_REPLACE test_pkt_access->get_skb_ifindex()]
  44. 660: BPF_PROG_TYPE_EXT new_get_constant linked:[650->19: BPF_TRAMP_REPLACE test_pkt_access->get_constant()]
  45. It can be seen that there is a program ``test_pkt_access``, id 650 and there
  46. are multiple other tracing and ext programs attached to functions in
  47. ``test_pkt_access``.
  48. For example the line::
  49. 658: BPF_PROG_TYPE_EXT new_get_skb_len linked:[650->16: BPF_TRAMP_REPLACE test_pkt_access->get_skb_len()]
  50. , means that BPF program id 658, type ``BPF_PROG_TYPE_EXT``, name
  51. ``new_get_skb_len`` replaces (``BPF_TRAMP_REPLACE``) function ``get_skb_len()``
  52. that has BTF id 16 in BPF program id 650, name ``test_pkt_access``.
  53. Getting help:
  54. .. code-block:: none
  55. % sudo bpf_inspect.py
  56. usage: bpf_inspect.py [-h] {prog,p,map,m} ...
  57. drgn script to list BPF programs or maps and their properties
  58. unavailable via kernel API.
  59. See https://github.com/osandov/drgn/ for more details on drgn.
  60. optional arguments:
  61. -h, --help show this help message and exit
  62. subcommands:
  63. {prog,p,map,m}
  64. prog (p) list BPF programs
  65. map (m) list BPF maps
  66. Customization
  67. =============
  68. The script is intended to be customized by developers to print relevant
  69. information about BPF programs, maps and other objects.
  70. For example, to print ``struct bpf_prog_aux`` for BPF program id 53077:
  71. .. code-block:: none
  72. % git diff
  73. diff --git a/tools/bpf_inspect.py b/tools/bpf_inspect.py
  74. index 650e228..aea2357 100755
  75. --- a/tools/bpf_inspect.py
  76. +++ b/tools/bpf_inspect.py
  77. @@ -112,7 +112,9 @@ def list_bpf_progs(args):
  78. if linked:
  79. linked = f" linked:[{linked}]"
  80. - print(f"{id_:>6}: {type_:32} {name:32} {linked}")
  81. + if id_ == 53077:
  82. + print(f"{id_:>6}: {type_:32} {name:32}")
  83. + print(f"{bpf_prog.aux}")
  84. def list_bpf_maps(args):
  85. It produces the output::
  86. % sudo bpf_inspect.py p
  87. 53077: BPF_PROG_TYPE_XDP tw_xdp_policer
  88. *(struct bpf_prog_aux *)0xffff8893fad4b400 = {
  89. .refcnt = (atomic64_t){
  90. .counter = (long)58,
  91. },
  92. .used_map_cnt = (u32)1,
  93. .max_ctx_offset = (u32)8,
  94. .max_pkt_offset = (u32)15,
  95. .max_tp_access = (u32)0,
  96. .stack_depth = (u32)8,
  97. .id = (u32)53077,
  98. .func_cnt = (u32)0,
  99. .func_idx = (u32)0,
  100. .attach_btf_id = (u32)0,
  101. .linked_prog = (struct bpf_prog *)0x0,
  102. .verifier_zext = (bool)0,
  103. .offload_requested = (bool)0,
  104. .attach_btf_trace = (bool)0,
  105. .func_proto_unreliable = (bool)0,
  106. .trampoline_prog_type = (enum bpf_tramp_prog_type)BPF_TRAMP_FENTRY,
  107. .trampoline = (struct bpf_trampoline *)0x0,
  108. .tramp_hlist = (struct hlist_node){
  109. .next = (struct hlist_node *)0x0,
  110. .pprev = (struct hlist_node **)0x0,
  111. },
  112. .attach_func_proto = (const struct btf_type *)0x0,
  113. .attach_func_name = (const char *)0x0,
  114. .func = (struct bpf_prog **)0x0,
  115. .jit_data = (void *)0x0,
  116. .poke_tab = (struct bpf_jit_poke_descriptor *)0x0,
  117. .size_poke_tab = (u32)0,
  118. .ksym_tnode = (struct latch_tree_node){
  119. .node = (struct rb_node [2]){
  120. {
  121. .__rb_parent_color = (unsigned long)18446612956263126665,
  122. .rb_right = (struct rb_node *)0x0,
  123. .rb_left = (struct rb_node *)0xffff88a0be3d0088,
  124. },
  125. {
  126. .__rb_parent_color = (unsigned long)18446612956263126689,
  127. .rb_right = (struct rb_node *)0x0,
  128. .rb_left = (struct rb_node *)0xffff88a0be3d00a0,
  129. },
  130. },
  131. },
  132. .ksym_lnode = (struct list_head){
  133. .next = (struct list_head *)0xffff88bf481830b8,
  134. .prev = (struct list_head *)0xffff888309f536b8,
  135. },
  136. .ops = (const struct bpf_prog_ops *)xdp_prog_ops+0x0 = 0xffffffff820fa350,
  137. .used_maps = (struct bpf_map **)0xffff889ff795de98,
  138. .prog = (struct bpf_prog *)0xffffc9000cf2d000,
  139. .user = (struct user_struct *)root_user+0x0 = 0xffffffff82444820,
  140. .load_time = (u64)2408348759285319,
  141. .cgroup_storage = (struct bpf_map *[2]){},
  142. .name = (char [16])"tw_xdp_policer",
  143. .security = (void *)0xffff889ff795d548,
  144. .offload = (struct bpf_prog_offload *)0x0,
  145. .btf = (struct btf *)0xffff8890ce6d0580,
  146. .func_info = (struct bpf_func_info *)0xffff889ff795d240,
  147. .func_info_aux = (struct bpf_func_info_aux *)0xffff889ff795de20,
  148. .linfo = (struct bpf_line_info *)0xffff888a707afc00,
  149. .jited_linfo = (void **)0xffff8893fad48600,
  150. .func_info_cnt = (u32)1,
  151. .nr_linfo = (u32)37,
  152. .linfo_idx = (u32)0,
  153. .num_exentries = (u32)0,
  154. .extable = (struct exception_table_entry *)0xffffffffa032d950,
  155. .stats = (struct bpf_prog_stats *)0x603fe3a1f6d0,
  156. .work = (struct work_struct){
  157. .data = (atomic_long_t){
  158. .counter = (long)0,
  159. },
  160. .entry = (struct list_head){
  161. .next = (struct list_head *)0x0,
  162. .prev = (struct list_head *)0x0,
  163. },
  164. .func = (work_func_t)0x0,
  165. },
  166. .rcu = (struct callback_head){
  167. .next = (struct callback_head *)0x0,
  168. .func = (void (*)(struct callback_head *))0x0,
  169. },
  170. }
  171. .. Links
  172. .. _drgn/doc: https://drgn.readthedocs.io/en/latest/
  173. .. _drgn/tools: https://github.com/osandov/drgn/tree/master/tools
  174. .. _bpf_inspect.py:
  175. https://github.com/osandov/drgn/blob/master/tools/bpf_inspect.py