History

Merge branch 'bpf_line_info'

Martin Lau says: ==================== This patch series introduces the bpf_line_info. Please see individual patch for details. It will be useful for introspection purpose, like: [root@arch-fb-vm1 bpf]# ~/devshare/fb-kernel/linux/tools/bpf/bpftool/bpftool prog dump jited pinned /sys/fs/bpf/test_btf_haskv [...] int test_long_fname_2(struct dummy_tracepoint_args * arg): bpf_prog_44a040bf25481309_test_long_fname_2: ; static int test_long_fname_2(struct dummy_tracepoint_args *arg) 0: push %rbp 1: mov %rsp,%rbp 4: sub $0x30,%rsp b: sub $0x28,%rbp f: mov %rbx,0x0(%rbp) 13: mov %r13,0x8(%rbp) 17: mov %r14,0x10(%rbp) 1b: mov %r15,0x18(%rbp) 1f: xor %eax,%eax 21: mov %rax,0x20(%rbp) 25: xor %esi,%esi ; int key = 0; 27: mov %esi,-0x4(%rbp) ; if (!arg->sock) 2a: mov 0x8(%rdi),%rdi ; if (!arg->sock) 2e: cmp $0x0,%rdi 32: je 0x0000000000000070 34: mov %rbp,%rsi ; counts = bpf_map_lookup_elem(&btf_map, &key); 37: add $0xfffffffffffffffc,%rsi 3b: movabs $0xffff8881139d7480,%rdi 45: add $0x110,%rdi 4c: mov 0x0(%rsi),%eax 4f: cmp $0x4,%rax 53: jae 0x000000000000005e 55: shl $0x3,%rax 59: add %rdi,%rax 5c: jmp 0x0000000000000060 5e: xor %eax,%eax ; if (!counts) 60: cmp $0x0,%rax 64: je 0x0000000000000070 ; counts->v6++; 66: mov 0x4(%rax),%edi 69: add $0x1,%rdi 6d: mov %edi,0x4(%rax) 70: mov 0x0(%rbp),%rbx 74: mov 0x8(%rbp),%r13 78: mov 0x10(%rbp),%r14 7c: mov 0x18(%rbp),%r15 80: add $0x28,%rbp 84: leaveq 85: retq [...] ====================

Alexei Starovoitov committed 7 years ago

Commit ca5d1a72 parents 6baefa1 b053b4329 files · +2036 −388Browse files

Unified · Split

29 files
  1. arch/x86/net/bpf_jit_comp.c +2 −0
  2. include/linux/bpf.h +21 −0
  3. include/linux/bpf_verifier.h +1 −0
  4. include/linux/btf.h +1 −0
  5. include/linux/filter.h +7 −0
  6. include/uapi/linux/bpf.h +19 −0
  7. kernel/bpf/btf.c +1 −1
  8. kernel/bpf/core.c +116 −2
  9. kernel/bpf/syscall.c +77 −6
  10. kernel/bpf/verifier.c +174 −24
  11. tools/bpf/bpftool/Documentation/bpftool-prog.rst +12 −4
  12. tools/bpf/bpftool/bash-completion/bpftool +3 −3
  13. tools/bpf/bpftool/btf_dumper.c +64 −0
  14. tools/bpf/bpftool/jit_disasm.c +22 −1
  15. tools/bpf/bpftool/main.h +21 −2
  16. tools/bpf/bpftool/prog.c +90 −10
  17. tools/bpf/bpftool/xlated_dumper.c +28 −2
  18. tools/bpf/bpftool/xlated_dumper.h +5 −2
  19. tools/include/uapi/linux/bpf.h +19 −0
  20. tools/lib/bpf/Build +1 −1
  21. tools/lib/bpf/bpf.c +62 −31
  22. tools/lib/bpf/bpf.h +3 −0
  23. tools/lib/bpf/bpf_prog_linfo.c +253 −0
  24. tools/lib/bpf/btf.c +194 −148
  25. tools/lib/bpf/btf.h +12 −13
  26. tools/lib/bpf/libbpf.c +115 −44
  27. tools/lib/bpf/libbpf.h +13 −0
  28. tools/lib/bpf/libbpf.map +4 −0
  29. tools/testing/selftests/bpf/test_btf.c +696 −94
arch/x86/net/bpf_jit_comp.c+2−0
@@ -1181,6 +1181,8 @@ out_image: · 1180 unmodified lines
1181 }1181 }
1182 1182
1183 if (!image || !prog->is_func || extra_pass) {1183 if (!image || !prog->is_func || extra_pass) {
1184 if (image)
1185 bpf_prog_fill_jited_linfo(prog, addrs);
1184out_addrs:1186out_addrs:
1185 kfree(addrs);1187 kfree(addrs);
1186 kfree(jit_data);1188 kfree(jit_data);
include/linux/bpf.h+21−0
@@ -319,7 +319,28 @@ struct bpf_prog_aux { · 318 unmodified lines
319 struct bpf_prog_offload *offload;319 struct bpf_prog_offload *offload;
320 struct btf *btf;320 struct btf *btf;
321 struct bpf_func_info *func_info;321 struct bpf_func_info *func_info;
322 /* bpf_line_info loaded from userspace. linfo->insn_off
323 * has the xlated insn offset.
324 * Both the main and sub prog share the same linfo.
325 * The subprog can access its first linfo by
326 * using the linfo_idx.
327 */
328 struct bpf_line_info *linfo;
329 /* jited_linfo is the jited addr of the linfo. It has a
330 * one to one mapping to linfo:
331 * jited_linfo[i] is the jited addr for the linfo[i]->insn_off.
332 * Both the main and sub prog share the same jited_linfo.
333 * The subprog can access its first jited_linfo by
334 * using the linfo_idx.
335 */
336 void **jited_linfo;
322 u32 func_info_cnt;337 u32 func_info_cnt;
338 u32 nr_linfo;
339 /* subprog can use linfo_idx to access its first linfo and
340 * jited_linfo.
341 * main prog always has linfo_idx == 0
342 */
343 u32 linfo_idx;
323 union {344 union {
324 struct work_struct work;345 struct work_struct work;
325 struct rcu_head rcu;346 struct rcu_head rcu;
include/linux/bpf_verifier.h+1−0
@@ -203,6 +203,7 @@ static inline bool bpf_verifier_log_needed(const struct bpf_verifier_log *log) · 202 unmodified lines
203 203
204struct bpf_subprog_info {204struct bpf_subprog_info {
205 u32 start; /* insn idx of function entry point */205 u32 start; /* insn idx of function entry point */
206 u32 linfo_idx; /* The idx to the main_prog->aux->linfo */
206 u16 stack_depth; /* max. stack depth used by this function */207 u16 stack_depth; /* max. stack depth used by this function */
207};208};
208 209
include/linux/btf.h+1−0
@@ -46,6 +46,7 @@ void btf_type_seq_show(const struct btf *btf, u32 type_id, void *obj, · 45 unmodified lines
46 struct seq_file *m);46 struct seq_file *m);
47int btf_get_fd_by_id(u32 id);47int btf_get_fd_by_id(u32 id);
48u32 btf_id(const struct btf *btf);48u32 btf_id(const struct btf *btf);
49bool btf_name_offset_valid(const struct btf *btf, u32 offset);
49 50
50#ifdef CONFIG_BPF_SYSCALL51#ifdef CONFIG_BPF_SYSCALL
51const struct btf_type *btf_type_by_id(const struct btf *btf, u32 type_id);52const struct btf_type *btf_type_by_id(const struct btf *btf, u32 type_id);
include/linux/filter.h+7−0
@@ -718,6 +718,13 @@ void bpf_prog_free(struct bpf_prog *fp); · 717 unmodified lines
718 718
719bool bpf_opcode_in_insntable(u8 code);719bool bpf_opcode_in_insntable(u8 code);
720 720
721void bpf_prog_free_linfo(struct bpf_prog *prog);
722void bpf_prog_fill_jited_linfo(struct bpf_prog *prog,
723 const u32 *insn_to_jit_off);
724int bpf_prog_alloc_jited_linfo(struct bpf_prog *prog);
725void bpf_prog_free_jited_linfo(struct bpf_prog *prog);
726void bpf_prog_free_unused_jited_linfo(struct bpf_prog *prog);
727
721struct bpf_prog *bpf_prog_alloc(unsigned int size, gfp_t gfp_extra_flags);728struct bpf_prog *bpf_prog_alloc(unsigned int size, gfp_t gfp_extra_flags);
722struct bpf_prog *bpf_prog_realloc(struct bpf_prog *fp_old, unsigned int size,729struct bpf_prog *bpf_prog_realloc(struct bpf_prog *fp_old, unsigned int size,
723 gfp_t gfp_extra_flags);730 gfp_t gfp_extra_flags);
include/uapi/linux/bpf.h+19−0
@@ -356,6 +356,9 @@ union bpf_attr { · 355 unmodified lines
356 __u32 func_info_rec_size; /* userspace bpf_func_info size */356 __u32 func_info_rec_size; /* userspace bpf_func_info size */
357 __aligned_u64 func_info; /* func info */357 __aligned_u64 func_info; /* func info */
358 __u32 func_info_cnt; /* number of bpf_func_info records */358 __u32 func_info_cnt; /* number of bpf_func_info records */
359 __u32 line_info_rec_size; /* userspace bpf_line_info size */
360 __aligned_u64 line_info; /* line info */
361 __u32 line_info_cnt; /* number of bpf_line_info records */
359 };362 };
360 363
361 struct { /* anonymous struct used by BPF_OBJ_* commands */364 struct { /* anonymous struct used by BPF_OBJ_* commands */
@@ -2679,6 +2682,12 @@ struct bpf_prog_info { · 2317 unmodified lines
2679 __u32 func_info_rec_size;2682 __u32 func_info_rec_size;
2680 __aligned_u64 func_info;2683 __aligned_u64 func_info;
2681 __u32 func_info_cnt;2684 __u32 func_info_cnt;
2685 __u32 line_info_cnt;
2686 __aligned_u64 line_info;
2687 __aligned_u64 jited_line_info;
2688 __u32 jited_line_info_cnt;
2689 __u32 line_info_rec_size;
2690 __u32 jited_line_info_rec_size;
2682} __attribute__((aligned(8)));2691} __attribute__((aligned(8)));
2683 2692
2684struct bpf_map_info {2693struct bpf_map_info {
@@ -2995,4 +3004,14 @@ struct bpf_func_info { · 310 unmodified lines
2995 __u32 type_id;3004 __u32 type_id;
2996};3005};
2997 3006
3007#define BPF_LINE_INFO_LINE_NUM(line_col) ((line_col) >> 10)
3008#define BPF_LINE_INFO_LINE_COL(line_col) ((line_col) & 0x3ff)
3009
3010struct bpf_line_info {
3011 __u32 insn_off;
3012 __u32 file_name_off;
3013 __u32 line_off;
3014 __u32 line_col;
3015};
3016
2998#endif /* _UAPI__LINUX_BPF_H__ */3017#endif /* _UAPI__LINUX_BPF_H__ */
kernel/bpf/btf.c+1−1
@@ -444,7 +444,7 @@ static const struct btf_kind_operations *btf_type_ops(const struct btf_type *t) · 443 unmodified lines
444 return kind_ops[BTF_INFO_KIND(t->info)];444 return kind_ops[BTF_INFO_KIND(t->info)];
445}445}
446 446
447static bool btf_name_offset_valid(const struct btf *btf, u32 offset)447bool btf_name_offset_valid(const struct btf *btf, u32 offset)
448{448{
449 return BTF_STR_OFFSET_VALID(offset) &&449 return BTF_STR_OFFSET_VALID(offset) &&
450 offset < btf->hdr.str_len;450 offset < btf->hdr.str_len;
kernel/bpf/core.c+116−2
@@ -105,6 +105,91 @@ struct bpf_prog *bpf_prog_alloc(unsigned int size, gfp_t gfp_extra_flags) · 104 unmodified lines
105}105}
106EXPORT_SYMBOL_GPL(bpf_prog_alloc);106EXPORT_SYMBOL_GPL(bpf_prog_alloc);
107 107
108int bpf_prog_alloc_jited_linfo(struct bpf_prog *prog)
109{
110 if (!prog->aux->nr_linfo || !prog->jit_requested)
111 return 0;
112
113 prog->aux->jited_linfo = kcalloc(prog->aux->nr_linfo,
114 sizeof(*prog->aux->jited_linfo),
115 GFP_KERNEL | __GFP_NOWARN);
116 if (!prog->aux->jited_linfo)
117 return -ENOMEM;
118
119 return 0;
120}
121
122void bpf_prog_free_jited_linfo(struct bpf_prog *prog)
123{
124 kfree(prog->aux->jited_linfo);
125 prog->aux->jited_linfo = NULL;
126}
127
128void bpf_prog_free_unused_jited_linfo(struct bpf_prog *prog)
129{
130 if (prog->aux->jited_linfo && !prog->aux->jited_linfo[0])
131 bpf_prog_free_jited_linfo(prog);
132}
133
134/* The jit engine is responsible to provide an array
135 * for insn_off to the jited_off mapping (insn_to_jit_off).
136 *
137 * The idx to this array is the insn_off. Hence, the insn_off
138 * here is relative to the prog itself instead of the main prog.
139 * This array has one entry for each xlated bpf insn.
140 *
141 * jited_off is the byte off to the last byte of the jited insn.
142 *
143 * Hence, with
144 * insn_start:
145 * The first bpf insn off of the prog. The insn off
146 * here is relative to the main prog.
147 * e.g. if prog is a subprog, insn_start > 0
148 * linfo_idx:
149 * The prog's idx to prog->aux->linfo and jited_linfo
150 *
151 * jited_linfo[linfo_idx] = prog->bpf_func
152 *
153 * For i > linfo_idx,
154 *
155 * jited_linfo[i] = prog->bpf_func +
156 * insn_to_jit_off[linfo[i].insn_off - insn_start - 1]
157 */
158void bpf_prog_fill_jited_linfo(struct bpf_prog *prog,
159 const u32 *insn_to_jit_off)
160{
161 u32 linfo_idx, insn_start, insn_end, nr_linfo, i;
162 const struct bpf_line_info *linfo;
163 void **jited_linfo;
164
165 if (!prog->aux->jited_linfo)
166 /* Userspace did not provide linfo */
167 return;
168
169 linfo_idx = prog->aux->linfo_idx;
170 linfo = &prog->aux->linfo[linfo_idx];
171 insn_start = linfo[0].insn_off;
172 insn_end = insn_start + prog->len;
173
174 jited_linfo = &prog->aux->jited_linfo[linfo_idx];
175 jited_linfo[0] = prog->bpf_func;
176
177 nr_linfo = prog->aux->nr_linfo - linfo_idx;
178
179 for (i = 1; i < nr_linfo && linfo[i].insn_off < insn_end; i++)
180 /* The verifier ensures that linfo[i].insn_off is
181 * strictly increasing
182 */
183 jited_linfo[i] = prog->bpf_func +
184 insn_to_jit_off[linfo[i].insn_off - insn_start - 1];
185}
186
187void bpf_prog_free_linfo(struct bpf_prog *prog)
188{
189 bpf_prog_free_jited_linfo(prog);
190 kvfree(prog->aux->linfo);
191}
192
108struct bpf_prog *bpf_prog_realloc(struct bpf_prog *fp_old, unsigned int size,193struct bpf_prog *bpf_prog_realloc(struct bpf_prog *fp_old, unsigned int size,
109 gfp_t gfp_extra_flags)194 gfp_t gfp_extra_flags)
110{195{
@@ -294,6 +379,26 @@ static int bpf_adj_branches(struct bpf_prog *prog, u32 pos, u32 delta, · 183 unmodified lines
294 return ret;379 return ret;
295}380}
296 381
382static void bpf_adj_linfo(struct bpf_prog *prog, u32 off, u32 delta)
383{
384 struct bpf_line_info *linfo;
385 u32 i, nr_linfo;
386
387 nr_linfo = prog->aux->nr_linfo;
388 if (!nr_linfo || !delta)
389 return;
390
391 linfo = prog->aux->linfo;
392
393 for (i = 0; i < nr_linfo; i++)
394 if (off < linfo[i].insn_off)
395 break;
396
397 /* Push all off < linfo[i].insn_off by delta */
398 for (; i < nr_linfo; i++)
399 linfo[i].insn_off += delta;
400}
401
297struct bpf_prog *bpf_patch_insn_single(struct bpf_prog *prog, u32 off,402struct bpf_prog *bpf_patch_insn_single(struct bpf_prog *prog, u32 off,
298 const struct bpf_insn *patch, u32 len)403 const struct bpf_insn *patch, u32 len)
299{404{
@@ -349,6 +454,8 @@ struct bpf_prog *bpf_patch_insn_single(struct bpf_prog *prog, u32 off, · 49 unmodified lines
349 */454 */
350 BUG_ON(bpf_adj_branches(prog_adj, off, insn_delta, false));455 BUG_ON(bpf_adj_branches(prog_adj, off, insn_delta, false));
351 456
457 bpf_adj_linfo(prog_adj, off, insn_delta);
458
352 return prog_adj;459 return prog_adj;
353}460}
354 461
@@ -1591,13 +1698,20 @@ struct bpf_prog *bpf_prog_select_runtime(struct bpf_prog *fp, int *err) · 1236 unmodified lines
1591 * be JITed, but falls back to the interpreter.1698 * be JITed, but falls back to the interpreter.
1592 */1699 */
1593 if (!bpf_prog_is_dev_bound(fp->aux)) {1700 if (!bpf_prog_is_dev_bound(fp->aux)) {
1701 *err = bpf_prog_alloc_jited_linfo(fp);
1702 if (*err)
1703 return fp;
1704
1594 fp = bpf_int_jit_compile(fp);1705 fp = bpf_int_jit_compile(fp);
1595#ifdef CONFIG_BPF_JIT_ALWAYS_ON
1596 if (!fp->jited) {1706 if (!fp->jited) {
1707 bpf_prog_free_jited_linfo(fp);
1708#ifdef CONFIG_BPF_JIT_ALWAYS_ON
1597 *err = -ENOTSUPP;1709 *err = -ENOTSUPP;
1598 return fp;1710 return fp;
1599 }
1600#endif1711#endif
1712 } else {
1713 bpf_prog_free_unused_jited_linfo(fp);
1714 }
1601 } else {1715 } else {
1602 *err = bpf_prog_offload_compile(fp);1716 *err = bpf_prog_offload_compile(fp);
1603 if (*err)1717 if (*err)
kernel/bpf/syscall.c+77−6
@@ -1215,6 +1215,7 @@ static void __bpf_prog_put(struct bpf_prog *prog, bool do_idr_lock) · 1214 unmodified lines
1215 bpf_prog_kallsyms_del_all(prog);1215 bpf_prog_kallsyms_del_all(prog);
1216 btf_put(prog->aux->btf);1216 btf_put(prog->aux->btf);
1217 kvfree(prog->aux->func_info);1217 kvfree(prog->aux->func_info);
1218 bpf_prog_free_linfo(prog);
1218 1219
1219 call_rcu(&prog->aux->rcu, __bpf_prog_put_rcu);1220 call_rcu(&prog->aux->rcu, __bpf_prog_put_rcu);
1220 }1221 }
@@ -1439,7 +1440,7 @@ bpf_prog_load_check_attach_type(enum bpf_prog_type prog_type, · 218 unmodified lines
1439}1440}
1440 1441
1441/* last field in 'union bpf_attr' used by this command */1442/* last field in 'union bpf_attr' used by this command */
1442#define BPF_PROG_LOAD_LAST_FIELD func_info_cnt1443#define BPF_PROG_LOAD_LAST_FIELD line_info_cnt
1443 1444
1444static int bpf_prog_load(union bpf_attr *attr, union bpf_attr __user *uattr)1445static int bpf_prog_load(union bpf_attr *attr, union bpf_attr __user *uattr)
1445{1446{
@@ -1560,6 +1561,7 @@ static int bpf_prog_load(union bpf_attr *attr, union bpf_attr __user *uattr) · 114 unmodified lines
1560 return err;1561 return err;
1561 1562
1562free_used_maps:1563free_used_maps:
1564 bpf_prog_free_linfo(prog);
1563 kvfree(prog->aux->func_info);1565 kvfree(prog->aux->func_info);
1564 btf_put(prog->aux->btf);1566 btf_put(prog->aux->btf);
1565 bpf_prog_kallsyms_del_subprogs(prog);1567 bpf_prog_kallsyms_del_subprogs(prog);
@@ -2041,6 +2043,37 @@ static struct bpf_insn *bpf_insn_prepare_dump(const struct bpf_prog *prog) · 475 unmodified lines
2041 return insns;2043 return insns;
2042}2044}
2043 2045
2046static int set_info_rec_size(struct bpf_prog_info *info)
2047{
2048 /*
2049 * Ensure info.*_rec_size is the same as kernel expected size
2050 *
2051 * or
2052 *
2053 * Only allow zero *_rec_size if both _rec_size and _cnt are
2054 * zero. In this case, the kernel will set the expected
2055 * _rec_size back to the info.
2056 */
2057
2058 if ((info->func_info_cnt || info->func_info_rec_size) &&
2059 info->func_info_rec_size != sizeof(struct bpf_func_info))
2060 return -EINVAL;
2061
2062 if ((info->line_info_cnt || info->line_info_rec_size) &&
2063 info->line_info_rec_size != sizeof(struct bpf_line_info))
2064 return -EINVAL;
2065
2066 if ((info->jited_line_info_cnt || info->jited_line_info_rec_size) &&
2067 info->jited_line_info_rec_size != sizeof(__u64))
2068 return -EINVAL;
2069
2070 info->func_info_rec_size = sizeof(struct bpf_func_info);
2071 info->line_info_rec_size = sizeof(struct bpf_line_info);
2072 info->jited_line_info_rec_size = sizeof(__u64);
2073
2074 return 0;
2075}
2076
2044static int bpf_prog_get_info_by_fd(struct bpf_prog *prog,2077static int bpf_prog_get_info_by_fd(struct bpf_prog *prog,
2045 const union bpf_attr *attr,2078 const union bpf_attr *attr,
2046 union bpf_attr __user *uattr)2079 union bpf_attr __user *uattr)
@@ -2083,11 +2116,9 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog, · 36 unmodified lines
2083 return -EFAULT;2116 return -EFAULT;
2084 }2117 }
2085 2118
2086 if ((info.func_info_cnt || info.func_info_rec_size) &&2119 err = set_info_rec_size(&info);
2087 info.func_info_rec_size != sizeof(struct bpf_func_info))2120 if (err)
2088 return -EINVAL;2121 return err;
2089
2090 info.func_info_rec_size = sizeof(struct bpf_func_info);
2091 2122
2092 if (!capable(CAP_SYS_ADMIN)) {2123 if (!capable(CAP_SYS_ADMIN)) {
2093 info.jited_prog_len = 0;2124 info.jited_prog_len = 0;
@@ -2095,6 +2126,8 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog, · 1 unmodified line
2095 info.nr_jited_ksyms = 0;2126 info.nr_jited_ksyms = 0;
2096 info.nr_jited_func_lens = 0;2127 info.nr_jited_func_lens = 0;
2097 info.func_info_cnt = 0;2128 info.func_info_cnt = 0;
2129 info.line_info_cnt = 0;
2130 info.jited_line_info_cnt = 0;
2098 goto done;2131 goto done;
2099 }2132 }
2100 2133
@@ -2251,6 +2284,44 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog, · 150 unmodified lines
2251 }2284 }
2252 }2285 }
2253 2286
2287 ulen = info.line_info_cnt;
2288 info.line_info_cnt = prog->aux->nr_linfo;
2289 if (info.line_info_cnt && ulen) {
2290 if (bpf_dump_raw_ok()) {
2291 __u8 __user *user_linfo;
2292
2293 user_linfo = u64_to_user_ptr(info.line_info);
2294 ulen = min_t(u32, info.line_info_cnt, ulen);
2295 if (copy_to_user(user_linfo, prog->aux->linfo,
2296 info.line_info_rec_size * ulen))
2297 return -EFAULT;
2298 } else {
2299 info.line_info = 0;
2300 }
2301 }
2302
2303 ulen = info.jited_line_info_cnt;
2304 if (prog->aux->jited_linfo)
2305 info.jited_line_info_cnt = prog->aux->nr_linfo;
2306 else
2307 info.jited_line_info_cnt = 0;
2308 if (info.jited_line_info_cnt && ulen) {
2309 if (bpf_dump_raw_ok()) {
2310 __u64 __user *user_linfo;
2311 u32 i;
2312
2313 user_linfo = u64_to_user_ptr(info.jited_line_info);
2314 ulen = min_t(u32, info.jited_line_info_cnt, ulen);
2315 for (i = 0; i < ulen; i++) {
2316 if (put_user((__u64)(long)prog->aux->jited_linfo[i],
2317 &user_linfo[i]))
2318 return -EFAULT;
2319 }
2320 } else {
2321 info.jited_line_info = 0;
2322 }
2323 }
2324
2254done:2325done:
2255 if (copy_to_user(uinfo, &info, info_len) ||2326 if (copy_to_user(uinfo, &info, info_len) ||
2256 put_user(info_len, &uattr->info.info_len))2327 put_user(info_len, &uattr->info.info_len))
kernel/bpf/verifier.c+174−24
@@ -4640,15 +4640,17 @@ err_free: · 4639 unmodified lines
4640#define MIN_BPF_FUNCINFO_SIZE 84640#define MIN_BPF_FUNCINFO_SIZE 8
4641#define MAX_FUNCINFO_REC_SIZE 2524641#define MAX_FUNCINFO_REC_SIZE 252
4642 4642
4643static int check_btf_func(struct bpf_prog *prog, struct bpf_verifier_env *env,4643static int check_btf_func(struct bpf_verifier_env *env,
4644 union bpf_attr *attr, union bpf_attr __user *uattr)4644 const union bpf_attr *attr,
4645 union bpf_attr __user *uattr)
4645{4646{
4646 u32 i, nfuncs, urec_size, min_size, prev_offset;4647 u32 i, nfuncs, urec_size, min_size, prev_offset;
4647 u32 krec_size = sizeof(struct bpf_func_info);4648 u32 krec_size = sizeof(struct bpf_func_info);
4648 struct bpf_func_info *krecord = NULL;4649 struct bpf_func_info *krecord;
4649 const struct btf_type *type;4650 const struct btf_type *type;
4651 struct bpf_prog *prog;
4652 const struct btf *btf;
4650 void __user *urecord;4653 void __user *urecord;
4651 struct btf *btf;
4652 int ret = 0;4654 int ret = 0;
4653 4655
4654 nfuncs = attr->func_info_cnt;4656 nfuncs = attr->func_info_cnt;
@@ -4668,20 +4670,15 @@ static int check_btf_func(struct bpf_prog *prog, struct bpf_verifier_env *env, · 13 unmodified lines
4668 return -EINVAL;4670 return -EINVAL;
4669 }4671 }
4670 4672
4671 btf = btf_get_by_fd(attr->prog_btf_fd);4673 prog = env->prog;
4672 if (IS_ERR(btf)) {4674 btf = prog->aux->btf;
4673 verbose(env, "unable to get btf from fd\n");
4674 return PTR_ERR(btf);
4675 }
4676 4675
4677 urecord = u64_to_user_ptr(attr->func_info);4676 urecord = u64_to_user_ptr(attr->func_info);
4678 min_size = min_t(u32, krec_size, urec_size);4677 min_size = min_t(u32, krec_size, urec_size);
4679 4678
4680 krecord = kvcalloc(nfuncs, krec_size, GFP_KERNEL | __GFP_NOWARN);4679 krecord = kvcalloc(nfuncs, krec_size, GFP_KERNEL | __GFP_NOWARN);
4681 if (!krecord) {4680 if (!krecord)
4682 ret = -ENOMEM;4681 return -ENOMEM;
4683 goto free_btf;
4684 }
4685 4682
4686 for (i = 0; i < nfuncs; i++) {4683 for (i = 0; i < nfuncs; i++) {
4687 ret = bpf_check_uarg_tail_zero(urecord, krec_size, urec_size);4684 ret = bpf_check_uarg_tail_zero(urecord, krec_size, urec_size);
@@ -4694,12 +4691,12 @@ static int check_btf_func(struct bpf_prog *prog, struct bpf_verifier_env *env, · 6 unmodified lines
4694 if (put_user(min_size, &uattr->func_info_rec_size))4691 if (put_user(min_size, &uattr->func_info_rec_size))
4695 ret = -EFAULT;4692 ret = -EFAULT;
4696 }4693 }
4697 goto free_btf;4694 goto err_free;
4698 }4695 }
4699 4696
4700 if (copy_from_user(&krecord[i], urecord, min_size)) {4697 if (copy_from_user(&krecord[i], urecord, min_size)) {
4701 ret = -EFAULT;4698 ret = -EFAULT;
4702 goto free_btf;4699 goto err_free;
4703 }4700 }
4704 4701
4705 /* check insn_off */4702 /* check insn_off */
@@ -4709,20 +4706,20 @@ static int check_btf_func(struct bpf_prog *prog, struct bpf_verifier_env *env, · 3 unmodified lines
4709 "nonzero insn_off %u for the first func info record",4706 "nonzero insn_off %u for the first func info record",
4710 krecord[i].insn_off);4707 krecord[i].insn_off);
4711 ret = -EINVAL;4708 ret = -EINVAL;
4712 goto free_btf;4709 goto err_free;
4713 }4710 }
4714 } else if (krecord[i].insn_off <= prev_offset) {4711 } else if (krecord[i].insn_off <= prev_offset) {
4715 verbose(env,4712 verbose(env,
4716 "same or smaller insn offset (%u) than previous func info record (%u)",4713 "same or smaller insn offset (%u) than previous func info record (%u)",
4717 krecord[i].insn_off, prev_offset);4714 krecord[i].insn_off, prev_offset);
4718 ret = -EINVAL;4715 ret = -EINVAL;
4719 goto free_btf;4716 goto err_free;
4720 }4717 }
4721 4718
4722 if (env->subprog_info[i].start != krecord[i].insn_off) {4719 if (env->subprog_info[i].start != krecord[i].insn_off) {
4723 verbose(env, "func_info BTF section doesn't match subprog layout in BPF program\n");4720 verbose(env, "func_info BTF section doesn't match subprog layout in BPF program\n");
4724 ret = -EINVAL;4721 ret = -EINVAL;
4725 goto free_btf;4722 goto err_free;
4726 }4723 }
4727 4724
4728 /* check type_id */4725 /* check type_id */
@@ -4731,20 +4728,18 @@ static int check_btf_func(struct bpf_prog *prog, struct bpf_verifier_env *env, · 2 unmodified lines
4731 verbose(env, "invalid type id %d in func info",4728 verbose(env, "invalid type id %d in func info",
4732 krecord[i].type_id);4729 krecord[i].type_id);
4733 ret = -EINVAL;4730 ret = -EINVAL;
4734 goto free_btf;4731 goto err_free;
4735 }4732 }
4736 4733
4737 prev_offset = krecord[i].insn_off;4734 prev_offset = krecord[i].insn_off;
4738 urecord += urec_size;4735 urecord += urec_size;
4739 }4736 }
4740 4737
4741 prog->aux->btf = btf;
4742 prog->aux->func_info = krecord;4738 prog->aux->func_info = krecord;
4743 prog->aux->func_info_cnt = nfuncs;4739 prog->aux->func_info_cnt = nfuncs;
4744 return 0;4740 return 0;
4745 4741
4746free_btf:4742err_free:
4747 btf_put(btf);
4748 kvfree(krecord);4743 kvfree(krecord);
4749 return ret;4744 return ret;
4750}4745}
@@ -4760,6 +4755,150 @@ static void adjust_btf_func(struct bpf_verifier_env *env) · 9 unmodified lines
4760 env->prog->aux->func_info[i].insn_off = env->subprog_info[i].start;4755 env->prog->aux->func_info[i].insn_off = env->subprog_info[i].start;
4761}4756}
4762 4757
4758#define MIN_BPF_LINEINFO_SIZE (offsetof(struct bpf_line_info, line_col) + \
4759 sizeof(((struct bpf_line_info *)(0))->line_col))
4760#define MAX_LINEINFO_REC_SIZE MAX_FUNCINFO_REC_SIZE
4761
4762static int check_btf_line(struct bpf_verifier_env *env,
4763 const union bpf_attr *attr,
4764 union bpf_attr __user *uattr)
4765{
4766 u32 i, s, nr_linfo, ncopy, expected_size, rec_size, prev_offset = 0;
4767 struct bpf_subprog_info *sub;
4768 struct bpf_line_info *linfo;
4769 struct bpf_prog *prog;
4770 const struct btf *btf;
4771 void __user *ulinfo;
4772 int err;
4773
4774 nr_linfo = attr->line_info_cnt;
4775 if (!nr_linfo)
4776 return 0;
4777
4778 rec_size = attr->line_info_rec_size;
4779 if (rec_size < MIN_BPF_LINEINFO_SIZE ||
4780 rec_size > MAX_LINEINFO_REC_SIZE ||
4781 rec_size & (sizeof(u32) - 1))
4782 return -EINVAL;
4783
4784 /* Need to zero it in case the userspace may
4785 * pass in a smaller bpf_line_info object.
4786 */
4787 linfo = kvcalloc(nr_linfo, sizeof(struct bpf_line_info),
4788 GFP_KERNEL | __GFP_NOWARN);
4789 if (!linfo)
4790 return -ENOMEM;
4791
4792 prog = env->prog;
4793 btf = prog->aux->btf;
4794
4795 s = 0;
4796 sub = env->subprog_info;
4797 ulinfo = u64_to_user_ptr(attr->line_info);
4798 expected_size = sizeof(struct bpf_line_info);
4799 ncopy = min_t(u32, expected_size, rec_size);
4800 for (i = 0; i < nr_linfo; i++) {
4801 err = bpf_check_uarg_tail_zero(ulinfo, expected_size, rec_size);
4802 if (err) {
4803 if (err == -E2BIG) {
4804 verbose(env, "nonzero tailing record in line_info");
4805 if (put_user(expected_size,
4806 &uattr->line_info_rec_size))
4807 err = -EFAULT;
4808 }
4809 goto err_free;
4810 }
4811
4812 if (copy_from_user(&linfo[i], ulinfo, ncopy)) {
4813 err = -EFAULT;
4814 goto err_free;
4815 }
4816
4817 /*
4818 * Check insn_off to ensure
4819 * 1) strictly increasing AND
4820 * 2) bounded by prog->len
4821 *
4822 * The linfo[0].insn_off == 0 check logically falls into
4823 * the later "missing bpf_line_info for func..." case
4824 * because the first linfo[0].insn_off must be the
4825 * first sub also and the first sub must have
4826 * subprog_info[0].start == 0.
4827 */
4828 if ((i && linfo[i].insn_off <= prev_offset) ||
4829 linfo[i].insn_off >= prog->len) {
4830 verbose(env, "Invalid line_info[%u].insn_off:%u (prev_offset:%u prog->len:%u)\n",
4831 i, linfo[i].insn_off, prev_offset,
4832 prog->len);
4833 err = -EINVAL;
4834 goto err_free;
4835 }
4836
4837 if (!btf_name_offset_valid(btf, linfo[i].line_off) ||
4838 !btf_name_offset_valid(btf, linfo[i].file_name_off)) {
4839 verbose(env, "Invalid line_info[%u].line_off or .file_name_off\n", i);
4840 err = -EINVAL;
4841 goto err_free;
4842 }
4843
4844 if (s != env->subprog_cnt) {
4845 if (linfo[i].insn_off == sub[s].start) {
4846 sub[s].linfo_idx = i;
4847 s++;
4848 } else if (sub[s].start < linfo[i].insn_off) {
4849 verbose(env, "missing bpf_line_info for func#%u\n", s);
4850 err = -EINVAL;
4851 goto err_free;
4852 }
4853 }
4854
4855 prev_offset = linfo[i].insn_off;
4856 ulinfo += rec_size;
4857 }
4858
4859 if (s != env->subprog_cnt) {
4860 verbose(env, "missing bpf_line_info for %u funcs starting from func#%u\n",
4861 env->subprog_cnt - s, s);
4862 err = -EINVAL;
4863 goto err_free;
4864 }
4865
4866 prog->aux->linfo = linfo;
4867 prog->aux->nr_linfo = nr_linfo;
4868
4869 return 0;
4870
4871err_free:
4872 kvfree(linfo);
4873 return err;
4874}
4875
4876static int check_btf_info(struct bpf_verifier_env *env,
4877 const union bpf_attr *attr,
4878 union bpf_attr __user *uattr)
4879{
4880 struct btf *btf;
4881 int err;
4882
4883 if (!attr->func_info_cnt && !attr->line_info_cnt)
4884 return 0;
4885
4886 btf = btf_get_by_fd(attr->prog_btf_fd);
4887 if (IS_ERR(btf))
4888 return PTR_ERR(btf);
4889 env->prog->aux->btf = btf;
4890
4891 err = check_btf_func(env, attr, uattr);
4892 if (err)
4893 return err;
4894
4895 err = check_btf_line(env, attr, uattr);
4896 if (err)
4897 return err;
4898
4899 return 0;
4900}
4901
4763/* check %cur's range satisfies %old's */4902/* check %cur's range satisfies %old's */
4764static bool range_within(struct bpf_reg_state *old,4903static bool range_within(struct bpf_reg_state *old,
4765 struct bpf_reg_state *cur)4904 struct bpf_reg_state *cur)
@@ -6004,7 +6143,7 @@ static int jit_subprogs(struct bpf_verifier_env *env) · 1238 unmodified lines
6004 int i, j, subprog_start, subprog_end = 0, len, subprog;6143 int i, j, subprog_start, subprog_end = 0, len, subprog;
6005 struct bpf_insn *insn;6144 struct bpf_insn *insn;
6006 void *old_bpf_func;6145 void *old_bpf_func;
6007 int err = -ENOMEM;6146 int err;
6008 6147
6009 if (env->subprog_cnt <= 1)6148 if (env->subprog_cnt <= 1)
6010 return 0;6149 return 0;
@@ -6035,6 +6174,11 @@ static int jit_subprogs(struct bpf_verifier_env *env) · 24 unmodified lines
6035 insn->imm = 1;6174 insn->imm = 1;
6036 }6175 }
6037 6176
6177 err = bpf_prog_alloc_jited_linfo(prog);
6178 if (err)
6179 goto out_undo_insn;
6180
6181 err = -ENOMEM;
6038 func = kcalloc(env->subprog_cnt, sizeof(prog), GFP_KERNEL);6182 func = kcalloc(env->subprog_cnt, sizeof(prog), GFP_KERNEL);
6039 if (!func)6183 if (!func)
6040 goto out_undo_insn;6184 goto out_undo_insn;
@@ -6065,6 +6209,10 @@ static int jit_subprogs(struct bpf_verifier_env *env) · 24 unmodified lines
6065 func[i]->aux->name[0] = 'F';6209 func[i]->aux->name[0] = 'F';
6066 func[i]->aux->stack_depth = env->subprog_info[i].stack_depth;6210 func[i]->aux->stack_depth = env->subprog_info[i].stack_depth;
6067 func[i]->jit_requested = 1;6211 func[i]->jit_requested = 1;
6212 func[i]->aux->linfo = prog->aux->linfo;
6213 func[i]->aux->nr_linfo = prog->aux->nr_linfo;
6214 func[i]->aux->jited_linfo = prog->aux->jited_linfo;
6215 func[i]->aux->linfo_idx = env->subprog_info[i].linfo_idx;
6068 func[i] = bpf_int_jit_compile(func[i]);6216 func[i] = bpf_int_jit_compile(func[i]);
6069 if (!func[i]->jited) {6217 if (!func[i]->jited) {
6070 err = -ENOTSUPP;6218 err = -ENOTSUPP;
@@ -6138,6 +6286,7 @@ static int jit_subprogs(struct bpf_verifier_env *env) · 67 unmodified lines
6138 prog->bpf_func = func[0]->bpf_func;6286 prog->bpf_func = func[0]->bpf_func;
6139 prog->aux->func = func;6287 prog->aux->func = func;
6140 prog->aux->func_cnt = env->subprog_cnt;6288 prog->aux->func_cnt = env->subprog_cnt;
6289 bpf_prog_free_unused_jited_linfo(prog);
6141 return 0;6290 return 0;
6142out_free:6291out_free:
6143 for (i = 0; i < env->subprog_cnt; i++)6292 for (i = 0; i < env->subprog_cnt; i++)
@@ -6154,6 +6303,7 @@ out_undo_insn: · 10 unmodified lines
6154 insn->off = 0;6303 insn->off = 0;
6155 insn->imm = env->insn_aux_data[i].call_imm;6304 insn->imm = env->insn_aux_data[i].call_imm;
6156 }6305 }
6306 bpf_prog_free_jited_linfo(prog);
6157 return err;6307 return err;
6158}6308}
6159 6309
@@ -6526,7 +6676,7 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, · 366 unmodified lines
6526 if (ret < 0)6676 if (ret < 0)
6527 goto skip_full_check;6677 goto skip_full_check;
6528 6678
6529 ret = check_btf_func(env->prog, env, attr, uattr);6679 ret = check_btf_info(env, attr, uattr);
6530 if (ret < 0)6680 if (ret < 0)
6531 goto skip_full_check;6681 goto skip_full_check;
6532 6682
tools/bpf/bpftool/Documentation/bpftool-prog.rst+12−4
@@ -22,8 +22,8 @@ MAP COMMANDS · 21 unmodified lines
22=============22=============
23 23
24| **bpftool** **prog { show | list }** [*PROG*]24| **bpftool** **prog { show | list }** [*PROG*]
25| **bpftool** **prog dump xlated** *PROG* [{**file** *FILE* | **opcodes** | **visual**}]25| **bpftool** **prog dump xlated** *PROG* [{**file** *FILE* | **opcodes** | **visual** | **linum**}]
26| **bpftool** **prog dump jited** *PROG* [{**file** *FILE* | **opcodes**}]26| **bpftool** **prog dump jited** *PROG* [{**file** *FILE* | **opcodes** | **linum**}]
27| **bpftool** **prog pin** *PROG* *FILE*27| **bpftool** **prog pin** *PROG* *FILE*
28| **bpftool** **prog { load | loadall }** *OBJ* *PATH* [**type** *TYPE*] [**map** {**idx** *IDX* | **name** *NAME*} *MAP*] [**dev** *NAME*]28| **bpftool** **prog { load | loadall }** *OBJ* *PATH* [**type** *TYPE*] [**map** {**idx** *IDX* | **name** *NAME*} *MAP*] [**dev** *NAME*]
29| **bpftool** **prog attach** *PROG* *ATTACH_TYPE* [*MAP*]29| **bpftool** **prog attach** *PROG* *ATTACH_TYPE* [*MAP*]
@@ -56,7 +56,7 @@ DESCRIPTION · 26 unmodified lines
56 Output will start with program ID followed by program type and56 Output will start with program ID followed by program type and
57 zero or more named attributes (depending on kernel version).57 zero or more named attributes (depending on kernel version).
58 58
59 **bpftool prog dump xlated** *PROG* [{ **file** *FILE* | **opcodes** | **visual** }]59 **bpftool prog dump xlated** *PROG* [{ **file** *FILE* | **opcodes** | **visual** | **linum** }]
60 Dump eBPF instructions of the program from the kernel. By60 Dump eBPF instructions of the program from the kernel. By
61 default, eBPF will be disassembled and printed to standard61 default, eBPF will be disassembled and printed to standard
62 output in human-readable format. In this case, **opcodes**62 output in human-readable format. In this case, **opcodes**
@@ -69,13 +69,21 @@ DESCRIPTION · 6 unmodified lines
69 built instead, and eBPF instructions will be presented with69 built instead, and eBPF instructions will be presented with
70 CFG in DOT format, on standard output.70 CFG in DOT format, on standard output.
71 71
72 **bpftool prog dump jited** *PROG* [{ **file** *FILE* | **opcodes** }]72 If the prog has line_info available, the source line will
73 be displayed by default. If **linum** is specified,
74 the filename, line number and line column will also be
75 displayed on top of the source line.
76 **bpftool prog dump jited** *PROG* [{ **file** *FILE* | **opcodes** | **linum** }]
73 Dump jited image (host machine code) of the program.77 Dump jited image (host machine code) of the program.
74 If *FILE* is specified image will be written to a file,78 If *FILE* is specified image will be written to a file,
75 otherwise it will be disassembled and printed to stdout.79 otherwise it will be disassembled and printed to stdout.
76 80
77 **opcodes** controls if raw opcodes will be printed.81 **opcodes** controls if raw opcodes will be printed.
78 82
83 If the prog has line_info available, the source line will
84 be displayed by default. If **linum** is specified,
85 the filename, line number and line column will also be
86 displayed on top of the source line.
79 **bpftool prog pin** *PROG* *FILE*87 **bpftool prog pin** *PROG* *FILE*
80 Pin program *PROG* as *FILE*.88 Pin program *PROG* as *FILE*.
81 89
tools/bpf/bpftool/bash-completion/bpftool+3−3
@@ -191,7 +191,7 @@ _bpftool() · 190 unmodified lines
191 191
192 # Deal with simplest keywords192 # Deal with simplest keywords
193 case $prev in193 case $prev in
194 help|hex|opcodes|visual)194 help|hex|opcodes|visual|linum)
195 return 0195 return 0
196 ;;196 ;;
197 tag)197 tag)
@@ -278,10 +278,10 @@ _bpftool() · 80 unmodified lines
278 *)278 *)
279 _bpftool_once_attr 'file'279 _bpftool_once_attr 'file'
280 if _bpftool_search_list 'xlated'; then280 if _bpftool_search_list 'xlated'; then
281 COMPREPLY+=( $( compgen -W 'opcodes visual' -- \281 COMPREPLY+=( $( compgen -W 'opcodes visual linum' -- \
282 "$cur" ) )282 "$cur" ) )
283 else283 else
284 COMPREPLY+=( $( compgen -W 'opcodes' -- \284 COMPREPLY+=( $( compgen -W 'opcodes linum' -- \
285 "$cur" ) )285 "$cur" ) )
286 fi286 fi
287 return 0287 return 0
tools/bpf/bpftool/btf_dumper.c+64−0
@@ -385,3 +385,67 @@ void btf_dumper_type_only(const struct btf *btf, __u32 type_id, char *func_sig, · 384 unmodified lines
385 if (err < 0)385 if (err < 0)
386 func_sig[0] = '\0';386 func_sig[0] = '\0';
387}387}
388
389static const char *ltrim(const char *s)
390{
391 while (isspace(*s))
392 s++;
393
394 return s;
395}
396
397void btf_dump_linfo_plain(const struct btf *btf,
398 const struct bpf_line_info *linfo,
399 const char *prefix, bool linum)
400{
401 const char *line = btf__name_by_offset(btf, linfo->line_off);
402
403 if (!line)
404 return;
405 line = ltrim(line);
406
407 if (!prefix)
408 prefix = "";
409
410 if (linum) {
411 const char *file = btf__name_by_offset(btf, linfo->file_name_off);
412
413 /* More forgiving on file because linum option is
414 * expected to provide more info than the already
415 * available src line.
416 */
417 if (!file)
418 file = "";
419
420 printf("%s%s [file:%s line_num:%u line_col:%u]\n",
421 prefix, line, file,
422 BPF_LINE_INFO_LINE_NUM(linfo->line_col),
423 BPF_LINE_INFO_LINE_COL(linfo->line_col));
424 } else {
425 printf("%s%s\n", prefix, line);
426 }
427}
428
429void btf_dump_linfo_json(const struct btf *btf,
430 const struct bpf_line_info *linfo, bool linum)
431{
432 const char *line = btf__name_by_offset(btf, linfo->line_off);
433
434 if (line)
435 jsonw_string_field(json_wtr, "src", ltrim(line));
436
437 if (linum) {
438 const char *file = btf__name_by_offset(btf, linfo->file_name_off);
439
440 if (file)
441 jsonw_string_field(json_wtr, "file", file);
442
443 if (BPF_LINE_INFO_LINE_NUM(linfo->line_col))
444 jsonw_int_field(json_wtr, "line_num",
445 BPF_LINE_INFO_LINE_NUM(linfo->line_col));
446
447 if (BPF_LINE_INFO_LINE_COL(linfo->line_col))
448 jsonw_int_field(json_wtr, "line_col",
449 BPF_LINE_INFO_LINE_COL(linfo->line_col));
450 }
451}
tools/bpf/bpftool/jit_disasm.c+22−1
@@ -21,6 +21,7 @@ · 20 unmodified lines
21#include <dis-asm.h>21#include <dis-asm.h>
22#include <sys/stat.h>22#include <sys/stat.h>
23#include <limits.h>23#include <limits.h>
24#include <libbpf.h>
24 25
25#include "json_writer.h"26#include "json_writer.h"
26#include "main.h"27#include "main.h"
@@ -68,10 +69,16 @@ static int fprintf_json(void *out, const char *fmt, ...) · 41 unmodified lines
68}69}
69 70
70void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes,71void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes,
71 const char *arch, const char *disassembler_options)72 const char *arch, const char *disassembler_options,
73 const struct btf *btf,
74 const struct bpf_prog_linfo *prog_linfo,
75 __u64 func_ksym, unsigned int func_idx,
76 bool linum)
72{77{
78 const struct bpf_line_info *linfo = NULL;
73 disassembler_ftype disassemble;79 disassembler_ftype disassemble;
74 struct disassemble_info info;80 struct disassemble_info info;
81 unsigned int nr_skip = 0;
75 int count, i, pc = 0;82 int count, i, pc = 0;
76 char tpath[PATH_MAX];83 char tpath[PATH_MAX];
77 bfd *bfdf;84 bfd *bfdf;
@@ -127,12 +134,26 @@ void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes, · 49 unmodified lines
127 if (json_output)134 if (json_output)
128 jsonw_start_array(json_wtr);135 jsonw_start_array(json_wtr);
129 do {136 do {
137 if (prog_linfo) {
138 linfo = bpf_prog_linfo__lfind_addr_func(prog_linfo,
139 func_ksym + pc,
140 func_idx,
141 nr_skip);
142 if (linfo)
143 nr_skip++;
144 }
145
130 if (json_output) {146 if (json_output) {
131 jsonw_start_object(json_wtr);147 jsonw_start_object(json_wtr);
132 oper_count = 0;148 oper_count = 0;
149 if (linfo)
150 btf_dump_linfo_json(btf, linfo, linum);
133 jsonw_name(json_wtr, "pc");151 jsonw_name(json_wtr, "pc");
134 jsonw_printf(json_wtr, "\"0x%x\"", pc);152 jsonw_printf(json_wtr, "\"0x%x\"", pc);
135 } else {153 } else {
154 if (linfo)
155 btf_dump_linfo_plain(btf, linfo, "; ",
156 linum);
136 printf("%4x:\t", pc);157 printf("%4x:\t", pc);
137 }158 }
138 159
tools/bpf/bpftool/main.h+21−2
@@ -138,6 +138,9 @@ struct pinned_obj { · 137 unmodified lines
138 struct hlist_node hash;138 struct hlist_node hash;
139};139};
140 140
141struct btf;
142struct bpf_line_info;
143
141int build_pinned_obj_table(struct pinned_obj_table *table,144int build_pinned_obj_table(struct pinned_obj_table *table,
142 enum bpf_obj_type type);145 enum bpf_obj_type type);
143void delete_pinned_obj_table(struct pinned_obj_table *tab);146void delete_pinned_obj_table(struct pinned_obj_table *tab);
@@ -175,13 +178,23 @@ int map_parse_fd(int *argc, char ***argv); · 31 unmodified lines
175int map_parse_fd_and_info(int *argc, char ***argv, void *info, __u32 *info_len);178int map_parse_fd_and_info(int *argc, char ***argv, void *info, __u32 *info_len);
176 179
177#ifdef HAVE_LIBBFD_SUPPORT180#ifdef HAVE_LIBBFD_SUPPORT
181struct bpf_prog_linfo;
178void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes,182void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes,
179 const char *arch, const char *disassembler_options);183 const char *arch, const char *disassembler_options,
184 const struct btf *btf,
185 const struct bpf_prog_linfo *prog_linfo,
186 __u64 func_ksym, unsigned int func_idx,
187 bool linum);
180int disasm_init(void);188int disasm_init(void);
181#else189#else
182static inline190static inline
183void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes,191void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes,
184 const char *arch, const char *disassembler_options)192 const char *arch, const char *disassembler_options,
193 const struct btf *btf,
194 const struct bpf_prog_linfo *prog_linfo,
195 __u64 func_ksym, unsigned int func_idx,
196 bool linum)
197
185{198{
186}199}
187static inline int disasm_init(void)200static inline int disasm_init(void)
@@ -217,6 +230,12 @@ int btf_dumper_type(const struct btf_dumper *d, __u32 type_id, · 29 unmodified lines
217void btf_dumper_type_only(const struct btf *btf, __u32 func_type_id,230void btf_dumper_type_only(const struct btf *btf, __u32 func_type_id,
218 char *func_only, int size);231 char *func_only, int size);
219 232
233void btf_dump_linfo_plain(const struct btf *btf,
234 const struct bpf_line_info *linfo,
235 const char *prefix, bool linum);
236void btf_dump_linfo_json(const struct btf *btf,
237 const struct bpf_line_info *linfo, bool linum);
238
220struct nlattr;239struct nlattr;
221struct ifinfomsg;240struct ifinfomsg;
222struct tcmsg;241struct tcmsg;
tools/bpf/bpftool/prog.c+90−10
@@ -423,24 +423,26 @@ static int do_show(int argc, char **argv) · 422 unmodified lines
423 423
424static int do_dump(int argc, char **argv)424static int do_dump(int argc, char **argv)
425{425{
426 unsigned int finfo_rec_size, linfo_rec_size, jited_linfo_rec_size;
427 void *func_info = NULL, *linfo = NULL, *jited_linfo = NULL;
428 unsigned int finfo_cnt, linfo_cnt = 0, jited_linfo_cnt = 0;
429 struct bpf_prog_linfo *prog_linfo = NULL;
426 unsigned long *func_ksyms = NULL;430 unsigned long *func_ksyms = NULL;
427 struct bpf_prog_info info = {};431 struct bpf_prog_info info = {};
428 unsigned int *func_lens = NULL;432 unsigned int *func_lens = NULL;
429 const char *disasm_opt = NULL;433 const char *disasm_opt = NULL;
430 unsigned int finfo_rec_size;
431 unsigned int nr_func_ksyms;434 unsigned int nr_func_ksyms;
432 unsigned int nr_func_lens;435 unsigned int nr_func_lens;
433 struct dump_data dd = {};436 struct dump_data dd = {};
434 __u32 len = sizeof(info);437 __u32 len = sizeof(info);
435 struct btf *btf = NULL;438 struct btf *btf = NULL;
436 void *func_info = NULL;
437 unsigned int finfo_cnt;
438 unsigned int buf_size;439 unsigned int buf_size;
439 char *filepath = NULL;440 char *filepath = NULL;
440 bool opcodes = false;441 bool opcodes = false;
441 bool visual = false;442 bool visual = false;
442 char func_sig[1024];443 char func_sig[1024];
443 unsigned char *buf;444 unsigned char *buf;
445 bool linum = false;
444 __u32 *member_len;446 __u32 *member_len;
445 __u64 *member_ptr;447 __u64 *member_ptr;
446 ssize_t n;448 ssize_t n;
@@ -484,6 +486,9 @@ static int do_dump(int argc, char **argv) · 37 unmodified lines
484 } else if (is_prefix(*argv, "visual")) {486 } else if (is_prefix(*argv, "visual")) {
485 visual = true;487 visual = true;
486 NEXT_ARG();488 NEXT_ARG();
489 } else if (is_prefix(*argv, "linum")) {
490 linum = true;
491 NEXT_ARG();
487 }492 }
488 493
489 if (argc) {494 if (argc) {
@@ -543,6 +548,32 @@ static int do_dump(int argc, char **argv) · 53 unmodified lines
543 }548 }
544 }549 }
545 550
551 linfo_rec_size = info.line_info_rec_size;
552 if (info.line_info_cnt && linfo_rec_size && info.btf_id) {
553 linfo_cnt = info.line_info_cnt;
554 linfo = malloc(linfo_cnt * linfo_rec_size);
555 if (!linfo) {
556 p_err("mem alloc failed");
557 close(fd);
558 goto err_free;
559 }
560 }
561
562 jited_linfo_rec_size = info.jited_line_info_rec_size;
563 if (info.jited_line_info_cnt &&
564 jited_linfo_rec_size &&
565 info.nr_jited_ksyms &&
566 info.nr_jited_func_lens &&
567 info.btf_id) {
568 jited_linfo_cnt = info.jited_line_info_cnt;
569 jited_linfo = malloc(jited_linfo_cnt * jited_linfo_rec_size);
570 if (!jited_linfo) {
571 p_err("mem alloc failed");
572 close(fd);
573 goto err_free;
574 }
575 }
576
546 memset(&info, 0, sizeof(info));577 memset(&info, 0, sizeof(info));
547 578
548 *member_ptr = ptr_to_u64(buf);579 *member_ptr = ptr_to_u64(buf);
@@ -554,6 +585,13 @@ static int do_dump(int argc, char **argv) · 5 unmodified lines
554 info.func_info_cnt = finfo_cnt;585 info.func_info_cnt = finfo_cnt;
555 info.func_info_rec_size = finfo_rec_size;586 info.func_info_rec_size = finfo_rec_size;
556 info.func_info = ptr_to_u64(func_info);587 info.func_info = ptr_to_u64(func_info);
588 info.line_info_cnt = linfo_cnt;
589 info.line_info_rec_size = linfo_rec_size;
590 info.line_info = ptr_to_u64(linfo);
591 info.jited_line_info_cnt = jited_linfo_cnt;
592 info.jited_line_info_rec_size = jited_linfo_rec_size;
593 info.jited_line_info = ptr_to_u64(jited_linfo);
594
557 595
558 err = bpf_obj_get_info_by_fd(fd, &info, &len);596 err = bpf_obj_get_info_by_fd(fd, &info, &len);
559 close(fd);597 close(fd);
@@ -596,6 +634,30 @@ static int do_dump(int argc, char **argv) · 36 unmodified lines
596 finfo_cnt = 0;634 finfo_cnt = 0;
597 }635 }
598 636
637 if (linfo && info.line_info_cnt != linfo_cnt) {
638 p_err("incorrect line_info_cnt %u vs. expected %u",
639 info.line_info_cnt, linfo_cnt);
640 goto err_free;
641 }
642
643 if (info.line_info_rec_size != linfo_rec_size) {
644 p_err("incorrect line_info_rec_size %u vs. expected %u",
645 info.line_info_rec_size, linfo_rec_size);
646 goto err_free;
647 }
648
649 if (jited_linfo && info.jited_line_info_cnt != jited_linfo_cnt) {
650 p_err("incorrect jited_line_info_cnt %u vs. expected %u",
651 info.jited_line_info_cnt, jited_linfo_cnt);
652 goto err_free;
653 }
654
655 if (info.jited_line_info_rec_size != jited_linfo_rec_size) {
656 p_err("incorrect jited_line_info_rec_size %u vs. expected %u",
657 info.jited_line_info_rec_size, jited_linfo_rec_size);
658 goto err_free;
659 }
660
599 if ((member_len == &info.jited_prog_len &&661 if ((member_len == &info.jited_prog_len &&
600 info.jited_prog_insns == 0) ||662 info.jited_prog_insns == 0) ||
601 (member_len == &info.xlated_prog_len &&663 (member_len == &info.xlated_prog_len &&
@@ -609,6 +671,12 @@ static int do_dump(int argc, char **argv) · 7 unmodified lines
609 goto err_free;671 goto err_free;
610 }672 }
611 673
674 if (linfo_cnt) {
675 prog_linfo = bpf_prog_linfo__new(&info);
676 if (!prog_linfo)
677 p_err("error in processing bpf_line_info. continue without it.");
678 }
679
612 if (filepath) {680 if (filepath) {
613 fd = open(filepath, O_WRONLY | O_CREAT | O_TRUNC, 0600);681 fd = open(filepath, O_WRONLY | O_CREAT | O_TRUNC, 0600);
614 if (fd < 0) {682 if (fd < 0) {
@@ -690,8 +758,11 @@ static int do_dump(int argc, char **argv) · 75 unmodified lines
690 printf("%s:\n", sym_name);758 printf("%s:\n", sym_name);
691 }759 }
692 760
693 disasm_print_insn(img, lens[i], opcodes, name,761 disasm_print_insn(img, lens[i], opcodes,
694 disasm_opt);762 name, disasm_opt, btf,
763 prog_linfo, ksyms[i], i,
764 linum);
765
695 img += lens[i];766 img += lens[i];
696 767
697 if (json_output)768 if (json_output)
@@ -704,7 +775,7 @@ static int do_dump(int argc, char **argv) · 6 unmodified lines
704 jsonw_end_array(json_wtr);775 jsonw_end_array(json_wtr);
705 } else {776 } else {
706 disasm_print_insn(buf, *member_len, opcodes, name,777 disasm_print_insn(buf, *member_len, opcodes, name,
707 disasm_opt);778 disasm_opt, btf, NULL, 0, 0, false);
708 }779 }
709 } else if (visual) {780 } else if (visual) {
710 if (json_output)781 if (json_output)
@@ -718,11 +789,14 @@ static int do_dump(int argc, char **argv) · 7 unmodified lines
718 dd.btf = btf;789 dd.btf = btf;
719 dd.func_info = func_info;790 dd.func_info = func_info;
720 dd.finfo_rec_size = finfo_rec_size;791 dd.finfo_rec_size = finfo_rec_size;
792 dd.prog_linfo = prog_linfo;
721 793
722 if (json_output)794 if (json_output)
723 dump_xlated_json(&dd, buf, *member_len, opcodes);795 dump_xlated_json(&dd, buf, *member_len, opcodes,
796 linum);
724 else797 else
725 dump_xlated_plain(&dd, buf, *member_len, opcodes);798 dump_xlated_plain(&dd, buf, *member_len, opcodes,
799 linum);
726 kernel_syms_destroy(&dd);800 kernel_syms_destroy(&dd);
727 }801 }
728 802
@@ -730,6 +804,9 @@ static int do_dump(int argc, char **argv) · 1 unmodified line
730 free(func_ksyms);804 free(func_ksyms);
731 free(func_lens);805 free(func_lens);
732 free(func_info);806 free(func_info);
807 free(linfo);
808 free(jited_linfo);
809 bpf_prog_linfo__free(prog_linfo);
733 return 0;810 return 0;
734 811
735err_free:812err_free:
@@ -737,6 +814,9 @@ err_free: · 1 unmodified line
737 free(func_ksyms);814 free(func_ksyms);
738 free(func_lens);815 free(func_lens);
739 free(func_info);816 free(func_info);
817 free(linfo);
818 free(jited_linfo);
819 bpf_prog_linfo__free(prog_linfo);
740 return -1;820 return -1;
741}821}
742 822
@@ -1138,8 +1218,8 @@ static int do_help(int argc, char **argv) · 395 unmodified lines
1138 1218
1139 fprintf(stderr,1219 fprintf(stderr,
1140 "Usage: %s %s { show | list } [PROG]\n"1220 "Usage: %s %s { show | list } [PROG]\n"
1141 " %s %s dump xlated PROG [{ file FILE | opcodes | visual }]\n"1221 " %s %s dump xlated PROG [{ file FILE | opcodes | visual | linum }]\n"
1142 " %s %s dump jited PROG [{ file FILE | opcodes }]\n"1222 " %s %s dump jited PROG [{ file FILE | opcodes | linum }]\n"
1143 " %s %s pin PROG FILE\n"1223 " %s %s pin PROG FILE\n"
1144 " %s %s { load | loadall } OBJ PATH \\\n"1224 " %s %s { load | loadall } OBJ PATH \\\n"
1145 " [type TYPE] [dev NAME] \\\n"1225 " [type TYPE] [dev NAME] \\\n"
tools/bpf/bpftool/xlated_dumper.c+28−2
@@ -41,6 +41,7 @@ · 40 unmodified lines
41#include <stdlib.h>41#include <stdlib.h>
42#include <string.h>42#include <string.h>
43#include <sys/types.h>43#include <sys/types.h>
44#include <libbpf.h>
44 45
45#include "disasm.h"46#include "disasm.h"
46#include "json_writer.h"47#include "json_writer.h"
@@ -234,8 +235,9 @@ static const char *print_imm(void *private_data, · 187 unmodified lines
234}235}
235 236
236void dump_xlated_json(struct dump_data *dd, void *buf, unsigned int len,237void dump_xlated_json(struct dump_data *dd, void *buf, unsigned int len,
237 bool opcodes)238 bool opcodes, bool linum)
238{239{
240 const struct bpf_prog_linfo *prog_linfo = dd->prog_linfo;
239 const struct bpf_insn_cbs cbs = {241 const struct bpf_insn_cbs cbs = {
240 .cb_print = print_insn_json,242 .cb_print = print_insn_json,
241 .cb_call = print_call,243 .cb_call = print_call,
@@ -246,6 +248,7 @@ void dump_xlated_json(struct dump_data *dd, void *buf, unsigned int len, · 4 unmodified lines
246 struct bpf_insn *insn = buf;248 struct bpf_insn *insn = buf;
247 struct btf *btf = dd->btf;249 struct btf *btf = dd->btf;
248 bool double_insn = false;250 bool double_insn = false;
251 unsigned int nr_skip = 0;
249 char func_sig[1024];252 char func_sig[1024];
250 unsigned int i;253 unsigned int i;
251 254
@@ -273,6 +276,16 @@ void dump_xlated_json(struct dump_data *dd, void *buf, unsigned int len, · 21 unmodified lines
273 }276 }
274 }277 }
275 278
279 if (prog_linfo) {
280 const struct bpf_line_info *linfo;
281
282 linfo = bpf_prog_linfo__lfind(prog_linfo, i, nr_skip);
283 if (linfo) {
284 btf_dump_linfo_json(btf, linfo, linum);
285 nr_skip++;
286 }
287 }
288
276 jsonw_name(json_wtr, "disasm");289 jsonw_name(json_wtr, "disasm");
277 print_bpf_insn(&cbs, insn + i, true);290 print_bpf_insn(&cbs, insn + i, true);
278 291
@@ -307,8 +320,9 @@ void dump_xlated_json(struct dump_data *dd, void *buf, unsigned int len, · 28 unmodified lines
307}320}
308 321
309void dump_xlated_plain(struct dump_data *dd, void *buf, unsigned int len,322void dump_xlated_plain(struct dump_data *dd, void *buf, unsigned int len,
310 bool opcodes)323 bool opcodes, bool linum)
311{324{
325 const struct bpf_prog_linfo *prog_linfo = dd->prog_linfo;
312 const struct bpf_insn_cbs cbs = {326 const struct bpf_insn_cbs cbs = {
313 .cb_print = print_insn,327 .cb_print = print_insn,
314 .cb_call = print_call,328 .cb_call = print_call,
@@ -318,6 +332,7 @@ void dump_xlated_plain(struct dump_data *dd, void *buf, unsigned int len, · 3 unmodified lines
318 struct bpf_func_info *record;332 struct bpf_func_info *record;
319 struct bpf_insn *insn = buf;333 struct bpf_insn *insn = buf;
320 struct btf *btf = dd->btf;334 struct btf *btf = dd->btf;
335 unsigned int nr_skip = 0;
321 bool double_insn = false;336 bool double_insn = false;
322 char func_sig[1024];337 char func_sig[1024];
323 unsigned int i;338 unsigned int i;
@@ -340,6 +355,17 @@ void dump_xlated_plain(struct dump_data *dd, void *buf, unsigned int len, · 16 unmodified lines
340 }355 }
341 }356 }
342 357
358 if (prog_linfo) {
359 const struct bpf_line_info *linfo;
360
361 linfo = bpf_prog_linfo__lfind(prog_linfo, i, nr_skip);
362 if (linfo) {
363 btf_dump_linfo_plain(btf, linfo, "; ",
364 linum);
365 nr_skip++;
366 }
367 }
368
343 double_insn = insn[i].code == (BPF_LD | BPF_IMM | BPF_DW);369 double_insn = insn[i].code == (BPF_LD | BPF_IMM | BPF_DW);
344 370
345 printf("% 4d: ", i);371 printf("% 4d: ", i);
tools/bpf/bpftool/xlated_dumper.h+5−2
@@ -40,6 +40,8 @@ · 39 unmodified lines
40 40
41#define SYM_MAX_NAME 25641#define SYM_MAX_NAME 256
42 42
43struct bpf_prog_linfo;
44
43struct kernel_sym {45struct kernel_sym {
44 unsigned long address;46 unsigned long address;
45 char name[SYM_MAX_NAME];47 char name[SYM_MAX_NAME];
@@ -54,6 +56,7 @@ struct dump_data { · 8 unmodified lines
54 struct btf *btf;56 struct btf *btf;
55 void *func_info;57 void *func_info;
56 __u32 finfo_rec_size;58 __u32 finfo_rec_size;
59 const struct bpf_prog_linfo *prog_linfo;
57 char scratch_buff[SYM_MAX_NAME + 8];60 char scratch_buff[SYM_MAX_NAME + 8];
58};61};
59 62
@@ -61,9 +64,9 @@ void kernel_syms_load(struct dump_data *dd); · 1 unmodified line
61void kernel_syms_destroy(struct dump_data *dd);64void kernel_syms_destroy(struct dump_data *dd);
62struct kernel_sym *kernel_syms_search(struct dump_data *dd, unsigned long key);65struct kernel_sym *kernel_syms_search(struct dump_data *dd, unsigned long key);
63void dump_xlated_json(struct dump_data *dd, void *buf, unsigned int len,66void dump_xlated_json(struct dump_data *dd, void *buf, unsigned int len,
64 bool opcodes);67 bool opcodes, bool linum);
65void dump_xlated_plain(struct dump_data *dd, void *buf, unsigned int len,68void dump_xlated_plain(struct dump_data *dd, void *buf, unsigned int len,
66 bool opcodes);69 bool opcodes, bool linum);
67void dump_xlated_for_graph(struct dump_data *dd, void *buf, void *buf_end,70void dump_xlated_for_graph(struct dump_data *dd, void *buf, void *buf_end,
68 unsigned int start_index);71 unsigned int start_index);
69 72
tools/include/uapi/linux/bpf.h+19−0
@@ -356,6 +356,9 @@ union bpf_attr { · 355 unmodified lines
356 __u32 func_info_rec_size; /* userspace bpf_func_info size */356 __u32 func_info_rec_size; /* userspace bpf_func_info size */
357 __aligned_u64 func_info; /* func info */357 __aligned_u64 func_info; /* func info */
358 __u32 func_info_cnt; /* number of bpf_func_info records */358 __u32 func_info_cnt; /* number of bpf_func_info records */
359 __u32 line_info_rec_size; /* userspace bpf_line_info size */
360 __aligned_u64 line_info; /* line info */
361 __u32 line_info_cnt; /* number of bpf_line_info records */
359 };362 };
360 363
361 struct { /* anonymous struct used by BPF_OBJ_* commands */364 struct { /* anonymous struct used by BPF_OBJ_* commands */
@@ -2679,6 +2682,12 @@ struct bpf_prog_info { · 2317 unmodified lines
2679 __u32 func_info_rec_size;2682 __u32 func_info_rec_size;
2680 __aligned_u64 func_info;2683 __aligned_u64 func_info;
2681 __u32 func_info_cnt;2684 __u32 func_info_cnt;
2685 __u32 line_info_cnt;
2686 __aligned_u64 line_info;
2687 __aligned_u64 jited_line_info;
2688 __u32 jited_line_info_cnt;
2689 __u32 line_info_rec_size;
2690 __u32 jited_line_info_rec_size;
2682} __attribute__((aligned(8)));2691} __attribute__((aligned(8)));
2683 2692
2684struct bpf_map_info {2693struct bpf_map_info {
@@ -2995,4 +3004,14 @@ struct bpf_func_info { · 310 unmodified lines
2995 __u32 type_id;3004 __u32 type_id;
2996};3005};
2997 3006
3007#define BPF_LINE_INFO_LINE_NUM(line_col) ((line_col) >> 10)
3008#define BPF_LINE_INFO_LINE_COL(line_col) ((line_col) & 0x3ff)
3009
3010struct bpf_line_info {
3011 __u32 insn_off;
3012 __u32 file_name_off;
3013 __u32 line_off;
3014 __u32 line_col;
3015};
3016
2998#endif /* _UAPI__LINUX_BPF_H__ */3017#endif /* _UAPI__LINUX_BPF_H__ */
tools/lib/bpf/Build+1−1
@@ -1 +1 @@
1libbpf-y := libbpf.o bpf.o nlattr.o btf.o libbpf_errno.o str_error.o netlink.o1libbpf-y := libbpf.o bpf.o nlattr.o btf.o libbpf_errno.o str_error.o netlink.o bpf_prog_linfo.o
tools/lib/bpf/bpf.c+62−31
@@ -173,11 +173,36 @@ int bpf_create_map_in_map(enum bpf_map_type map_type, const char *name, · 172 unmodified lines
173 -1);173 -1);
174}174}
175 175
176static void *
177alloc_zero_tailing_info(const void *orecord, __u32 cnt,
178 __u32 actual_rec_size, __u32 expected_rec_size)
179{
180 __u64 info_len = actual_rec_size * cnt;
181 void *info, *nrecord;
182 int i;
183
184 info = malloc(info_len);
185 if (!info)
186 return NULL;
187
188 /* zero out bytes kernel does not understand */
189 nrecord = info;
190 for (i = 0; i < cnt; i++) {
191 memcpy(nrecord, orecord, expected_rec_size);
192 memset(nrecord + expected_rec_size, 0,
193 actual_rec_size - expected_rec_size);
194 orecord += actual_rec_size;
195 nrecord += actual_rec_size;
196 }
197
198 return info;
199}
200
176int bpf_load_program_xattr(const struct bpf_load_program_attr *load_attr,201int bpf_load_program_xattr(const struct bpf_load_program_attr *load_attr,
177 char *log_buf, size_t log_buf_sz)202 char *log_buf, size_t log_buf_sz)
178{203{
204 void *finfo = NULL, *linfo = NULL;
179 union bpf_attr attr;205 union bpf_attr attr;
180 void *finfo = NULL;
181 __u32 name_len;206 __u32 name_len;
182 int fd;207 int fd;
183 208
@@ -201,53 +226,58 @@ int bpf_load_program_xattr(const struct bpf_load_program_attr *load_attr, · 17 unmodified lines
201 attr.func_info_rec_size = load_attr->func_info_rec_size;226 attr.func_info_rec_size = load_attr->func_info_rec_size;
202 attr.func_info_cnt = load_attr->func_info_cnt;227 attr.func_info_cnt = load_attr->func_info_cnt;
203 attr.func_info = ptr_to_u64(load_attr->func_info);228 attr.func_info = ptr_to_u64(load_attr->func_info);
229 attr.line_info_rec_size = load_attr->line_info_rec_size;
230 attr.line_info_cnt = load_attr->line_info_cnt;
231 attr.line_info = ptr_to_u64(load_attr->line_info);
204 memcpy(attr.prog_name, load_attr->name,232 memcpy(attr.prog_name, load_attr->name,
205 min(name_len, BPF_OBJ_NAME_LEN - 1));233 min(name_len, BPF_OBJ_NAME_LEN - 1));
206 234
207 fd = sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));235 fd = sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
208 if (fd >= 0 || !log_buf || !log_buf_sz)236 if (fd >= 0)
209 return fd;237 return fd;
210 238
211 /* After bpf_prog_load, the kernel may modify certain attributes239 /* After bpf_prog_load, the kernel may modify certain attributes
212 * to give user space a hint how to deal with loading failure.240 * to give user space a hint how to deal with loading failure.
213 * Check to see whether we can make some changes and load again.241 * Check to see whether we can make some changes and load again.
214 */242 */
215 if (errno == E2BIG && attr.func_info_cnt &&243 while (errno == E2BIG && (!finfo || !linfo)) {
216 attr.func_info_rec_size < load_attr->func_info_rec_size) {244 if (!finfo && attr.func_info_cnt &&
217 __u32 actual_rec_size = load_attr->func_info_rec_size;245 attr.func_info_rec_size < load_attr->func_info_rec_size) {
218 __u32 expected_rec_size = attr.func_info_rec_size;246 /* try with corrected func info records */
219 __u32 finfo_cnt = load_attr->func_info_cnt;247 finfo = alloc_zero_tailing_info(load_attr->func_info,
220 __u64 finfo_len = actual_rec_size * finfo_cnt;248 load_attr->func_info_cnt,
221 const void *orecord;249 load_attr->func_info_rec_size,
222 void *nrecord;250 attr.func_info_rec_size);
223 int i;251 if (!finfo)
224 252 goto done;
225 finfo = malloc(finfo_len);253
226 if (!finfo)254 attr.func_info = ptr_to_u64(finfo);
227 /* further try with log buffer won't help */255 attr.func_info_rec_size = load_attr->func_info_rec_size;
228 return fd;256 } else if (!linfo && attr.line_info_cnt &&
229 257 attr.line_info_rec_size <
230 /* zero out bytes kernel does not understand */258 load_attr->line_info_rec_size) {
231 orecord = load_attr->func_info;259 linfo = alloc_zero_tailing_info(load_attr->line_info,
232 nrecord = finfo;260 load_attr->line_info_cnt,
233 for (i = 0; i < load_attr->func_info_cnt; i++) {261 load_attr->line_info_rec_size,
234 memcpy(nrecord, orecord, expected_rec_size);262 attr.line_info_rec_size);
235 memset(nrecord + expected_rec_size, 0,263 if (!linfo)
236 actual_rec_size - expected_rec_size);264 goto done;
237 orecord += actual_rec_size;265
238 nrecord += actual_rec_size;266 attr.line_info = ptr_to_u64(linfo);
267 attr.line_info_rec_size = load_attr->line_info_rec_size;
268 } else {
269 break;
239 }270 }
240 271
241 /* try with corrected func info records */
242 attr.func_info = ptr_to_u64(finfo);
243 attr.func_info_rec_size = load_attr->func_info_rec_size;
244
245 fd = sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));272 fd = sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
246 273
247 if (fd >= 0 || !log_buf || !log_buf_sz)274 if (fd >= 0)
248 goto done;275 goto done;
249 }276 }
250 277
278 if (!log_buf || !log_buf_sz)
279 goto done;
280
251 /* Try again with log */281 /* Try again with log */
252 attr.log_buf = ptr_to_u64(log_buf);282 attr.log_buf = ptr_to_u64(log_buf);
253 attr.log_size = log_buf_sz;283 attr.log_size = log_buf_sz;
@@ -256,6 +286,7 @@ int bpf_load_program_xattr(const struct bpf_load_program_attr *load_attr, · 2 unmodified lines
256 fd = sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));286 fd = sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
257done:287done:
258 free(finfo);288 free(finfo);
289 free(linfo);
259 return fd;290 return fd;
260}291}
261 292
tools/lib/bpf/bpf.h+3−0
@@ -82,6 +82,9 @@ struct bpf_load_program_attr { · 81 unmodified lines
82 __u32 func_info_rec_size;82 __u32 func_info_rec_size;
83 const void *func_info;83 const void *func_info;
84 __u32 func_info_cnt;84 __u32 func_info_cnt;
85 __u32 line_info_rec_size;
86 const void *line_info;
87 __u32 line_info_cnt;
85};88};
86 89
87/* Flags to direct loading requirements */90/* Flags to direct loading requirements */
tools/lib/bpf/bpf_prog_linfo.c+253−0
@@ -0,0 +1,253 @@
1// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
2/* Copyright (c) 2018 Facebook */
3
4#include <string.h>
5#include <stdlib.h>
6#include <linux/err.h>
7#include <linux/bpf.h>
8#include "libbpf.h"
9
10#ifndef min
11#define min(x, y) ((x) < (y) ? (x) : (y))
12#endif
13
14struct bpf_prog_linfo {
15 void *raw_linfo;
16 void *raw_jited_linfo;
17 __u32 *nr_jited_linfo_per_func;
18 __u32 *jited_linfo_func_idx;
19 __u32 nr_linfo;
20 __u32 nr_jited_func;
21 __u32 rec_size;
22 __u32 jited_rec_size;
23};
24
25static int dissect_jited_func(struct bpf_prog_linfo *prog_linfo,
26 const __u64 *ksym_func, const __u32 *ksym_len)
27{
28 __u32 nr_jited_func, nr_linfo;
29 const void *raw_jited_linfo;
30 const __u64 *jited_linfo;
31 __u64 last_jited_linfo;
32 /*
33 * Index to raw_jited_linfo:
34 * i: Index for searching the next ksym_func
35 * prev_i: Index to the last found ksym_func
36 */
37 __u32 i, prev_i;
38 __u32 f; /* Index to ksym_func */
39
40 raw_jited_linfo = prog_linfo->raw_jited_linfo;
41 jited_linfo = raw_jited_linfo;
42 if (ksym_func[0] != *jited_linfo)
43 goto errout;
44
45 prog_linfo->jited_linfo_func_idx[0] = 0;
46 nr_jited_func = prog_linfo->nr_jited_func;
47 nr_linfo = prog_linfo->nr_linfo;
48
49 for (prev_i = 0, i = 1, f = 1;
50 i < nr_linfo && f < nr_jited_func;
51 i++) {
52 raw_jited_linfo += prog_linfo->jited_rec_size;
53 last_jited_linfo = *jited_linfo;
54 jited_linfo = raw_jited_linfo;
55
56 if (ksym_func[f] == *jited_linfo) {
57 prog_linfo->jited_linfo_func_idx[f] = i;
58
59 /* Sanity check */
60 if (last_jited_linfo - ksym_func[f - 1] + 1 >
61 ksym_len[f - 1])
62 goto errout;
63
64 prog_linfo->nr_jited_linfo_per_func[f - 1] =
65 i - prev_i;
66 prev_i = i;
67
68 /*
69 * The ksym_func[f] is found in jited_linfo.
70 * Look for the next one.
71 */
72 f++;
73 } else if (*jited_linfo <= last_jited_linfo) {
74 /* Ensure the addr is increasing _within_ a func */
75 goto errout;
76 }
77 }
78
79 if (f != nr_jited_func)
80 goto errout;
81
82 prog_linfo->nr_jited_linfo_per_func[nr_jited_func - 1] =
83 nr_linfo - prev_i;
84
85 return 0;
86
87errout:
88 return -EINVAL;
89}
90
91void bpf_prog_linfo__free(struct bpf_prog_linfo *prog_linfo)
92{
93 if (!prog_linfo)
94 return;
95
96 free(prog_linfo->raw_linfo);
97 free(prog_linfo->raw_jited_linfo);
98 free(prog_linfo->nr_jited_linfo_per_func);
99 free(prog_linfo->jited_linfo_func_idx);
100 free(prog_linfo);
101}
102
103struct bpf_prog_linfo *bpf_prog_linfo__new(const struct bpf_prog_info *info)
104{
105 struct bpf_prog_linfo *prog_linfo;
106 __u32 nr_linfo, nr_jited_func;
107
108 nr_linfo = info->line_info_cnt;
109
110 /*
111 * Test !info->line_info because the kernel may NULL
112 * the ptr if kernel.kptr_restrict is set.
113 */
114 if (!nr_linfo || !info->line_info)
115 return NULL;
116
117 /*
118 * The min size that bpf_prog_linfo has to access for
119 * searching purpose.
120 */
121 if (info->line_info_rec_size <
122 offsetof(struct bpf_line_info, file_name_off))
123 return NULL;
124
125 prog_linfo = calloc(1, sizeof(*prog_linfo));
126 if (!prog_linfo)
127 return NULL;
128
129 /* Copy xlated line_info */
130 prog_linfo->nr_linfo = nr_linfo;
131 prog_linfo->rec_size = info->line_info_rec_size;
132 prog_linfo->raw_linfo = malloc(nr_linfo * prog_linfo->rec_size);
133 if (!prog_linfo->raw_linfo)
134 goto err_free;
135 memcpy(prog_linfo->raw_linfo, (void *)(long)info->line_info,
136 nr_linfo * prog_linfo->rec_size);
137
138 nr_jited_func = info->nr_jited_ksyms;
139 if (!nr_jited_func ||
140 !info->jited_line_info ||
141 info->jited_line_info_cnt != nr_linfo ||
142 info->jited_line_info_rec_size < sizeof(__u64) ||
143 info->nr_jited_func_lens != nr_jited_func ||
144 !info->jited_ksyms ||
145 !info->jited_func_lens)
146 /* Not enough info to provide jited_line_info */
147 return prog_linfo;
148
149 /* Copy jited_line_info */
150 prog_linfo->nr_jited_func = nr_jited_func;
151 prog_linfo->jited_rec_size = info->jited_line_info_rec_size;
152 prog_linfo->raw_jited_linfo = malloc(nr_linfo *
153 prog_linfo->jited_rec_size);
154 if (!prog_linfo->raw_jited_linfo)
155 goto err_free;
156 memcpy(prog_linfo->raw_jited_linfo,
157 (void *)(long)info->jited_line_info,
158 nr_linfo * prog_linfo->jited_rec_size);
159
160 /* Number of jited_line_info per jited func */
161 prog_linfo->nr_jited_linfo_per_func = malloc(nr_jited_func *
162 sizeof(__u32));
163 if (!prog_linfo->nr_jited_linfo_per_func)
164 goto err_free;
165
166 /*
167 * For each jited func,
168 * the start idx to the "linfo" and "jited_linfo" array,
169 */
170 prog_linfo->jited_linfo_func_idx = malloc(nr_jited_func *
171 sizeof(__u32));
172 if (!prog_linfo->jited_linfo_func_idx)
173 goto err_free;
174
175 if (dissect_jited_func(prog_linfo,
176 (__u64 *)(long)info->jited_ksyms,
177 (__u32 *)(long)info->jited_func_lens))
178 goto err_free;
179
180 return prog_linfo;
181
182err_free:
183 bpf_prog_linfo__free(prog_linfo);
184 return NULL;
185}
186
187const struct bpf_line_info *
188bpf_prog_linfo__lfind_addr_func(const struct bpf_prog_linfo *prog_linfo,
189 __u64 addr, __u32 func_idx, __u32 nr_skip)
190{
191 __u32 jited_rec_size, rec_size, nr_linfo, start, i;
192 const void *raw_jited_linfo, *raw_linfo;
193 const __u64 *jited_linfo;
194
195 if (func_idx >= prog_linfo->nr_jited_func)
196 return NULL;
197
198 nr_linfo = prog_linfo->nr_jited_linfo_per_func[func_idx];
199 if (nr_skip >= nr_linfo)
200 return NULL;
201
202 start = prog_linfo->jited_linfo_func_idx[func_idx] + nr_skip;
203 jited_rec_size = prog_linfo->jited_rec_size;
204 raw_jited_linfo = prog_linfo->raw_jited_linfo +
205 (start * jited_rec_size);
206 jited_linfo = raw_jited_linfo;
207 if (addr < *jited_linfo)
208 return NULL;
209
210 nr_linfo -= nr_skip;
211 rec_size = prog_linfo->rec_size;
212 raw_linfo = prog_linfo->raw_linfo + (start * rec_size);
213 for (i = 0; i < nr_linfo; i++) {
214 if (addr < *jited_linfo)
215 break;
216
217 raw_linfo += rec_size;
218 raw_jited_linfo += jited_rec_size;
219 jited_linfo = raw_jited_linfo;
220 }
221
222 return raw_linfo - rec_size;
223}
224
225const struct bpf_line_info *
226bpf_prog_linfo__lfind(const struct bpf_prog_linfo *prog_linfo,
227 __u32 insn_off, __u32 nr_skip)
228{
229 const struct bpf_line_info *linfo;
230 __u32 rec_size, nr_linfo, i;
231 const void *raw_linfo;
232
233 nr_linfo = prog_linfo->nr_linfo;
234 if (nr_skip >= nr_linfo)
235 return NULL;
236
237 rec_size = prog_linfo->rec_size;
238 raw_linfo = prog_linfo->raw_linfo + (nr_skip * rec_size);
239 linfo = raw_linfo;
240 if (insn_off < linfo->insn_off)
241 return NULL;
242
243 nr_linfo -= nr_skip;
244 for (i = 0; i < nr_linfo; i++) {
245 if (insn_off < linfo->insn_off)
246 break;
247
248 raw_linfo += rec_size;
249 linfo = raw_linfo;
250 }
251
252 return raw_linfo - rec_size;
253}
tools/lib/bpf/btf.c+194−148
@@ -37,10 +37,27 @@ struct btf { · 36 unmodified lines
37 int fd;37 int fd;
38};38};
39 39
40struct btf_ext_info {
41 /*
42 * info points to a deep copy of the individual info section
43 * (e.g. func_info and line_info) from the .BTF.ext.
44 * It does not include the __u32 rec_size.
45 */
46 void *info;
47 __u32 rec_size;
48 __u32 len;
49};
50
40struct btf_ext {51struct btf_ext {
41 void *func_info;52 struct btf_ext_info func_info;
42 __u32 func_info_rec_size;53 struct btf_ext_info line_info;
43 __u32 func_info_len;54};
55
56struct btf_ext_info_sec {
57 __u32 sec_name_off;
58 __u32 num_info;
59 /* Followed by num_info * record_size number of bytes */
60 __u8 data[0];
44};61};
45 62
46/* The minimum bpf_func_info checked by the loader */63/* The minimum bpf_func_info checked by the loader */
@@ -49,6 +66,14 @@ struct bpf_func_info_min { · 2 unmodified lines
49 __u32 type_id;66 __u32 type_id;
50};67};
51 68
69/* The minimum bpf_line_info checked by the loader */
70struct bpf_line_info_min {
71 __u32 insn_off;
72 __u32 file_name_off;
73 __u32 line_off;
74 __u32 line_col;
75};
76
52static inline __u64 ptr_to_u64(const void *ptr)77static inline __u64 ptr_to_u64(const void *ptr)
53{78{
54 return (__u64) (unsigned long) ptr;79 return (__u64) (unsigned long) ptr;
@@ -479,71 +504,147 @@ exit_free: · 424 unmodified lines
479 return err;504 return err;
480}505}
481 506
482static int btf_ext_validate_func_info(const void *finfo, __u32 size,507struct btf_ext_sec_copy_param {
483 btf_print_fn_t err_log)508 __u32 off;
509 __u32 len;
510 __u32 min_rec_size;
511 struct btf_ext_info *ext_info;
512 const char *desc;
513};
514
515static int btf_ext_copy_info(struct btf_ext *btf_ext,
516 __u8 *data, __u32 data_size,
517 struct btf_ext_sec_copy_param *ext_sec,
518 btf_print_fn_t err_log)
484{519{
485 int sec_hdrlen = sizeof(struct btf_sec_func_info);520 const struct btf_ext_header *hdr = (struct btf_ext_header *)data;
486 __u32 size_left, num_records, record_size;521 const struct btf_ext_info_sec *sinfo;
487 const struct btf_sec_func_info *sinfo;522 struct btf_ext_info *ext_info;
488 __u64 total_record_size;523 __u32 info_left, record_size;
489 524 /* The start of the info sec (including the __u32 record_size). */
490 /* At least a func_info record size */525 const void *info;
491 if (size < sizeof(__u32)) {526
492 elog("BTF.ext func_info record size not found");527 /* data and data_size do not include btf_ext_header from now on */
528 data = data + hdr->hdr_len;
529 data_size -= hdr->hdr_len;
530
531 if (ext_sec->off & 0x03) {
532 elog(".BTF.ext %s section is not aligned to 4 bytes\n",
533 ext_sec->desc);
493 return -EINVAL;534 return -EINVAL;
494 }535 }
495 536
496 /* The record size needs to meet below minimum standard */537 if (data_size < ext_sec->off ||
497 record_size = *(__u32 *)finfo;538 ext_sec->len > data_size - ext_sec->off) {
498 if (record_size < sizeof(struct bpf_func_info_min) ||539 elog("%s section (off:%u len:%u) is beyond the end of the ELF section .BTF.ext\n",
499 record_size % sizeof(__u32)) {540 ext_sec->desc, ext_sec->off, ext_sec->len);
500 elog("BTF.ext func_info invalid record size");
501 return -EINVAL;541 return -EINVAL;
502 }542 }
503 543
504 sinfo = finfo + sizeof(__u32);544 info = data + ext_sec->off;
505 size_left = size - sizeof(__u32);545 info_left = ext_sec->len;
506 546
507 /* If no func_info records, return failure now so .BTF.ext547 /* At least a record size */
508 * won't be used.548 if (info_left < sizeof(__u32)) {
509 */549 elog(".BTF.ext %s record size not found\n", ext_sec->desc);
510 if (!size_left) {550 return -EINVAL;
511 elog("BTF.ext no func info records");551 }
552
553 /* The record size needs to meet the minimum standard */
554 record_size = *(__u32 *)info;
555 if (record_size < ext_sec->min_rec_size ||
556 record_size & 0x03) {
557 elog("%s section in .BTF.ext has invalid record size %u\n",
558 ext_sec->desc, record_size);
512 return -EINVAL;559 return -EINVAL;
513 }560 }
514 561
515 while (size_left) {562 sinfo = info + sizeof(__u32);
516 if (size_left < sec_hdrlen) {563 info_left -= sizeof(__u32);
517 elog("BTF.ext func_info header not found");564
565 /* If no records, return failure now so .BTF.ext won't be used. */
566 if (!info_left) {
567 elog("%s section in .BTF.ext has no records", ext_sec->desc);
568 return -EINVAL;
569 }
570
571 while (info_left) {
572 unsigned int sec_hdrlen = sizeof(struct btf_ext_info_sec);
573 __u64 total_record_size;
574 __u32 num_records;
575
576 if (info_left < sec_hdrlen) {
577 elog("%s section header is not found in .BTF.ext\n",
578 ext_sec->desc);
518 return -EINVAL;579 return -EINVAL;
519 }580 }
520 581
521 num_records = sinfo->num_func_info;582 num_records = sinfo->num_info;
522 if (num_records == 0) {583 if (num_records == 0) {
523 elog("incorrect BTF.ext num_func_info");584 elog("%s section has incorrect num_records in .BTF.ext\n",
585 ext_sec->desc);
524 return -EINVAL;586 return -EINVAL;
525 }587 }
526 588
527 total_record_size = sec_hdrlen +589 total_record_size = sec_hdrlen +
528 (__u64)num_records * record_size;590 (__u64)num_records * record_size;
529 if (size_left < total_record_size) {591 if (info_left < total_record_size) {
530 elog("incorrect BTF.ext num_func_info");592 elog("%s section has incorrect num_records in .BTF.ext\n",
593 ext_sec->desc);
531 return -EINVAL;594 return -EINVAL;
532 }595 }
533 596
534 size_left -= total_record_size;597 info_left -= total_record_size;
535 sinfo = (void *)sinfo + total_record_size;598 sinfo = (void *)sinfo + total_record_size;
536 }599 }
537 600
601 ext_info = ext_sec->ext_info;
602 ext_info->len = ext_sec->len - sizeof(__u32);
603 ext_info->rec_size = record_size;
604 ext_info->info = malloc(ext_info->len);
605 if (!ext_info->info)
606 return -ENOMEM;
607 memcpy(ext_info->info, info + sizeof(__u32), ext_info->len);
608
538 return 0;609 return 0;
539}610}
540 611
612static int btf_ext_copy_func_info(struct btf_ext *btf_ext,
613 __u8 *data, __u32 data_size,
614 btf_print_fn_t err_log)
615{
616 const struct btf_ext_header *hdr = (struct btf_ext_header *)data;
617 struct btf_ext_sec_copy_param param = {
618 .off = hdr->func_info_off,
619 .len = hdr->func_info_len,
620 .min_rec_size = sizeof(struct bpf_func_info_min),
621 .ext_info = &btf_ext->func_info,
622 .desc = "func_info"
623 };
624
625 return btf_ext_copy_info(btf_ext, data, data_size, &param, err_log);
626}
627
628static int btf_ext_copy_line_info(struct btf_ext *btf_ext,
629 __u8 *data, __u32 data_size,
630 btf_print_fn_t err_log)
631{
632 const struct btf_ext_header *hdr = (struct btf_ext_header *)data;
633 struct btf_ext_sec_copy_param param = {
634 .off = hdr->line_info_off,
635 .len = hdr->line_info_len,
636 .min_rec_size = sizeof(struct bpf_line_info_min),
637 .ext_info = &btf_ext->line_info,
638 .desc = "line_info",
639 };
640
641 return btf_ext_copy_info(btf_ext, data, data_size, &param, err_log);
642}
643
541static int btf_ext_parse_hdr(__u8 *data, __u32 data_size,644static int btf_ext_parse_hdr(__u8 *data, __u32 data_size,
542 btf_print_fn_t err_log)645 btf_print_fn_t err_log)
543{646{
544 const struct btf_ext_header *hdr = (struct btf_ext_header *)data;647 const struct btf_ext_header *hdr = (struct btf_ext_header *)data;
545 __u32 meta_left, last_func_info_pos;
546 void *finfo;
547 648
548 if (data_size < offsetof(struct btf_ext_header, func_info_off) ||649 if (data_size < offsetof(struct btf_ext_header, func_info_off) ||
549 data_size < hdr->hdr_len) {650 data_size < hdr->hdr_len) {
@@ -566,34 +667,12 @@ static int btf_ext_parse_hdr(__u8 *data, __u32 data_size, · 16 unmodified lines
566 return -ENOTSUP;667 return -ENOTSUP;
567 }668 }
568 669
569 meta_left = data_size - hdr->hdr_len;670 if (data_size == hdr->hdr_len) {
570 if (!meta_left) {
571 elog("BTF.ext has no data\n");671 elog("BTF.ext has no data\n");
572 return -EINVAL;672 return -EINVAL;
573 }673 }
574 674
575 if (meta_left < hdr->func_info_off) {675 return 0;
576 elog("Invalid BTF.ext func_info section offset:%u\n",
577 hdr->func_info_off);
578 return -EINVAL;
579 }
580
581 if (hdr->func_info_off & 0x03) {
582 elog("BTF.ext func_info section is not aligned to 4 bytes\n");
583 return -EINVAL;
584 }
585
586 last_func_info_pos = hdr->hdr_len + hdr->func_info_off +
587 hdr->func_info_len;
588 if (last_func_info_pos > data_size) {
589 elog("Invalid BTF.ext func_info section size:%u\n",
590 hdr->func_info_len);
591 return -EINVAL;
592 }
593
594 finfo = data + hdr->hdr_len + hdr->func_info_off;
595 return btf_ext_validate_func_info(finfo, hdr->func_info_len,
596 err_log);
597}676}
598 677
599void btf_ext__free(struct btf_ext *btf_ext)678void btf_ext__free(struct btf_ext *btf_ext)
@@ -601,16 +680,14 @@ void btf_ext__free(struct btf_ext *btf_ext) · 1 unmodified line
601 if (!btf_ext)680 if (!btf_ext)
602 return;681 return;
603 682
604 free(btf_ext->func_info);683 free(btf_ext->func_info.info);
684 free(btf_ext->line_info.info);
605 free(btf_ext);685 free(btf_ext);
606}686}
607 687
608struct btf_ext *btf_ext__new(__u8 *data, __u32 size, btf_print_fn_t err_log)688struct btf_ext *btf_ext__new(__u8 *data, __u32 size, btf_print_fn_t err_log)
609{689{
610 const struct btf_ext_header *hdr;
611 struct btf_ext *btf_ext;690 struct btf_ext *btf_ext;
612 void *org_fdata, *fdata;
613 __u32 hdrlen, size_u32;
614 int err;691 int err;
615 692
616 err = btf_ext_parse_hdr(data, size, err_log);693 err = btf_ext_parse_hdr(data, size, err_log);
@@ -621,42 +698,38 @@ struct btf_ext *btf_ext__new(__u8 *data, __u32 size, btf_print_fn_t err_log) · 4 unmodified lines
621 if (!btf_ext)698 if (!btf_ext)
622 return ERR_PTR(-ENOMEM);699 return ERR_PTR(-ENOMEM);
623 700
624 hdr = (const struct btf_ext_header *)data;701 err = btf_ext_copy_func_info(btf_ext, data, size, err_log);
625 hdrlen = hdr->hdr_len;702 if (err) {
626 size_u32 = sizeof(__u32);703 btf_ext__free(btf_ext);
627 fdata = malloc(hdr->func_info_len - size_u32);704 return ERR_PTR(err);
628 if (!fdata) {
629 free(btf_ext);
630 return ERR_PTR(-ENOMEM);
631 }705 }
632 706
633 /* remember record size and copy rest of func_info data */707 err = btf_ext_copy_line_info(btf_ext, data, size, err_log);
634 org_fdata = data + hdrlen + hdr->func_info_off;708 if (err) {
635 btf_ext->func_info_rec_size = *(__u32 *)org_fdata;709 btf_ext__free(btf_ext);
636 memcpy(fdata, org_fdata + size_u32, hdr->func_info_len - size_u32);710 return ERR_PTR(err);
637 btf_ext->func_info = fdata;711 }
638 btf_ext->func_info_len = hdr->func_info_len - size_u32;
639 712
640 return btf_ext;713 return btf_ext;
641}714}
642 715
643int btf_ext__reloc_init(struct btf *btf, struct btf_ext *btf_ext,716static int btf_ext_reloc_info(const struct btf *btf,
644 const char *sec_name, void **func_info,717 const struct btf_ext_info *ext_info,
645 __u32 *func_info_rec_size, __u32 *func_info_len)718 const char *sec_name, __u32 insns_cnt,
719 void **info, __u32 *cnt)
646{720{
647 __u32 sec_hdrlen = sizeof(struct btf_sec_func_info);721 __u32 sec_hdrlen = sizeof(struct btf_ext_info_sec);
648 __u32 i, record_size, records_len;722 __u32 i, record_size, existing_len, records_len;
649 struct btf_sec_func_info *sinfo;723 struct btf_ext_info_sec *sinfo;
650 const char *info_sec_name;724 const char *info_sec_name;
651 __s64 remain_len;725 __u64 remain_len;
652 void *data;726 void *data;
653 727
654 record_size = btf_ext->func_info_rec_size;728 record_size = ext_info->rec_size;
655 sinfo = btf_ext->func_info;729 sinfo = ext_info->info;
656 remain_len = btf_ext->func_info_len;730 remain_len = ext_info->len;
657
658 while (remain_len > 0) {731 while (remain_len > 0) {
659 records_len = sinfo->num_func_info * record_size;732 records_len = sinfo->num_info * record_size;
660 info_sec_name = btf__name_by_offset(btf, sinfo->sec_name_off);733 info_sec_name = btf__name_by_offset(btf, sinfo->sec_name_off);
661 if (strcmp(info_sec_name, sec_name)) {734 if (strcmp(info_sec_name, sec_name)) {
662 remain_len -= sec_hdrlen + records_len;735 remain_len -= sec_hdrlen + records_len;
@@ -664,79 +737,52 @@ int btf_ext__reloc_init(struct btf *btf, struct btf_ext *btf_ext, · 1 unmodified line
664 continue;737 continue;
665 }738 }
666 739
667 data = malloc(records_len);740 existing_len = (*cnt) * record_size;
741 data = realloc(*info, existing_len + records_len);
668 if (!data)742 if (!data)
669 return -ENOMEM;743 return -ENOMEM;
670 744
671 memcpy(data, sinfo->data, records_len);745 memcpy(data + existing_len, sinfo->data, records_len);
672 746 /* adjust insn_off only, the rest data will be passed
673 /* adjust the insn_off, the data in .BTF.ext is747 * to the kernel.
674 * the actual byte offset, and the kernel expects
675 * the offset in term of bpf_insn.
676 *
677 * adjust the insn offset only, the rest data will
678 * be passed to kernel.
679 */748 */
680 for (i = 0; i < sinfo->num_func_info; i++) {749 for (i = 0; i < sinfo->num_info; i++) {
681 struct bpf_func_info_min *record;750 __u32 *insn_off;
682 751
683 record = data + i * record_size;752 insn_off = data + existing_len + (i * record_size);
684 record->insn_off /= sizeof(struct bpf_insn);753 *insn_off = *insn_off / sizeof(struct bpf_insn) +
754 insns_cnt;
685 }755 }
686 756 *info = data;
687 *func_info = data;757 *cnt += sinfo->num_info;
688 *func_info_len = records_len;
689 *func_info_rec_size = record_size;
690 return 0;758 return 0;
691 }759 }
692 760
693 return -EINVAL;761 return -ENOENT;
694}762}
695 763
696int btf_ext__reloc(struct btf *btf, struct btf_ext *btf_ext,764int btf_ext__reloc_func_info(const struct btf *btf, const struct btf_ext *btf_ext,
697 const char *sec_name, __u32 insns_cnt,765 const char *sec_name, __u32 insns_cnt,
698 void **func_info, __u32 *func_info_len)766 void **func_info, __u32 *cnt)
699{767{
700 __u32 sec_hdrlen = sizeof(struct btf_sec_func_info);768 return btf_ext_reloc_info(btf, &btf_ext->func_info, sec_name,
701 __u32 i, record_size, existing_flen, records_len;769 insns_cnt, func_info, cnt);
702 struct btf_sec_func_info *sinfo;770}
703 const char *info_sec_name;
704 __u64 remain_len;
705 void *data;
706
707 record_size = btf_ext->func_info_rec_size;
708 sinfo = btf_ext->func_info;
709 remain_len = btf_ext->func_info_len;
710 while (remain_len > 0) {
711 records_len = sinfo->num_func_info * record_size;
712 info_sec_name = btf__name_by_offset(btf, sinfo->sec_name_off);
713 if (strcmp(info_sec_name, sec_name)) {
714 remain_len -= sec_hdrlen + records_len;
715 sinfo = (void *)sinfo + sec_hdrlen + records_len;
716 continue;
717 }
718
719 existing_flen = *func_info_len;
720 data = realloc(*func_info, existing_flen + records_len);
721 if (!data)
722 return -ENOMEM;
723 771
724 memcpy(data + existing_flen, sinfo->data, records_len);772int btf_ext__reloc_line_info(const struct btf *btf, const struct btf_ext *btf_ext,
725 /* adjust insn_off only, the rest data will be passed773 const char *sec_name, __u32 insns_cnt,
726 * to the kernel.774 void **line_info, __u32 *cnt)
727 */775{
728 for (i = 0; i < sinfo->num_func_info; i++) {776 return btf_ext_reloc_info(btf, &btf_ext->line_info, sec_name,
729 struct bpf_func_info_min *record;777 insns_cnt, line_info, cnt);
778}
730 779
731 record = data + existing_flen + i * record_size;780__u32 btf_ext__func_info_rec_size(const struct btf_ext *btf_ext)
732 record->insn_off =781{
733 record->insn_off / sizeof(struct bpf_insn) +782 return btf_ext->func_info.rec_size;
734 insns_cnt;783}
735 }
736 *func_info = data;
737 *func_info_len = existing_flen + records_len;
738 return 0;
739 }
740 784
741 return -EINVAL;785__u32 btf_ext__line_info_rec_size(const struct btf_ext *btf_ext)
786{
787 return btf_ext->line_info.rec_size;
742}788}
tools/lib/bpf/btf.h+12−13
@@ -51,13 +51,8 @@ struct btf_ext_header { · 50 unmodified lines
51 /* All offsets are in bytes relative to the end of this header */51 /* All offsets are in bytes relative to the end of this header */
52 __u32 func_info_off;52 __u32 func_info_off;
53 __u32 func_info_len;53 __u32 func_info_len;
54};54 __u32 line_info_off;
55 55 __u32 line_info_len;
56struct btf_sec_func_info {
57 __u32 sec_name_off;
58 __u32 num_func_info;
59 /* Followed by num_func_info number of bpf func_info records */
60 __u8 data[0];
61};56};
62 57
63typedef int (*btf_print_fn_t)(const char *, ...)58typedef int (*btf_print_fn_t)(const char *, ...)
@@ -77,12 +72,16 @@ LIBBPF_API int btf__get_from_id(__u32 id, struct btf **btf); · 13 unmodified lines
77 72
78struct btf_ext *btf_ext__new(__u8 *data, __u32 size, btf_print_fn_t err_log);73struct btf_ext *btf_ext__new(__u8 *data, __u32 size, btf_print_fn_t err_log);
79void btf_ext__free(struct btf_ext *btf_ext);74void btf_ext__free(struct btf_ext *btf_ext);
80int btf_ext__reloc_init(struct btf *btf, struct btf_ext *btf_ext,75int btf_ext__reloc_func_info(const struct btf *btf,
81 const char *sec_name, void **func_info,76 const struct btf_ext *btf_ext,
82 __u32 *func_info_rec_size, __u32 *func_info_len);77 const char *sec_name, __u32 insns_cnt,
83int btf_ext__reloc(struct btf *btf, struct btf_ext *btf_ext,78 void **func_info, __u32 *func_info_len);
84 const char *sec_name, __u32 insns_cnt, void **func_info,79int btf_ext__reloc_line_info(const struct btf *btf,
85 __u32 *func_info_len);80 const struct btf_ext *btf_ext,
81 const char *sec_name, __u32 insns_cnt,
82 void **line_info, __u32 *cnt);
83__u32 btf_ext__func_info_rec_size(const struct btf_ext *btf_ext);
84__u32 btf_ext__line_info_rec_size(const struct btf_ext *btf_ext);
86 85
87#ifdef __cplusplus86#ifdef __cplusplus
88} /* extern "C" */87} /* extern "C" */
tools/lib/bpf/libbpf.c+115−44
@@ -167,9 +167,13 @@ struct bpf_program { · 166 unmodified lines
167 int btf_fd;167 int btf_fd;
168 void *func_info;168 void *func_info;
169 __u32 func_info_rec_size;169 __u32 func_info_rec_size;
170 __u32 func_info_len;170 __u32 func_info_cnt;
171 171
172 struct bpf_capabilities *caps;172 struct bpf_capabilities *caps;
173
174 void *line_info;
175 __u32 line_info_rec_size;
176 __u32 line_info_cnt;
173};177};
174 178
175struct bpf_map {179struct bpf_map {
@@ -779,6 +783,7 @@ static int bpf_object__elf_collect(struct bpf_object *obj, int flags) · 603 unmodified lines
779{783{
780 Elf *elf = obj->efile.elf;784 Elf *elf = obj->efile.elf;
781 GElf_Ehdr *ep = &obj->efile.ehdr;785 GElf_Ehdr *ep = &obj->efile.ehdr;
786 Elf_Data *btf_ext_data = NULL;
782 Elf_Scn *scn = NULL;787 Elf_Scn *scn = NULL;
783 int idx = 0, err = 0;788 int idx = 0, err = 0;
784 789
@@ -841,14 +846,7 @@ static int bpf_object__elf_collect(struct bpf_object *obj, int flags) · 56 unmodified lines
841 obj->btf = NULL;846 obj->btf = NULL;
842 }847 }
843 } else if (strcmp(name, BTF_EXT_ELF_SEC) == 0) {848 } else if (strcmp(name, BTF_EXT_ELF_SEC) == 0) {
844 obj->btf_ext = btf_ext__new(data->d_buf, data->d_size,849 btf_ext_data = data;
845 __pr_debug);
846 if (IS_ERR(obj->btf_ext)) {
847 pr_warning("Error loading ELF section %s: %ld. Ignored and continue.\n",
848 BTF_EXT_ELF_SEC,
849 PTR_ERR(obj->btf_ext));
850 obj->btf_ext = NULL;
851 }
852 } else if (sh.sh_type == SHT_SYMTAB) {850 } else if (sh.sh_type == SHT_SYMTAB) {
853 if (obj->efile.symbols) {851 if (obj->efile.symbols) {
854 pr_warning("bpf: multiple SYMTAB in %s\n",852 pr_warning("bpf: multiple SYMTAB in %s\n",
@@ -910,6 +908,22 @@ static int bpf_object__elf_collect(struct bpf_object *obj, int flags) · 55 unmodified lines
910 pr_warning("Corrupted ELF file: index of strtab invalid\n");908 pr_warning("Corrupted ELF file: index of strtab invalid\n");
911 return LIBBPF_ERRNO__FORMAT;909 return LIBBPF_ERRNO__FORMAT;
912 }910 }
911 if (btf_ext_data) {
912 if (!obj->btf) {
913 pr_debug("Ignore ELF section %s because its depending ELF section %s is not found.\n",
914 BTF_EXT_ELF_SEC, BTF_ELF_SEC);
915 } else {
916 obj->btf_ext = btf_ext__new(btf_ext_data->d_buf,
917 btf_ext_data->d_size,
918 __pr_debug);
919 if (IS_ERR(obj->btf_ext)) {
920 pr_warning("Error loading ELF section %s: %ld. Ignored and continue.\n",
921 BTF_EXT_ELF_SEC,
922 PTR_ERR(obj->btf_ext));
923 obj->btf_ext = NULL;
924 }
925 }
926 }
913 if (obj->efile.maps_shndx >= 0) {927 if (obj->efile.maps_shndx >= 0) {
914 err = bpf_object__init_maps(obj, flags);928 err = bpf_object__init_maps(obj, flags);
915 if (err)929 if (err)
@@ -1275,6 +1289,82 @@ bpf_object__create_maps(struct bpf_object *obj) · 359 unmodified lines
1275 return 0;1289 return 0;
1276}1290}
1277 1291
1292static int
1293check_btf_ext_reloc_err(struct bpf_program *prog, int err,
1294 void *btf_prog_info, const char *info_name)
1295{
1296 if (err != -ENOENT) {
1297 pr_warning("Error in loading %s for sec %s.\n",
1298 info_name, prog->section_name);
1299 return err;
1300 }
1301
1302 /* err == -ENOENT (i.e. prog->section_name not found in btf_ext) */
1303
1304 if (btf_prog_info) {
1305 /*
1306 * Some info has already been found but has problem
1307 * in the last btf_ext reloc. Must have to error
1308 * out.
1309 */
1310 pr_warning("Error in relocating %s for sec %s.\n",
1311 info_name, prog->section_name);
1312 return err;
1313 }
1314
1315 /*
1316 * Have problem loading the very first info. Ignore
1317 * the rest.
1318 */
1319 pr_warning("Cannot find %s for main program sec %s. Ignore all %s.\n",
1320 info_name, prog->section_name, info_name);
1321 return 0;
1322}
1323
1324static int
1325bpf_program_reloc_btf_ext(struct bpf_program *prog, struct bpf_object *obj,
1326 const char *section_name, __u32 insn_offset)
1327{
1328 int err;
1329
1330 if (!insn_offset || prog->func_info) {
1331 /*
1332 * !insn_offset => main program
1333 *
1334 * For sub prog, the main program's func_info has to
1335 * be loaded first (i.e. prog->func_info != NULL)
1336 */
1337 err = btf_ext__reloc_func_info(obj->btf, obj->btf_ext,
1338 section_name, insn_offset,
1339 &prog->func_info,
1340 &prog->func_info_cnt);
1341 if (err)
1342 return check_btf_ext_reloc_err(prog, err,
1343 prog->func_info,
1344 "bpf_func_info");
1345
1346 prog->func_info_rec_size = btf_ext__func_info_rec_size(obj->btf_ext);
1347 }
1348
1349 if (!insn_offset || prog->line_info) {
1350 err = btf_ext__reloc_line_info(obj->btf, obj->btf_ext,
1351 section_name, insn_offset,
1352 &prog->line_info,
1353 &prog->line_info_cnt);
1354 if (err)
1355 return check_btf_ext_reloc_err(prog, err,
1356 prog->line_info,
1357 "bpf_line_info");
1358
1359 prog->line_info_rec_size = btf_ext__line_info_rec_size(obj->btf_ext);
1360 }
1361
1362 if (!insn_offset)
1363 prog->btf_fd = btf__fd(obj->btf);
1364
1365 return 0;
1366}
1367
1278static int1368static int
1279bpf_program__reloc_text(struct bpf_program *prog, struct bpf_object *obj,1369bpf_program__reloc_text(struct bpf_program *prog, struct bpf_object *obj,
1280 struct reloc_desc *relo)1370 struct reloc_desc *relo)
@@ -1306,17 +1396,12 @@ bpf_program__reloc_text(struct bpf_program *prog, struct bpf_object *obj, · 25 unmodified lines
1306 return -ENOMEM;1396 return -ENOMEM;
1307 }1397 }
1308 1398
1309 if (obj->btf && obj->btf_ext) {1399 if (obj->btf_ext) {
1310 err = btf_ext__reloc(obj->btf, obj->btf_ext,1400 err = bpf_program_reloc_btf_ext(prog, obj,
1311 text->section_name,1401 text->section_name,
1312 prog->insns_cnt,1402 prog->insns_cnt);
1313 &prog->func_info,1403 if (err)
1314 &prog->func_info_len);
1315 if (err) {
1316 pr_warning("error in btf_ext__reloc for sec %s\n",
1317 text->section_name);
1318 return err;1404 return err;
1319 }
1320 }1405 }
1321 1406
1322 memcpy(new_insn + prog->insns_cnt, text->insns,1407 memcpy(new_insn + prog->insns_cnt, text->insns,
@@ -1341,18 +1426,11 @@ bpf_program__relocate(struct bpf_program *prog, struct bpf_object *obj) · 18 unmodified lines
1341 if (!prog)1426 if (!prog)
1342 return 0;1427 return 0;
1343 1428
1344 if (obj->btf && obj->btf_ext) {1429 if (obj->btf_ext) {
1345 err = btf_ext__reloc_init(obj->btf, obj->btf_ext,1430 err = bpf_program_reloc_btf_ext(prog, obj,
1346 prog->section_name,1431 prog->section_name, 0);
1347 &prog->func_info,1432 if (err)
1348 &prog->func_info_rec_size,
1349 &prog->func_info_len);
1350 if (err) {
1351 pr_warning("err in btf_ext__reloc_init for sec %s\n",
1352 prog->section_name);
1353 return err;1433 return err;
1354 }
1355 prog->btf_fd = btf__fd(obj->btf);
1356 }1434 }
1357 1435
1358 if (!prog->reloc_desc)1436 if (!prog->reloc_desc)
@@ -1444,8 +1522,7 @@ static int bpf_object__collect_reloc(struct bpf_object *obj) · 85 unmodified lines
1444 1522
1445static int1523static int
1446load_program(struct bpf_program *prog, struct bpf_insn *insns, int insns_cnt,1524load_program(struct bpf_program *prog, struct bpf_insn *insns, int insns_cnt,
1447 char *license, __u32 kern_version, int *pfd,1525 char *license, __u32 kern_version, int *pfd)
1448 __u32 func_info_cnt)
1449{1526{
1450 struct bpf_load_program_attr load_attr;1527 struct bpf_load_program_attr load_attr;
1451 char *cp, errmsg[STRERR_BUFSIZE];1528 char *cp, errmsg[STRERR_BUFSIZE];
@@ -1465,8 +1542,10 @@ load_program(struct bpf_program *prog, struct bpf_insn *insns, int insns_cnt, · 13 unmodified lines
1465 load_attr.prog_btf_fd = prog->btf_fd >= 0 ? prog->btf_fd : 0;1542 load_attr.prog_btf_fd = prog->btf_fd >= 0 ? prog->btf_fd : 0;
1466 load_attr.func_info = prog->func_info;1543 load_attr.func_info = prog->func_info;
1467 load_attr.func_info_rec_size = prog->func_info_rec_size;1544 load_attr.func_info_rec_size = prog->func_info_rec_size;
1468 load_attr.func_info_cnt = func_info_cnt;1545 load_attr.func_info_cnt = prog->func_info_cnt;
1469 1546 load_attr.line_info = prog->line_info;
1547 load_attr.line_info_rec_size = prog->line_info_rec_size;
1548 load_attr.line_info_cnt = prog->line_info_cnt;
1470 if (!load_attr.insns || !load_attr.insns_cnt)1549 if (!load_attr.insns || !load_attr.insns_cnt)
1471 return -EINVAL;1550 return -EINVAL;
1472 1551
@@ -1523,14 +1602,8 @@ int · 50 unmodified lines
1523bpf_program__load(struct bpf_program *prog,1602bpf_program__load(struct bpf_program *prog,
1524 char *license, __u32 kern_version)1603 char *license, __u32 kern_version)
1525{1604{
1526 __u32 func_info_cnt;
1527 int err = 0, fd, i;1605 int err = 0, fd, i;
1528 1606
1529 if (prog->func_info_len == 0)
1530 func_info_cnt = 0;
1531 else
1532 func_info_cnt = prog->func_info_len / prog->func_info_rec_size;
1533
1534 if (prog->instances.nr < 0 || !prog->instances.fds) {1607 if (prog->instances.nr < 0 || !prog->instances.fds) {
1535 if (prog->preprocessor) {1608 if (prog->preprocessor) {
1536 pr_warning("Internal error: can't load program '%s'\n",1609 pr_warning("Internal error: can't load program '%s'\n",
@@ -1553,8 +1626,7 @@ bpf_program__load(struct bpf_program *prog, · 16 unmodified lines
1553 prog->section_name, prog->instances.nr);1626 prog->section_name, prog->instances.nr);
1554 }1627 }
1555 err = load_program(prog, prog->insns, prog->insns_cnt,1628 err = load_program(prog, prog->insns, prog->insns_cnt,
1556 license, kern_version, &fd,1629 license, kern_version, &fd);
1557 func_info_cnt);
1558 if (!err)1630 if (!err)
1559 prog->instances.fds[0] = fd;1631 prog->instances.fds[0] = fd;
1560 goto out;1632 goto out;
@@ -1584,8 +1656,7 @@ bpf_program__load(struct bpf_program *prog, · 23 unmodified lines
1584 1656
1585 err = load_program(prog, result.new_insn_ptr,1657 err = load_program(prog, result.new_insn_ptr,
1586 result.new_insn_cnt,1658 result.new_insn_cnt,
1587 license, kern_version, &fd,1659 license, kern_version, &fd);
1588 func_info_cnt);
1589 1660
1590 if (err) {1661 if (err) {
1591 pr_warning("Loading the %dth instance of program '%s' failed\n",1662 pr_warning("Loading the %dth instance of program '%s' failed\n",
tools/lib/bpf/libbpf.h+13−0
@@ -342,6 +342,19 @@ int libbpf_nl_get_qdisc(int sock, unsigned int nl_pid, int ifindex, · 341 unmodified lines
342int libbpf_nl_get_filter(int sock, unsigned int nl_pid, int ifindex, int handle,342int libbpf_nl_get_filter(int sock, unsigned int nl_pid, int ifindex, int handle,
343 libbpf_dump_nlmsg_t dump_filter_nlmsg, void *cookie);343 libbpf_dump_nlmsg_t dump_filter_nlmsg, void *cookie);
344 344
345struct bpf_prog_linfo;
346struct bpf_prog_info;
347
348LIBBPF_API void bpf_prog_linfo__free(struct bpf_prog_linfo *prog_linfo);
349LIBBPF_API struct bpf_prog_linfo *
350bpf_prog_linfo__new(const struct bpf_prog_info *info);
351LIBBPF_API const struct bpf_line_info *
352bpf_prog_linfo__lfind_addr_func(const struct bpf_prog_linfo *prog_linfo,
353 __u64 addr, __u32 func_idx, __u32 nr_skip);
354LIBBPF_API const struct bpf_line_info *
355bpf_prog_linfo__lfind(const struct bpf_prog_linfo *prog_linfo,
356 __u32 insn_off, __u32 nr_skip);
357
345#ifdef __cplusplus358#ifdef __cplusplus
346} /* extern "C" */359} /* extern "C" */
347#endif360#endif
tools/lib/bpf/libbpf.map+4−0
@@ -99,6 +99,10 @@ LIBBPF_0.0.1 { · 98 unmodified lines
99 bpf_program__unload;99 bpf_program__unload;
100 bpf_program__unpin;100 bpf_program__unpin;
101 bpf_program__unpin_instance;101 bpf_program__unpin_instance;
102 bpf_prog_linfo__free;
103 bpf_prog_linfo__new;
104 bpf_prog_linfo__lfind_addr_func;
105 bpf_prog_linfo__lfind;
102 bpf_raw_tracepoint_open;106 bpf_raw_tracepoint_open;
103 bpf_set_link_xdp_fd;107 bpf_set_link_xdp_fd;
104 bpf_task_fd_query;108 bpf_task_fd_query;
tools/testing/selftests/bpf/test_btf.c+696−94
@@ -6,6 +6,7 @@ · 5 unmodified lines
6#include <linux/err.h>6#include <linux/err.h>
7#include <linux/kernel.h>7#include <linux/kernel.h>
8#include <linux/filter.h>8#include <linux/filter.h>
9#include <linux/unistd.h>
9#include <bpf/bpf.h>10#include <bpf/bpf.h>
10#include <sys/resource.h>11#include <sys/resource.h>
11#include <libelf.h>12#include <libelf.h>
@@ -107,19 +108,20 @@ static int __base_pr(const char *format, ...) · 95 unmodified lines
107#define BTF_END_RAW 0xdeadbeef108#define BTF_END_RAW 0xdeadbeef
108#define NAME_TBD 0xdeadb33f109#define NAME_TBD 0xdeadb33f
109 110
110#define MAX_NR_RAW_TYPES 1024111#define MAX_NR_RAW_U32 1024
111#define BTF_LOG_BUF_SIZE 65535112#define BTF_LOG_BUF_SIZE 65535
112 113
113static struct args {114static struct args {
114 unsigned int raw_test_num;115 unsigned int raw_test_num;
115 unsigned int file_test_num;116 unsigned int file_test_num;
116 unsigned int get_info_test_num;117 unsigned int get_info_test_num;
118 unsigned int info_raw_test_num;
117 bool raw_test;119 bool raw_test;
118 bool file_test;120 bool file_test;
119 bool get_info_test;121 bool get_info_test;
120 bool pprint_test;122 bool pprint_test;
121 bool always_log;123 bool always_log;
122 bool func_type_test;124 bool info_raw_test;
123} args;125} args;
124 126
125static char btf_log_buf[BTF_LOG_BUF_SIZE];127static char btf_log_buf[BTF_LOG_BUF_SIZE];
@@ -135,7 +137,7 @@ struct btf_raw_test { · 9 unmodified lines
135 const char *str_sec;137 const char *str_sec;
136 const char *map_name;138 const char *map_name;
137 const char *err_str;139 const char *err_str;
138 __u32 raw_types[MAX_NR_RAW_TYPES];140 __u32 raw_types[MAX_NR_RAW_U32];
139 __u32 str_sec_size;141 __u32 str_sec_size;
140 enum bpf_map_type map_type;142 enum bpf_map_type map_type;
141 __u32 key_size;143 __u32 key_size;
@@ -154,6 +156,9 @@ struct btf_raw_test { · 12 unmodified lines
154 int str_len_delta;156 int str_len_delta;
155};157};
156 158
159#define BTF_STR_SEC(str) \
160 .str_sec = str, .str_sec_size = sizeof(str)
161
157static struct btf_raw_test raw_tests[] = {162static struct btf_raw_test raw_tests[] = {
158/* enum E {163/* enum E {
159 * E0,164 * E0,
@@ -1856,11 +1861,11 @@ static const char *get_next_str(const char *start, const char *end) · 1696 unmodified lines
1856 return start < end - 1 ? start + 1 : NULL;1861 return start < end - 1 ? start + 1 : NULL;
1857}1862}
1858 1863
1859static int get_type_sec_size(const __u32 *raw_types)1864static int get_raw_sec_size(const __u32 *raw_types)
1860{1865{
1861 int i;1866 int i;
1862 1867
1863 for (i = MAX_NR_RAW_TYPES - 1;1868 for (i = MAX_NR_RAW_U32 - 1;
1864 i >= 0 && raw_types[i] != BTF_END_RAW;1869 i >= 0 && raw_types[i] != BTF_END_RAW;
1865 i--)1870 i--)
1866 ;1871 ;
@@ -1872,7 +1877,8 @@ static void *btf_raw_create(const struct btf_header *hdr, · 5 unmodified lines
1872 const __u32 *raw_types,1877 const __u32 *raw_types,
1873 const char *str,1878 const char *str,
1874 unsigned int str_sec_size,1879 unsigned int str_sec_size,
1875 unsigned int *btf_size)1880 unsigned int *btf_size,
1881 const char **ret_next_str)
1876{1882{
1877 const char *next_str = str, *end_str = str + str_sec_size;1883 const char *next_str = str, *end_str = str + str_sec_size;
1878 unsigned int size_needed, offset;1884 unsigned int size_needed, offset;
@@ -1881,7 +1887,7 @@ static void *btf_raw_create(const struct btf_header *hdr, · 2 unmodified lines
1881 uint32_t *ret_types;1887 uint32_t *ret_types;
1882 void *raw_btf;1888 void *raw_btf;
1883 1889
1884 type_sec_size = get_type_sec_size(raw_types);1890 type_sec_size = get_raw_sec_size(raw_types);
1885 if (CHECK(type_sec_size < 0, "Cannot get nr_raw_types"))1891 if (CHECK(type_sec_size < 0, "Cannot get nr_raw_types"))
1886 return NULL;1892 return NULL;
1887 1893
@@ -1920,6 +1926,8 @@ static void *btf_raw_create(const struct btf_header *hdr, · 32 unmodified lines
1920 ret_hdr->str_len = str_sec_size;1926 ret_hdr->str_len = str_sec_size;
1921 1927
1922 *btf_size = size_needed;1928 *btf_size = size_needed;
1929 if (ret_next_str)
1930 *ret_next_str = next_str;
1923 1931
1924 return raw_btf;1932 return raw_btf;
1925}1933}
@@ -1939,7 +1947,7 @@ static int do_test_raw(unsigned int test_num) · 13 unmodified lines
1939 test->raw_types,1947 test->raw_types,
1940 test->str_sec,1948 test->str_sec,
1941 test->str_sec_size,1949 test->str_sec_size,
1942 &raw_btf_size);1950 &raw_btf_size, NULL);
1943 1951
1944 if (!raw_btf)1952 if (!raw_btf)
1945 return -1;1953 return -1;
@@ -2016,7 +2024,7 @@ static int test_raw(void) · 70 unmodified lines
2016struct btf_get_info_test {2024struct btf_get_info_test {
2017 const char *descr;2025 const char *descr;
2018 const char *str_sec;2026 const char *str_sec;
2019 __u32 raw_types[MAX_NR_RAW_TYPES];2027 __u32 raw_types[MAX_NR_RAW_U32];
2020 __u32 str_sec_size;2028 __u32 str_sec_size;
2021 int btf_size_delta;2029 int btf_size_delta;
2022 int (*special_test)(unsigned int test_num);2030 int (*special_test)(unsigned int test_num);
@@ -2096,7 +2104,7 @@ static int test_big_btf_info(unsigned int test_num) · 73 unmodified lines
2096 test->raw_types,2104 test->raw_types,
2097 test->str_sec,2105 test->str_sec,
2098 test->str_sec_size,2106 test->str_sec_size,
2099 &raw_btf_size);2107 &raw_btf_size, NULL);
2100 2108
2101 if (!raw_btf)2109 if (!raw_btf)
2102 return -1;2110 return -1;
@@ -2180,7 +2188,7 @@ static int test_btf_id(unsigned int test_num) · 77 unmodified lines
2180 test->raw_types,2188 test->raw_types,
2181 test->str_sec,2189 test->str_sec,
2182 test->str_sec_size,2190 test->str_sec_size,
2183 &raw_btf_size);2191 &raw_btf_size, NULL);
2184 2192
2185 if (!raw_btf)2193 if (!raw_btf)
2186 return -1;2194 return -1;
@@ -2318,7 +2326,7 @@ static int do_test_get_info(unsigned int test_num) · 131 unmodified lines
2318 test->raw_types,2326 test->raw_types,
2319 test->str_sec,2327 test->str_sec,
2320 test->str_sec_size,2328 test->str_sec_size,
2321 &raw_btf_size);2329 &raw_btf_size, NULL);
2322 2330
2323 if (!raw_btf)2331 if (!raw_btf)
2324 return -1;2332 return -1;
@@ -2847,7 +2855,7 @@ static int do_test_pprint(void) · 522 unmodified lines
2847 fprintf(stderr, "%s......", test->descr);2855 fprintf(stderr, "%s......", test->descr);
2848 raw_btf = btf_raw_create(&hdr_tmpl, test->raw_types,2856 raw_btf = btf_raw_create(&hdr_tmpl, test->raw_types,
2849 test->str_sec, test->str_sec_size,2857 test->str_sec, test->str_sec_size,
2850 &raw_btf_size);2858 &raw_btf_size, NULL);
2851 2859
2852 if (!raw_btf)2860 if (!raw_btf)
2853 return -1;2861 return -1;
@@ -3051,18 +3059,25 @@ static int test_pprint(void) · 197 unmodified lines
3051 return err;3059 return err;
3052}3060}
3053 3061
3054static struct btf_func_type_test {3062#define BPF_LINE_INFO_ENC(insn_off, file_off, line_off, line_num, line_col) \
3063 (insn_off), (file_off), (line_off), ((line_num) << 10 | ((line_col) & 0x3ff))
3064
3065static struct prog_info_raw_test {
3055 const char *descr;3066 const char *descr;
3056 const char *str_sec;3067 const char *str_sec;
3057 __u32 raw_types[MAX_NR_RAW_TYPES];3068 const char *err_str;
3069 __u32 raw_types[MAX_NR_RAW_U32];
3058 __u32 str_sec_size;3070 __u32 str_sec_size;
3059 struct bpf_insn insns[MAX_INSNS];3071 struct bpf_insn insns[MAX_INSNS];
3060 __u32 prog_type;3072 __u32 prog_type;
3061 __u32 func_info[MAX_SUBPROGS][2];3073 __u32 func_info[MAX_SUBPROGS][2];
3062 __u32 func_info_rec_size;3074 __u32 func_info_rec_size;
3063 __u32 func_info_cnt;3075 __u32 func_info_cnt;
3076 __u32 line_info[MAX_NR_RAW_U32];
3077 __u32 line_info_rec_size;
3078 __u32 nr_jited_ksyms;
3064 bool expected_prog_load_failure;3079 bool expected_prog_load_failure;
3065} func_type_test[] = {3080} info_raw_tests[] = {
3066{3081{
3067 .descr = "func_type (main func + one sub)",3082 .descr = "func_type (main func + one sub)",
3068 .raw_types = {3083 .raw_types = {
@@ -3091,6 +3106,7 @@ static struct btf_func_type_test { · 22 unmodified lines
3091 .func_info = { {0, 5}, {3, 6} },3106 .func_info = { {0, 5}, {3, 6} },
3092 .func_info_rec_size = 8,3107 .func_info_rec_size = 8,
3093 .func_info_cnt = 2,3108 .func_info_cnt = 2,
3109 .line_info = { BTF_END_RAW },
3094},3110},
3095 3111
3096{3112{
@@ -3121,6 +3137,7 @@ static struct btf_func_type_test { · 24 unmodified lines
3121 .func_info = { {0, 5}, {3, 6} },3137 .func_info = { {0, 5}, {3, 6} },
3122 .func_info_rec_size = 4,3138 .func_info_rec_size = 4,
3123 .func_info_cnt = 2,3139 .func_info_cnt = 2,
3140 .line_info = { BTF_END_RAW },
3124 .expected_prog_load_failure = true,3141 .expected_prog_load_failure = true,
3125},3142},
3126 3143
@@ -3152,6 +3169,7 @@ static struct btf_func_type_test { · 25 unmodified lines
3152 .func_info = { {0, 5}, {3, 6} },3169 .func_info = { {0, 5}, {3, 6} },
3153 .func_info_rec_size = 8,3170 .func_info_rec_size = 8,
3154 .func_info_cnt = 1,3171 .func_info_cnt = 1,
3172 .line_info = { BTF_END_RAW },
3155 .expected_prog_load_failure = true,3173 .expected_prog_load_failure = true,
3156},3174},
3157 3175
@@ -3183,6 +3201,278 @@ static struct btf_func_type_test { · 25 unmodified lines
3183 .func_info = { {0, 5}, {2, 6} },3201 .func_info = { {0, 5}, {2, 6} },
3184 .func_info_rec_size = 8,3202 .func_info_rec_size = 8,
3185 .func_info_cnt = 2,3203 .func_info_cnt = 2,
3204 .line_info = { BTF_END_RAW },
3205 .expected_prog_load_failure = true,
3206},
3207
3208{
3209 .descr = "line_info (No subprog)",
3210 .raw_types = {
3211 BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
3212 BTF_END_RAW,
3213 },
3214 BTF_STR_SEC("\0int\0int a=1;\0int b=2;\0return a + b;\0return a + b;"),
3215 .insns = {
3216 BPF_MOV64_IMM(BPF_REG_0, 1),
3217 BPF_MOV64_IMM(BPF_REG_1, 2),
3218 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
3219 BPF_EXIT_INSN(),
3220 },
3221 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
3222 .func_info_cnt = 0,
3223 .line_info = {
3224 BPF_LINE_INFO_ENC(0, 0, NAME_TBD, 1, 10),
3225 BPF_LINE_INFO_ENC(1, 0, NAME_TBD, 2, 9),
3226 BPF_LINE_INFO_ENC(2, 0, NAME_TBD, 3, 8),
3227 BPF_LINE_INFO_ENC(3, 0, NAME_TBD, 4, 7),
3228 BTF_END_RAW,
3229 },
3230 .line_info_rec_size = sizeof(struct bpf_line_info),
3231 .nr_jited_ksyms = 1,
3232},
3233
3234{
3235 .descr = "line_info (No subprog. insn_off >= prog->len)",
3236 .raw_types = {
3237 BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
3238 BTF_END_RAW,
3239 },
3240 BTF_STR_SEC("\0int\0int a=1;\0int b=2;\0return a + b;\0return a + b;"),
3241 .insns = {
3242 BPF_MOV64_IMM(BPF_REG_0, 1),
3243 BPF_MOV64_IMM(BPF_REG_1, 2),
3244 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
3245 BPF_EXIT_INSN(),
3246 },
3247 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
3248 .func_info_cnt = 0,
3249 .line_info = {
3250 BPF_LINE_INFO_ENC(0, 0, NAME_TBD, 1, 10),
3251 BPF_LINE_INFO_ENC(1, 0, NAME_TBD, 2, 9),
3252 BPF_LINE_INFO_ENC(2, 0, NAME_TBD, 3, 8),
3253 BPF_LINE_INFO_ENC(3, 0, NAME_TBD, 4, 7),
3254 BPF_LINE_INFO_ENC(4, 0, 0, 5, 6),
3255 BTF_END_RAW,
3256 },
3257 .line_info_rec_size = sizeof(struct bpf_line_info),
3258 .nr_jited_ksyms = 1,
3259 .err_str = "line_info[4].insn_off",
3260 .expected_prog_load_failure = true,
3261},
3262
3263{
3264 .descr = "line_info (No subprog. zero tailing line_info",
3265 .raw_types = {
3266 BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
3267 BTF_END_RAW,
3268 },
3269 BTF_STR_SEC("\0int\0int a=1;\0int b=2;\0return a + b;\0return a + b;"),
3270 .insns = {
3271 BPF_MOV64_IMM(BPF_REG_0, 1),
3272 BPF_MOV64_IMM(BPF_REG_1, 2),
3273 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
3274 BPF_EXIT_INSN(),
3275 },
3276 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
3277 .func_info_cnt = 0,
3278 .line_info = {
3279 BPF_LINE_INFO_ENC(0, 0, NAME_TBD, 1, 10), 0,
3280 BPF_LINE_INFO_ENC(1, 0, NAME_TBD, 2, 9), 0,
3281 BPF_LINE_INFO_ENC(2, 0, NAME_TBD, 3, 8), 0,
3282 BPF_LINE_INFO_ENC(3, 0, NAME_TBD, 4, 7), 0,
3283 BTF_END_RAW,
3284 },
3285 .line_info_rec_size = sizeof(struct bpf_line_info) + sizeof(__u32),
3286 .nr_jited_ksyms = 1,
3287},
3288
3289{
3290 .descr = "line_info (No subprog. nonzero tailing line_info)",
3291 .raw_types = {
3292 BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
3293 BTF_END_RAW,
3294 },
3295 BTF_STR_SEC("\0int\0int a=1;\0int b=2;\0return a + b;\0return a + b;"),
3296 .insns = {
3297 BPF_MOV64_IMM(BPF_REG_0, 1),
3298 BPF_MOV64_IMM(BPF_REG_1, 2),
3299 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
3300 BPF_EXIT_INSN(),
3301 },
3302 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
3303 .func_info_cnt = 0,
3304 .line_info = {
3305 BPF_LINE_INFO_ENC(0, 0, NAME_TBD, 1, 10), 0,
3306 BPF_LINE_INFO_ENC(1, 0, NAME_TBD, 2, 9), 0,
3307 BPF_LINE_INFO_ENC(2, 0, NAME_TBD, 3, 8), 0,
3308 BPF_LINE_INFO_ENC(3, 0, NAME_TBD, 4, 7), 1,
3309 BTF_END_RAW,
3310 },
3311 .line_info_rec_size = sizeof(struct bpf_line_info) + sizeof(__u32),
3312 .nr_jited_ksyms = 1,
3313 .err_str = "nonzero tailing record in line_info",
3314 .expected_prog_load_failure = true,
3315},
3316
3317{
3318 .descr = "line_info (subprog)",
3319 .raw_types = {
3320 BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
3321 BTF_END_RAW,
3322 },
3323 BTF_STR_SEC("\0int\0int a=1+1;\0return func(a);\0b+=1;\0return b;"),
3324 .insns = {
3325 BPF_MOV64_IMM(BPF_REG_2, 1),
3326 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, 1),
3327 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
3328 BPF_CALL_REL(1),
3329 BPF_EXIT_INSN(),
3330 BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
3331 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 1),
3332 BPF_EXIT_INSN(),
3333 },
3334 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
3335 .func_info_cnt = 0,
3336 .line_info = {
3337 BPF_LINE_INFO_ENC(0, 0, NAME_TBD, 1, 10),
3338 BPF_LINE_INFO_ENC(2, 0, NAME_TBD, 2, 9),
3339 BPF_LINE_INFO_ENC(5, 0, NAME_TBD, 3, 8),
3340 BPF_LINE_INFO_ENC(7, 0, NAME_TBD, 4, 7),
3341 BTF_END_RAW,
3342 },
3343 .line_info_rec_size = sizeof(struct bpf_line_info),
3344 .nr_jited_ksyms = 2,
3345},
3346
3347{
3348 .descr = "line_info (subprog + func_info)",
3349 .raw_types = {
3350 BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
3351 BTF_FUNC_PROTO_ENC(1, 1), /* [2] */
3352 BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
3353 BTF_FUNC_ENC(NAME_TBD, 2), /* [3] */
3354 BTF_FUNC_ENC(NAME_TBD, 2), /* [4] */
3355 BTF_END_RAW,
3356 },
3357 BTF_STR_SEC("\0int\0x\0sub\0main\0int a=1+1;\0return func(a);\0b+=1;\0return b;"),
3358 .insns = {
3359 BPF_MOV64_IMM(BPF_REG_2, 1),
3360 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, 1),
3361 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
3362 BPF_CALL_REL(1),
3363 BPF_EXIT_INSN(),
3364 BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
3365 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 1),
3366 BPF_EXIT_INSN(),
3367 },
3368 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
3369 .func_info_cnt = 2,
3370 .func_info_rec_size = 8,
3371 .func_info = { {0, 4}, {5, 3} },
3372 .line_info = {
3373 BPF_LINE_INFO_ENC(0, 0, NAME_TBD, 1, 10),
3374 BPF_LINE_INFO_ENC(2, 0, NAME_TBD, 2, 9),
3375 BPF_LINE_INFO_ENC(5, 0, NAME_TBD, 3, 8),
3376 BPF_LINE_INFO_ENC(7, 0, NAME_TBD, 4, 7),
3377 BTF_END_RAW,
3378 },
3379 .line_info_rec_size = sizeof(struct bpf_line_info),
3380 .nr_jited_ksyms = 2,
3381},
3382
3383{
3384 .descr = "line_info (subprog. missing 1st func line info)",
3385 .raw_types = {
3386 BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
3387 BTF_END_RAW,
3388 },
3389 BTF_STR_SEC("\0int\0int a=1+1;\0return func(a);\0b+=1;\0return b;"),
3390 .insns = {
3391 BPF_MOV64_IMM(BPF_REG_2, 1),
3392 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, 1),
3393 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
3394 BPF_CALL_REL(1),
3395 BPF_EXIT_INSN(),
3396 BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
3397 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 1),
3398 BPF_EXIT_INSN(),
3399 },
3400 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
3401 .func_info_cnt = 0,
3402 .line_info = {
3403 BPF_LINE_INFO_ENC(1, 0, NAME_TBD, 1, 10),
3404 BPF_LINE_INFO_ENC(2, 0, NAME_TBD, 2, 9),
3405 BPF_LINE_INFO_ENC(5, 0, NAME_TBD, 3, 8),
3406 BPF_LINE_INFO_ENC(7, 0, NAME_TBD, 4, 7),
3407 BTF_END_RAW,
3408 },
3409 .line_info_rec_size = sizeof(struct bpf_line_info),
3410 .nr_jited_ksyms = 2,
3411 .err_str = "missing bpf_line_info for func#0",
3412 .expected_prog_load_failure = true,
3413},
3414
3415{
3416 .descr = "line_info (subprog. missing 2nd func line info)",
3417 .raw_types = {
3418 BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
3419 BTF_END_RAW,
3420 },
3421 BTF_STR_SEC("\0int\0int a=1+1;\0return func(a);\0b+=1;\0return b;"),
3422 .insns = {
3423 BPF_MOV64_IMM(BPF_REG_2, 1),
3424 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, 1),
3425 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
3426 BPF_CALL_REL(1),
3427 BPF_EXIT_INSN(),
3428 BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
3429 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 1),
3430 BPF_EXIT_INSN(),
3431 },
3432 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
3433 .func_info_cnt = 0,
3434 .line_info = {
3435 BPF_LINE_INFO_ENC(0, 0, NAME_TBD, 1, 10),
3436 BPF_LINE_INFO_ENC(2, 0, NAME_TBD, 2, 9),
3437 BPF_LINE_INFO_ENC(6, 0, NAME_TBD, 3, 8),
3438 BPF_LINE_INFO_ENC(7, 0, NAME_TBD, 4, 7),
3439 BTF_END_RAW,
3440 },
3441 .line_info_rec_size = sizeof(struct bpf_line_info),
3442 .nr_jited_ksyms = 2,
3443 .err_str = "missing bpf_line_info for func#1",
3444 .expected_prog_load_failure = true,
3445},
3446
3447{
3448 .descr = "line_info (subprog. unordered insn offset)",
3449 .raw_types = {
3450 BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
3451 BTF_END_RAW,
3452 },
3453 BTF_STR_SEC("\0int\0int a=1+1;\0return func(a);\0b+=1;\0return b;"),
3454 .insns = {
3455 BPF_MOV64_IMM(BPF_REG_2, 1),
3456 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, 1),
3457 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
3458 BPF_CALL_REL(1),
3459 BPF_EXIT_INSN(),
3460 BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
3461 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 1),
3462 BPF_EXIT_INSN(),
3463 },
3464 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
3465 .func_info_cnt = 0,
3466 .line_info = {
3467 BPF_LINE_INFO_ENC(0, 0, NAME_TBD, 1, 10),
3468 BPF_LINE_INFO_ENC(5, 0, NAME_TBD, 2, 9),
3469 BPF_LINE_INFO_ENC(2, 0, NAME_TBD, 3, 8),
3470 BPF_LINE_INFO_ENC(7, 0, NAME_TBD, 4, 7),
3471 BTF_END_RAW,
3472 },
3473 .line_info_rec_size = sizeof(struct bpf_line_info),
3474 .nr_jited_ksyms = 2,
3475 .err_str = "Invalid line_info[2].insn_off",
3186 .expected_prog_load_failure = true,3476 .expected_prog_load_failure = true,
3187},3477},
3188 3478
@@ -3198,90 +3488,84 @@ static size_t probe_prog_length(const struct bpf_insn *fp) · 9 unmodified lines
3198 return len + 1;3488 return len + 1;
3199}3489}
3200 3490
3201static int do_test_func_type(int test_num)3491static __u32 *patch_name_tbd(const __u32 *raw_u32,
3492 const char *str, __u32 str_off,
3493 unsigned int str_sec_size,
3494 unsigned int *ret_size)
3202{3495{
3203 const struct btf_func_type_test *test = &func_type_test[test_num];3496 int i, raw_u32_size = get_raw_sec_size(raw_u32);
3204 unsigned int raw_btf_size, info_len, rec_size;3497 const char *end_str = str + str_sec_size;
3205 int i, btf_fd = -1, prog_fd = -1, err = 0;3498 const char *next_str = str + str_off;
3206 struct bpf_load_program_attr attr = {};3499 __u32 *new_u32 = NULL;
3207 void *raw_btf, *func_info = NULL;
3208 struct bpf_prog_info info = {};
3209 struct bpf_func_info *finfo;
3210 3500
3211 fprintf(stderr, "%s......", test->descr);3501 if (raw_u32_size == -1)
3212 raw_btf = btf_raw_create(&hdr_tmpl, test->raw_types,3502 return ERR_PTR(-EINVAL);
3213 test->str_sec, test->str_sec_size,
3214 &raw_btf_size);
3215 3503
3216 if (!raw_btf)3504 if (!raw_u32_size) {
3217 return -1;3505 *ret_size = 0;
3506 return NULL;
3507 }
3218 3508
3219 *btf_log_buf = '\0';3509 new_u32 = malloc(raw_u32_size);
3220 btf_fd = bpf_load_btf(raw_btf, raw_btf_size,3510 if (!new_u32)
3221 btf_log_buf, BTF_LOG_BUF_SIZE,3511 return ERR_PTR(-ENOMEM);
3222 args.always_log);
3223 free(raw_btf);
3224 3512
3225 if (CHECK(btf_fd == -1, "invalid btf_fd errno:%d", errno)) {3513 for (i = 0; i < raw_u32_size / sizeof(raw_u32[0]); i++) {
3226 err = -1;3514 if (raw_u32[i] == NAME_TBD) {
3227 goto done;3515 next_str = get_next_str(next_str, end_str);
3516 if (CHECK(!next_str, "Error in getting next_str\n")) {
3517 free(new_u32);
3518 return ERR_PTR(-EINVAL);
3519 }
3520 new_u32[i] = next_str - str;
3521 next_str += strlen(next_str);
3522 } else {
3523 new_u32[i] = raw_u32[i];
3524 }
3228 }3525 }
3229 3526
3230 if (*btf_log_buf && args.always_log)3527 *ret_size = raw_u32_size;
3231 fprintf(stderr, "\n%s", btf_log_buf);3528 return new_u32;
3232 3529}
3233 attr.prog_type = test->prog_type;
3234 attr.insns = test->insns;
3235 attr.insns_cnt = probe_prog_length(attr.insns);
3236 attr.license = "GPL";
3237 attr.prog_btf_fd = btf_fd;
3238 attr.func_info_rec_size = test->func_info_rec_size;
3239 attr.func_info_cnt = test->func_info_cnt;
3240 attr.func_info = test->func_info;
3241 3530
3242 *btf_log_buf = '\0';3531static int test_get_finfo(const struct prog_info_raw_test *test,
3243 prog_fd = bpf_load_program_xattr(&attr, btf_log_buf,3532 int prog_fd)
3244 BTF_LOG_BUF_SIZE);3533{
3245 if (test->expected_prog_load_failure && prog_fd == -1) {3534 struct bpf_prog_info info = {};
3246 err = 0;3535 struct bpf_func_info *finfo;
3247 goto done;3536 __u32 info_len, rec_size, i;
3248 }3537 void *func_info = NULL;
3249 if (CHECK(prog_fd == -1, "invalid prog_id errno:%d", errno)) {3538 int err;
3250 fprintf(stderr, "%s\n", btf_log_buf);
3251 err = -1;
3252 goto done;
3253 }
3254 3539
3255 /* get necessary lens */3540 /* get necessary lens */
3256 info_len = sizeof(struct bpf_prog_info);3541 info_len = sizeof(struct bpf_prog_info);
3257 err = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);3542 err = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);
3258 if (CHECK(err == -1, "invalid get info (1st) errno:%d", errno)) {3543 if (CHECK(err == -1, "invalid get info (1st) errno:%d", errno)) {
3259 fprintf(stderr, "%s\n", btf_log_buf);3544 fprintf(stderr, "%s\n", btf_log_buf);
3260 err = -1;3545 return -1;
3261 goto done;
3262 }3546 }
3263 if (CHECK(info.func_info_cnt != 2,3547 if (CHECK(info.func_info_cnt != test->func_info_cnt,
3264 "incorrect info.func_info_cnt (1st) %d\n",3548 "incorrect info.func_info_cnt (1st) %d",
3265 info.func_info_cnt)) {3549 info.func_info_cnt)) {
3266 err = -1;3550 return -1;
3267 goto done;
3268 }3551 }
3552
3269 rec_size = info.func_info_rec_size;3553 rec_size = info.func_info_rec_size;
3270 if (CHECK(rec_size < 4,3554 if (CHECK(rec_size < 8,
3271 "incorrect info.func_info_rec_size (1st) %d\n", rec_size)) {3555 "incorrect info.func_info_rec_size (1st) %d", rec_size)) {
3272 err = -1;3556 return -1;
3273 goto done;
3274 }3557 }
3275 3558
3559 if (!info.func_info_cnt)
3560 return 0;
3561
3276 func_info = malloc(info.func_info_cnt * rec_size);3562 func_info = malloc(info.func_info_cnt * rec_size);
3277 if (CHECK(!func_info, "out of memory")) {3563 if (CHECK(!func_info, "out of memory"))
3278 err = -1;3564 return -1;
3279 goto done;
3280 }
3281 3565
3282 /* reset info to only retrieve func_info related data */3566 /* reset info to only retrieve func_info related data */
3283 memset(&info, 0, sizeof(info));3567 memset(&info, 0, sizeof(info));
3284 info.func_info_cnt = 2;3568 info.func_info_cnt = test->func_info_cnt;
3285 info.func_info_rec_size = rec_size;3569 info.func_info_rec_size = rec_size;
3286 info.func_info = ptr_to_u64(func_info);3570 info.func_info = ptr_to_u64(func_info);
3287 err = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);3571 err = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);
@@ -3290,14 +3574,14 @@ static int do_test_func_type(int test_num) · 2 unmodified lines
3290 err = -1;3574 err = -1;
3291 goto done;3575 goto done;
3292 }3576 }
3293 if (CHECK(info.func_info_cnt != 2,3577 if (CHECK(info.func_info_cnt != test->func_info_cnt,
3294 "incorrect info.func_info_cnt (2nd) %d\n",3578 "incorrect info.func_info_cnt (2nd) %d",
3295 info.func_info_cnt)) {3579 info.func_info_cnt)) {
3296 err = -1;3580 err = -1;
3297 goto done;3581 goto done;
3298 }3582 }
3299 if (CHECK(info.func_info_rec_size != rec_size,3583 if (CHECK(info.func_info_rec_size < 8,
3300 "incorrect info.func_info_rec_size (2nd) %d\n",3584 "incorrect info.func_info_rec_size (2nd) %d",
3301 info.func_info_rec_size)) {3585 info.func_info_rec_size)) {
3302 err = -1;3586 err = -1;
3303 goto done;3587 goto done;
@@ -3310,7 +3594,7 @@ static int do_test_func_type(int test_num) · 6 unmodified lines
3310 }3594 }
3311 3595
3312 finfo = func_info;3596 finfo = func_info;
3313 for (i = 0; i < 2; i++) {3597 for (i = 0; i < test->func_info_cnt; i++) {
3314 if (CHECK(finfo->type_id != test->func_info[i][1],3598 if (CHECK(finfo->type_id != test->func_info[i][1],
3315 "incorrect func_type %u expected %u",3599 "incorrect func_type %u expected %u",
3316 finfo->type_id, test->func_info[i][1])) {3600 finfo->type_id, test->func_info[i][1])) {
@@ -3320,7 +3604,307 @@ static int do_test_func_type(int test_num) · 3 unmodified lines
3320 finfo = (void *)finfo + rec_size;3604 finfo = (void *)finfo + rec_size;
3321 }3605 }
3322 3606
3607 err = 0;
3608
3609done:
3610 free(func_info);
3611 return err;
3612}
3613
3614static int test_get_linfo(const struct prog_info_raw_test *test,
3615 const void *patched_linfo,
3616 __u32 cnt, int prog_fd)
3617{
3618 __u32 i, info_len, nr_jited_ksyms, nr_jited_func_lens;
3619 __u64 *jited_linfo = NULL, *jited_ksyms = NULL;
3620 __u32 rec_size, jited_rec_size, jited_cnt;
3621 struct bpf_line_info *linfo = NULL;
3622 __u32 cur_func_len, ksyms_found;
3623 struct bpf_prog_info info = {};
3624 __u32 *jited_func_lens = NULL;
3625 __u64 cur_func_ksyms;
3626 int err;
3627
3628 jited_cnt = cnt;
3629 rec_size = sizeof(*linfo);
3630 jited_rec_size = sizeof(*jited_linfo);
3631 if (test->nr_jited_ksyms)
3632 nr_jited_ksyms = test->nr_jited_ksyms;
3633 else
3634 nr_jited_ksyms = test->func_info_cnt;
3635 nr_jited_func_lens = nr_jited_ksyms;
3636
3637 info_len = sizeof(struct bpf_prog_info);
3638 err = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);
3639 if (CHECK(err == -1, "err:%d errno:%d", err, errno)) {
3640 err = -1;
3641 goto done;
3642 }
3643
3644 if (!info.jited_prog_len) {
3645 /* prog is not jited */
3646 jited_cnt = 0;
3647 nr_jited_ksyms = 1;
3648 nr_jited_func_lens = 1;
3649 }
3650
3651 if (CHECK(info.line_info_cnt != cnt ||
3652 info.jited_line_info_cnt != jited_cnt ||
3653 info.nr_jited_ksyms != nr_jited_ksyms ||
3654 info.nr_jited_func_lens != nr_jited_func_lens ||
3655 (!info.line_info_cnt && info.jited_line_info_cnt),
3656 "info: line_info_cnt:%u(expected:%u) jited_line_info_cnt:%u(expected:%u) nr_jited_ksyms:%u(expected:%u) nr_jited_func_lens:%u(expected:%u)",
3657 info.line_info_cnt, cnt,
3658 info.jited_line_info_cnt, jited_cnt,
3659 info.nr_jited_ksyms, nr_jited_ksyms,
3660 info.nr_jited_func_lens, nr_jited_func_lens)) {
3661 err = -1;
3662 goto done;
3663 }
3664
3665 if (CHECK(info.line_info_rec_size < 16 ||
3666 info.jited_line_info_rec_size < 8,
3667 "info: line_info_rec_size:%u(userspace expected:%u) jited_line_info_rec_size:%u(userspace expected:%u)",
3668 info.line_info_rec_size, rec_size,
3669 info.jited_line_info_rec_size, jited_rec_size)) {
3670 err = -1;
3671 goto done;
3672 }
3673
3674 if (!cnt)
3675 return 0;
3676
3677 rec_size = info.line_info_rec_size;
3678 jited_rec_size = info.jited_line_info_rec_size;
3679
3680 memset(&info, 0, sizeof(info));
3681
3682 linfo = calloc(cnt, rec_size);
3683 if (CHECK(!linfo, "!linfo")) {
3684 err = -1;
3685 goto done;
3686 }
3687 info.line_info_cnt = cnt;
3688 info.line_info_rec_size = rec_size;
3689 info.line_info = ptr_to_u64(linfo);
3690
3691 if (jited_cnt) {
3692 jited_linfo = calloc(jited_cnt, jited_rec_size);
3693 jited_ksyms = calloc(nr_jited_ksyms, sizeof(*jited_ksyms));
3694 jited_func_lens = calloc(nr_jited_func_lens,
3695 sizeof(*jited_func_lens));
3696 if (CHECK(!jited_linfo || !jited_ksyms || !jited_func_lens,
3697 "jited_linfo:%p jited_ksyms:%p jited_func_lens:%p",
3698 jited_linfo, jited_ksyms, jited_func_lens)) {
3699 err = -1;
3700 goto done;
3701 }
3702
3703 info.jited_line_info_cnt = jited_cnt;
3704 info.jited_line_info_rec_size = jited_rec_size;
3705 info.jited_line_info = ptr_to_u64(jited_linfo);
3706 info.nr_jited_ksyms = nr_jited_ksyms;
3707 info.jited_ksyms = ptr_to_u64(jited_ksyms);
3708 info.nr_jited_func_lens = nr_jited_func_lens;
3709 info.jited_func_lens = ptr_to_u64(jited_func_lens);
3710 }
3711
3712 err = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);
3713
3714 /*
3715 * Only recheck the info.*line_info* fields.
3716 * Other fields are not the concern of this test.
3717 */
3718 if (CHECK(err == -1 ||
3719 !info.line_info ||
3720 info.line_info_cnt != cnt ||
3721 (jited_cnt && !info.jited_line_info) ||
3722 info.jited_line_info_cnt != jited_cnt ||
3723 info.line_info_rec_size != rec_size ||
3724 info.jited_line_info_rec_size != jited_rec_size,
3725 "err:%d errno:%d info: line_info_cnt:%u(expected:%u) jited_line_info_cnt:%u(expected:%u) line_info_rec_size:%u(expected:%u) jited_linfo_rec_size:%u(expected:%u) line_info:%p jited_line_info:%p",
3726 err, errno,
3727 info.line_info_cnt, cnt,
3728 info.jited_line_info_cnt, jited_cnt,
3729 info.line_info_rec_size, rec_size,
3730 info.jited_line_info_rec_size, jited_rec_size,
3731 (void *)(long)info.line_info,
3732 (void *)(long)info.jited_line_info)) {
3733 err = -1;
3734 goto done;
3735 }
3736
3737 CHECK(linfo[0].insn_off, "linfo[0].insn_off:%u",
3738 linfo[0].insn_off);
3739 for (i = 1; i < cnt; i++) {
3740 const struct bpf_line_info *expected_linfo;
3741
3742 expected_linfo = patched_linfo + (i * test->line_info_rec_size);
3743 if (CHECK(linfo[i].insn_off <= linfo[i - 1].insn_off,
3744 "linfo[%u].insn_off:%u <= linfo[%u].insn_off:%u",
3745 i, linfo[i].insn_off,
3746 i - 1, linfo[i - 1].insn_off)) {
3747 err = -1;
3748 goto done;
3749 }
3750 if (CHECK(linfo[i].file_name_off != expected_linfo->file_name_off ||
3751 linfo[i].line_off != expected_linfo->line_off ||
3752 linfo[i].line_col != expected_linfo->line_col,
3753 "linfo[%u] (%u, %u, %u) != (%u, %u, %u)", i,
3754 linfo[i].file_name_off,
3755 linfo[i].line_off,
3756 linfo[i].line_col,
3757 expected_linfo->file_name_off,
3758 expected_linfo->line_off,
3759 expected_linfo->line_col)) {
3760 err = -1;
3761 goto done;
3762 }
3763 }
3764
3765 if (!jited_cnt) {
3766 fprintf(stderr, "not jited. skipping jited_line_info check. ");
3767 err = 0;
3768 goto done;
3769 }
3770
3771 if (CHECK(jited_linfo[0] != jited_ksyms[0],
3772 "jited_linfo[0]:%lx != jited_ksyms[0]:%lx",
3773 (long)(jited_linfo[0]), (long)(jited_ksyms[0]))) {
3774 err = -1;
3775 goto done;
3776 }
3777
3778 ksyms_found = 1;
3779 cur_func_len = jited_func_lens[0];
3780 cur_func_ksyms = jited_ksyms[0];
3781 for (i = 1; i < jited_cnt; i++) {
3782 if (ksyms_found < nr_jited_ksyms &&
3783 jited_linfo[i] == jited_ksyms[ksyms_found]) {
3784 cur_func_ksyms = jited_ksyms[ksyms_found];
3785 cur_func_len = jited_ksyms[ksyms_found];
3786 ksyms_found++;
3787 continue;
3788 }
3789
3790 if (CHECK(jited_linfo[i] <= jited_linfo[i - 1],
3791 "jited_linfo[%u]:%lx <= jited_linfo[%u]:%lx",
3792 i, (long)jited_linfo[i],
3793 i - 1, (long)(jited_linfo[i - 1]))) {
3794 err = -1;
3795 goto done;
3796 }
3797
3798 if (CHECK(jited_linfo[i] - cur_func_ksyms > cur_func_len,
3799 "jited_linfo[%u]:%lx - %lx > %u",
3800 i, (long)jited_linfo[i], (long)cur_func_ksyms,
3801 cur_func_len)) {
3802 err = -1;
3803 goto done;
3804 }
3805 }
3806
3807 if (CHECK(ksyms_found != nr_jited_ksyms,
3808 "ksyms_found:%u != nr_jited_ksyms:%u",
3809 ksyms_found, nr_jited_ksyms)) {
3810 err = -1;
3811 goto done;
3812 }
3813
3814 err = 0;
3815
3323done:3816done:
3817 free(linfo);
3818 free(jited_linfo);
3819 free(jited_ksyms);
3820 free(jited_func_lens);
3821 return err;
3822}
3823
3824static int do_test_info_raw(unsigned int test_num)
3825{
3826 const struct prog_info_raw_test *test = &info_raw_tests[test_num - 1];
3827 unsigned int raw_btf_size, linfo_str_off, linfo_size;
3828 int btf_fd = -1, prog_fd = -1, err = 0;
3829 void *raw_btf, *patched_linfo = NULL;
3830 const char *ret_next_str;
3831 union bpf_attr attr = {};
3832
3833 fprintf(stderr, "BTF prog info raw test[%u] (%s): ", test_num, test->descr);
3834 raw_btf = btf_raw_create(&hdr_tmpl, test->raw_types,
3835 test->str_sec, test->str_sec_size,
3836 &raw_btf_size, &ret_next_str);
3837
3838 if (!raw_btf)
3839 return -1;
3840
3841 *btf_log_buf = '\0';
3842 btf_fd = bpf_load_btf(raw_btf, raw_btf_size,
3843 btf_log_buf, BTF_LOG_BUF_SIZE,
3844 args.always_log);
3845 free(raw_btf);
3846
3847 if (CHECK(btf_fd == -1, "invalid btf_fd errno:%d", errno)) {
3848 err = -1;
3849 goto done;
3850 }
3851
3852 if (*btf_log_buf && args.always_log)
3853 fprintf(stderr, "\n%s", btf_log_buf);
3854 *btf_log_buf = '\0';
3855
3856 linfo_str_off = ret_next_str - test->str_sec;
3857 patched_linfo = patch_name_tbd(test->line_info,
3858 test->str_sec, linfo_str_off,
3859 test->str_sec_size, &linfo_size);
3860 if (IS_ERR(patched_linfo)) {
3861 fprintf(stderr, "error in creating raw bpf_line_info");
3862 err = -1;
3863 goto done;
3864 }
3865
3866 attr.prog_type = test->prog_type;
3867 attr.insns = ptr_to_u64(test->insns);
3868 attr.insn_cnt = probe_prog_length(test->insns);
3869 attr.license = ptr_to_u64("GPL");
3870 attr.prog_btf_fd = btf_fd;
3871 attr.func_info_rec_size = test->func_info_rec_size;
3872 attr.func_info_cnt = test->func_info_cnt;
3873 attr.func_info = ptr_to_u64(test->func_info);
3874 attr.log_buf = ptr_to_u64(btf_log_buf);
3875 attr.log_size = BTF_LOG_BUF_SIZE;
3876 attr.log_level = 1;
3877 if (linfo_size) {
3878 attr.line_info_rec_size = test->line_info_rec_size;
3879 attr.line_info = ptr_to_u64(patched_linfo);
3880 attr.line_info_cnt = linfo_size / attr.line_info_rec_size;
3881 }
3882
3883 prog_fd = syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr));
3884 err = ((prog_fd == -1) != test->expected_prog_load_failure);
3885 if (CHECK(err, "prog_fd:%d expected_prog_load_failure:%u errno:%d",
3886 prog_fd, test->expected_prog_load_failure, errno) ||
3887 CHECK(test->err_str && !strstr(btf_log_buf, test->err_str),
3888 "expected err_str:%s", test->err_str)) {
3889 err = -1;
3890 goto done;
3891 }
3892
3893 if (prog_fd == -1)
3894 goto done;
3895
3896 err = test_get_finfo(test, prog_fd);
3897 if (err)
3898 goto done;
3899
3900 err = test_get_linfo(test, patched_linfo, attr.line_info_cnt, prog_fd);
3901 if (err)
3902 goto done;
3903
3904done:
3905 if (!err)
3906 fprintf(stderr, "OK");
3907
3324 if (*btf_log_buf && (err || args.always_log))3908 if (*btf_log_buf && (err || args.always_log))
3325 fprintf(stderr, "\n%s", btf_log_buf);3909 fprintf(stderr, "\n%s", btf_log_buf);
3326 3910
@@ -3328,33 +3912,41 @@ done: · 1 unmodified line
3328 close(btf_fd);3912 close(btf_fd);
3329 if (prog_fd != -1)3913 if (prog_fd != -1)
3330 close(prog_fd);3914 close(prog_fd);
3331 free(func_info);3915
3916 if (!IS_ERR(patched_linfo))
3917 free(patched_linfo);
3918
3332 return err;3919 return err;
3333}3920}
3334 3921
3335static int test_func_type(void)3922static int test_info_raw(void)
3336{3923{
3337 unsigned int i;3924 unsigned int i;
3338 int err = 0;3925 int err = 0;
3339 3926
3340 for (i = 0; i < ARRAY_SIZE(func_type_test); i++)3927 if (args.info_raw_test_num)
3341 err |= count_result(do_test_func_type(i));3928 return count_result(do_test_info_raw(args.info_raw_test_num));
3929
3930 for (i = 1; i <= ARRAY_SIZE(info_raw_tests); i++)
3931 err |= count_result(do_test_info_raw(i));
3342 3932
3343 return err;3933 return err;
3344}3934}
3345 3935
3346static void usage(const char *cmd)3936static void usage(const char *cmd)
3347{3937{
3348 fprintf(stderr, "Usage: %s [-l] [[-r test_num (1 - %zu)] |"3938 fprintf(stderr, "Usage: %s [-l] [[-r btf_raw_test_num (1 - %zu)] |\n"
3349 " [-g test_num (1 - %zu)] |"3939 "\t[-g btf_get_info_test_num (1 - %zu)] |\n"
3350 " [-f test_num (1 - %zu)] | [-p] | [-k] ]\n",3940 "\t[-f btf_file_test_num (1 - %zu)] |\n"
3941 "\t[-k btf_prog_info_raw_test_num (1 - %zu)] |\n"
3942 "\t[-p (pretty print test)]]\n",
3351 cmd, ARRAY_SIZE(raw_tests), ARRAY_SIZE(get_info_tests),3943 cmd, ARRAY_SIZE(raw_tests), ARRAY_SIZE(get_info_tests),
3352 ARRAY_SIZE(file_tests));3944 ARRAY_SIZE(file_tests), ARRAY_SIZE(info_raw_tests));
3353}3945}
3354 3946
3355static int parse_args(int argc, char **argv)3947static int parse_args(int argc, char **argv)
3356{3948{
3357 const char *optstr = "lpkf:r:g:";3949 const char *optstr = "lpk:f:r:g:";
3358 int opt;3950 int opt;
3359 3951
3360 while ((opt = getopt(argc, argv, optstr)) != -1) {3952 while ((opt = getopt(argc, argv, optstr)) != -1) {
@@ -3378,7 +3970,8 @@ static int parse_args(int argc, char **argv) · 17 unmodified lines
3378 args.pprint_test = true;3970 args.pprint_test = true;
3379 break;3971 break;
3380 case 'k':3972 case 'k':
3381 args.func_type_test = true;3973 args.info_raw_test_num = atoi(optarg);
3974 args.info_raw_test = true;
3382 break;3975 break;
3383 case 'h':3976 case 'h':
3384 usage(argv[0]);3977 usage(argv[0]);
@@ -3413,6 +4006,14 @@ static int parse_args(int argc, char **argv) · 28 unmodified lines
3413 return -1;4006 return -1;
3414 }4007 }
3415 4008
4009 if (args.info_raw_test_num &&
4010 (args.info_raw_test_num < 1 ||
4011 args.info_raw_test_num > ARRAY_SIZE(info_raw_tests))) {
4012 fprintf(stderr, "BTF prog info raw test number must be [1 - %zu]\n",
4013 ARRAY_SIZE(info_raw_tests));
4014 return -1;
4015 }
4016
3416 return 0;4017 return 0;
3417}4018}
3418 4019
@@ -3445,16 +4046,17 @@ int main(int argc, char **argv) · 26 unmodified lines
3445 if (args.pprint_test)4046 if (args.pprint_test)
3446 err |= test_pprint();4047 err |= test_pprint();
3447 4048
3448 if (args.func_type_test)4049 if (args.info_raw_test)
3449 err |= test_func_type();4050 err |= test_info_raw();
3450 4051
3451 if (args.raw_test || args.get_info_test || args.file_test ||4052 if (args.raw_test || args.get_info_test || args.file_test ||
3452 args.pprint_test || args.func_type_test)4053 args.pprint_test || args.info_raw_test)
3453 goto done;4054 goto done;
3454 4055
3455 err |= test_raw();4056 err |= test_raw();
3456 err |= test_get_info();4057 err |= test_get_info();
3457 err |= test_file();4058 err |= test_file();
4059 err |= test_info_raw();
3458 4060
3459done:4061done:
3460 print_summary();4062 print_summary();

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t