forked from mirrors/linux
		
	tools/bpf: bpftool: add support for func types
This patch added support to print function signature
if btf func_info is available. Note that ksym
now uses function name instead of prog_name as
prog_name has a limit of 16 bytes including
ending '\0'.
The following is a sample output for selftests
test_btf with file test_btf_haskv.o for translated insns
and jited insns respectively.
  $ bpftool prog dump xlated id 1
  int _dummy_tracepoint(struct dummy_tracepoint_args * arg):
     0: (85) call pc+2#bpf_prog_2dcecc18072623fc_test_long_fname_1
     1: (b7) r0 = 0
     2: (95) exit
  int test_long_fname_1(struct dummy_tracepoint_args * arg):
     3: (85) call pc+1#bpf_prog_89d64e4abf0f0126_test_long_fname_2
     4: (95) exit
  int test_long_fname_2(struct dummy_tracepoint_args * arg):
     5: (b7) r2 = 0
     6: (63) *(u32 *)(r10 -4) = r2
     7: (79) r1 = *(u64 *)(r1 +8)
     ...
     22: (07) r1 += 1
     23: (63) *(u32 *)(r0 +4) = r1
     24: (95) exit
  $ bpftool prog dump jited id 1
  int _dummy_tracepoint(struct dummy_tracepoint_args * arg):
  bpf_prog_b07ccb89267cf242__dummy_tracepoint:
     0:   push   %rbp
     1:   mov    %rsp,%rbp
    ......
    3c:   add    $0x28,%rbp
    40:   leaveq
    41:   retq
  int test_long_fname_1(struct dummy_tracepoint_args * arg):
  bpf_prog_2dcecc18072623fc_test_long_fname_1:
     0:   push   %rbp
     1:   mov    %rsp,%rbp
    ......
    3a:   add    $0x28,%rbp
    3e:   leaveq
    3f:   retq
  int test_long_fname_2(struct dummy_tracepoint_args * arg):
  bpf_prog_89d64e4abf0f0126_test_long_fname_2:
     0:   push   %rbp
     1:   mov    %rsp,%rbp
    ......
    80:   add    $0x28,%rbp
    84:   leaveq
    85:   retq
Signed-off-by: Yonghong Song <yhs@fb.com>
Signed-off-by: Martin KaFai Lau <kafai@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
			
			
This commit is contained in:
		
							parent
							
								
									999d82cbc0
								
							
						
					
					
						commit
						254471e57a
					
				
					 5 changed files with 230 additions and 0 deletions
				
			
		| 
						 | 
					@ -249,3 +249,139 @@ int btf_dumper_type(const struct btf_dumper *d, __u32 type_id,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return btf_dumper_do_type(d, type_id, 0, data);
 | 
						return btf_dumper_do_type(d, type_id, 0, data);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define BTF_PRINT_ARG(...)						\
 | 
				
			||||||
 | 
						do {								\
 | 
				
			||||||
 | 
							pos += snprintf(func_sig + pos, size - pos,		\
 | 
				
			||||||
 | 
									__VA_ARGS__);				\
 | 
				
			||||||
 | 
							if (pos >= size)					\
 | 
				
			||||||
 | 
								return -1;					\
 | 
				
			||||||
 | 
						} while (0)
 | 
				
			||||||
 | 
					#define BTF_PRINT_TYPE(type)					\
 | 
				
			||||||
 | 
						do {								\
 | 
				
			||||||
 | 
							pos = __btf_dumper_type_only(btf, type, func_sig,	\
 | 
				
			||||||
 | 
										     pos, size);		\
 | 
				
			||||||
 | 
							if (pos == -1)						\
 | 
				
			||||||
 | 
								return -1;					\
 | 
				
			||||||
 | 
						} while (0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int btf_dump_func(const struct btf *btf, char *func_sig,
 | 
				
			||||||
 | 
								 const struct btf_type *func_proto,
 | 
				
			||||||
 | 
								 const struct btf_type *func, int pos, int size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int __btf_dumper_type_only(const struct btf *btf, __u32 type_id,
 | 
				
			||||||
 | 
									  char *func_sig, int pos, int size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const struct btf_type *proto_type;
 | 
				
			||||||
 | 
						const struct btf_array *array;
 | 
				
			||||||
 | 
						const struct btf_type *t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!type_id) {
 | 
				
			||||||
 | 
							BTF_PRINT_ARG("void ");
 | 
				
			||||||
 | 
							return pos;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						t = btf__type_by_id(btf, type_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (BTF_INFO_KIND(t->info)) {
 | 
				
			||||||
 | 
						case BTF_KIND_INT:
 | 
				
			||||||
 | 
							BTF_PRINT_ARG("%s ", btf__name_by_offset(btf, t->name_off));
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case BTF_KIND_STRUCT:
 | 
				
			||||||
 | 
							BTF_PRINT_ARG("struct %s ",
 | 
				
			||||||
 | 
								      btf__name_by_offset(btf, t->name_off));
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case BTF_KIND_UNION:
 | 
				
			||||||
 | 
							BTF_PRINT_ARG("union %s ",
 | 
				
			||||||
 | 
								      btf__name_by_offset(btf, t->name_off));
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case BTF_KIND_ENUM:
 | 
				
			||||||
 | 
							BTF_PRINT_ARG("enum %s ",
 | 
				
			||||||
 | 
								      btf__name_by_offset(btf, t->name_off));
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case BTF_KIND_ARRAY:
 | 
				
			||||||
 | 
							array = (struct btf_array *)(t + 1);
 | 
				
			||||||
 | 
							BTF_PRINT_TYPE(array->type);
 | 
				
			||||||
 | 
							BTF_PRINT_ARG("[%d]", array->nelems);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case BTF_KIND_PTR:
 | 
				
			||||||
 | 
							BTF_PRINT_TYPE(t->type);
 | 
				
			||||||
 | 
							BTF_PRINT_ARG("* ");
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case BTF_KIND_UNKN:
 | 
				
			||||||
 | 
						case BTF_KIND_FWD:
 | 
				
			||||||
 | 
						case BTF_KIND_TYPEDEF:
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						case BTF_KIND_VOLATILE:
 | 
				
			||||||
 | 
							BTF_PRINT_ARG("volatile ");
 | 
				
			||||||
 | 
							BTF_PRINT_TYPE(t->type);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case BTF_KIND_CONST:
 | 
				
			||||||
 | 
							BTF_PRINT_ARG("const ");
 | 
				
			||||||
 | 
							BTF_PRINT_TYPE(t->type);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case BTF_KIND_RESTRICT:
 | 
				
			||||||
 | 
							BTF_PRINT_ARG("restrict ");
 | 
				
			||||||
 | 
							BTF_PRINT_TYPE(t->type);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case BTF_KIND_FUNC_PROTO:
 | 
				
			||||||
 | 
							pos = btf_dump_func(btf, func_sig, t, NULL, pos, size);
 | 
				
			||||||
 | 
							if (pos == -1)
 | 
				
			||||||
 | 
								return -1;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case BTF_KIND_FUNC:
 | 
				
			||||||
 | 
							proto_type = btf__type_by_id(btf, t->type);
 | 
				
			||||||
 | 
							pos = btf_dump_func(btf, func_sig, proto_type, t, pos, size);
 | 
				
			||||||
 | 
							if (pos == -1)
 | 
				
			||||||
 | 
								return -1;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return pos;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int btf_dump_func(const struct btf *btf, char *func_sig,
 | 
				
			||||||
 | 
								 const struct btf_type *func_proto,
 | 
				
			||||||
 | 
								 const struct btf_type *func, int pos, int size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i, vlen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						BTF_PRINT_TYPE(func_proto->type);
 | 
				
			||||||
 | 
						if (func)
 | 
				
			||||||
 | 
							BTF_PRINT_ARG("%s(", btf__name_by_offset(btf, func->name_off));
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							BTF_PRINT_ARG("(");
 | 
				
			||||||
 | 
						vlen = BTF_INFO_VLEN(func_proto->info);
 | 
				
			||||||
 | 
						for (i = 0; i < vlen; i++) {
 | 
				
			||||||
 | 
							struct btf_param *arg = &((struct btf_param *)(func_proto + 1))[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (i)
 | 
				
			||||||
 | 
								BTF_PRINT_ARG(", ");
 | 
				
			||||||
 | 
							if (arg->type) {
 | 
				
			||||||
 | 
								BTF_PRINT_TYPE(arg->type);
 | 
				
			||||||
 | 
								BTF_PRINT_ARG("%s",
 | 
				
			||||||
 | 
									      btf__name_by_offset(btf, arg->name_off));
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								BTF_PRINT_ARG("...");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						BTF_PRINT_ARG(")");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return pos;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void btf_dumper_type_only(const struct btf *btf, __u32 type_id, char *func_sig,
 | 
				
			||||||
 | 
								  int size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						func_sig[0] = '\0';
 | 
				
			||||||
 | 
						if (!btf)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = __btf_dumper_type_only(btf, type_id, func_sig, 0, size);
 | 
				
			||||||
 | 
						if (err < 0)
 | 
				
			||||||
 | 
							func_sig[0] = '\0';
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -187,6 +187,8 @@ struct btf_dumper {
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int btf_dumper_type(const struct btf_dumper *d, __u32 type_id,
 | 
					int btf_dumper_type(const struct btf_dumper *d, __u32 type_id,
 | 
				
			||||||
		    const void *data);
 | 
							    const void *data);
 | 
				
			||||||
 | 
					void btf_dumper_type_only(const struct btf *btf, __u32 func_type_id,
 | 
				
			||||||
 | 
								  char *func_only, int size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct nlattr;
 | 
					struct nlattr;
 | 
				
			||||||
struct ifinfomsg;
 | 
					struct ifinfomsg;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -47,6 +47,7 @@
 | 
				
			||||||
#include <linux/err.h>
 | 
					#include <linux/err.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <bpf.h>
 | 
					#include <bpf.h>
 | 
				
			||||||
 | 
					#include <btf.h>
 | 
				
			||||||
#include <libbpf.h>
 | 
					#include <libbpf.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "cfg.h"
 | 
					#include "cfg.h"
 | 
				
			||||||
| 
						 | 
					@ -451,14 +452,19 @@ static int do_dump(int argc, char **argv)
 | 
				
			||||||
	struct bpf_prog_info info = {};
 | 
						struct bpf_prog_info info = {};
 | 
				
			||||||
	unsigned int *func_lens = NULL;
 | 
						unsigned int *func_lens = NULL;
 | 
				
			||||||
	const char *disasm_opt = NULL;
 | 
						const char *disasm_opt = NULL;
 | 
				
			||||||
 | 
						unsigned int finfo_rec_size;
 | 
				
			||||||
	unsigned int nr_func_ksyms;
 | 
						unsigned int nr_func_ksyms;
 | 
				
			||||||
	unsigned int nr_func_lens;
 | 
						unsigned int nr_func_lens;
 | 
				
			||||||
	struct dump_data dd = {};
 | 
						struct dump_data dd = {};
 | 
				
			||||||
	__u32 len = sizeof(info);
 | 
						__u32 len = sizeof(info);
 | 
				
			||||||
 | 
						struct btf *btf = NULL;
 | 
				
			||||||
 | 
						void *func_info = NULL;
 | 
				
			||||||
 | 
						unsigned int finfo_cnt;
 | 
				
			||||||
	unsigned int buf_size;
 | 
						unsigned int buf_size;
 | 
				
			||||||
	char *filepath = NULL;
 | 
						char *filepath = NULL;
 | 
				
			||||||
	bool opcodes = false;
 | 
						bool opcodes = false;
 | 
				
			||||||
	bool visual = false;
 | 
						bool visual = false;
 | 
				
			||||||
 | 
						char func_sig[1024];
 | 
				
			||||||
	unsigned char *buf;
 | 
						unsigned char *buf;
 | 
				
			||||||
	__u32 *member_len;
 | 
						__u32 *member_len;
 | 
				
			||||||
	__u64 *member_ptr;
 | 
						__u64 *member_ptr;
 | 
				
			||||||
| 
						 | 
					@ -551,6 +557,17 @@ static int do_dump(int argc, char **argv)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						finfo_cnt = info.func_info_cnt;
 | 
				
			||||||
 | 
						finfo_rec_size = info.func_info_rec_size;
 | 
				
			||||||
 | 
						if (finfo_cnt && finfo_rec_size) {
 | 
				
			||||||
 | 
							func_info = malloc(finfo_cnt * finfo_rec_size);
 | 
				
			||||||
 | 
							if (!func_info) {
 | 
				
			||||||
 | 
								p_err("mem alloc failed");
 | 
				
			||||||
 | 
								close(fd);
 | 
				
			||||||
 | 
								goto err_free;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	memset(&info, 0, sizeof(info));
 | 
						memset(&info, 0, sizeof(info));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	*member_ptr = ptr_to_u64(buf);
 | 
						*member_ptr = ptr_to_u64(buf);
 | 
				
			||||||
| 
						 | 
					@ -559,6 +576,9 @@ static int do_dump(int argc, char **argv)
 | 
				
			||||||
	info.nr_jited_ksyms = nr_func_ksyms;
 | 
						info.nr_jited_ksyms = nr_func_ksyms;
 | 
				
			||||||
	info.jited_func_lens = ptr_to_u64(func_lens);
 | 
						info.jited_func_lens = ptr_to_u64(func_lens);
 | 
				
			||||||
	info.nr_jited_func_lens = nr_func_lens;
 | 
						info.nr_jited_func_lens = nr_func_lens;
 | 
				
			||||||
 | 
						info.func_info_cnt = finfo_cnt;
 | 
				
			||||||
 | 
						info.func_info_rec_size = finfo_rec_size;
 | 
				
			||||||
 | 
						info.func_info = ptr_to_u64(func_info);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = bpf_obj_get_info_by_fd(fd, &info, &len);
 | 
						err = bpf_obj_get_info_by_fd(fd, &info, &len);
 | 
				
			||||||
	close(fd);
 | 
						close(fd);
 | 
				
			||||||
| 
						 | 
					@ -582,6 +602,18 @@ static int do_dump(int argc, char **argv)
 | 
				
			||||||
		goto err_free;
 | 
							goto err_free;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (info.func_info_cnt != finfo_cnt) {
 | 
				
			||||||
 | 
							p_err("incorrect func_info_cnt %d vs. expected %d",
 | 
				
			||||||
 | 
							      info.func_info_cnt, finfo_cnt);
 | 
				
			||||||
 | 
							goto err_free;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (info.func_info_rec_size != finfo_rec_size) {
 | 
				
			||||||
 | 
							p_err("incorrect func_info_rec_size %d vs. expected %d",
 | 
				
			||||||
 | 
							      info.func_info_rec_size, finfo_rec_size);
 | 
				
			||||||
 | 
							goto err_free;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((member_len == &info.jited_prog_len &&
 | 
						if ((member_len == &info.jited_prog_len &&
 | 
				
			||||||
	     info.jited_prog_insns == 0) ||
 | 
						     info.jited_prog_insns == 0) ||
 | 
				
			||||||
	    (member_len == &info.xlated_prog_len &&
 | 
						    (member_len == &info.xlated_prog_len &&
 | 
				
			||||||
| 
						 | 
					@ -590,6 +622,11 @@ static int do_dump(int argc, char **argv)
 | 
				
			||||||
		goto err_free;
 | 
							goto err_free;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (info.btf_id && btf_get_from_id(info.btf_id, &btf)) {
 | 
				
			||||||
 | 
							p_err("failed to get btf");
 | 
				
			||||||
 | 
							goto err_free;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (filepath) {
 | 
						if (filepath) {
 | 
				
			||||||
		fd = open(filepath, O_WRONLY | O_CREAT | O_TRUNC, 0600);
 | 
							fd = open(filepath, O_WRONLY | O_CREAT | O_TRUNC, 0600);
 | 
				
			||||||
		if (fd < 0) {
 | 
							if (fd < 0) {
 | 
				
			||||||
| 
						 | 
					@ -622,6 +659,7 @@ static int do_dump(int argc, char **argv)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (info.nr_jited_func_lens && info.jited_func_lens) {
 | 
							if (info.nr_jited_func_lens && info.jited_func_lens) {
 | 
				
			||||||
			struct kernel_sym *sym = NULL;
 | 
								struct kernel_sym *sym = NULL;
 | 
				
			||||||
 | 
								struct bpf_func_info *record;
 | 
				
			||||||
			char sym_name[SYM_MAX_NAME];
 | 
								char sym_name[SYM_MAX_NAME];
 | 
				
			||||||
			unsigned char *img = buf;
 | 
								unsigned char *img = buf;
 | 
				
			||||||
			__u64 *ksyms = NULL;
 | 
								__u64 *ksyms = NULL;
 | 
				
			||||||
| 
						 | 
					@ -648,12 +686,25 @@ static int do_dump(int argc, char **argv)
 | 
				
			||||||
					strcpy(sym_name, "unknown");
 | 
										strcpy(sym_name, "unknown");
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (func_info) {
 | 
				
			||||||
 | 
										record = func_info + i * finfo_rec_size;
 | 
				
			||||||
 | 
										btf_dumper_type_only(btf, record->type_id,
 | 
				
			||||||
 | 
												     func_sig,
 | 
				
			||||||
 | 
												     sizeof(func_sig));
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if (json_output) {
 | 
									if (json_output) {
 | 
				
			||||||
					jsonw_start_object(json_wtr);
 | 
										jsonw_start_object(json_wtr);
 | 
				
			||||||
 | 
										if (func_info && func_sig[0] != '\0') {
 | 
				
			||||||
 | 
											jsonw_name(json_wtr, "proto");
 | 
				
			||||||
 | 
											jsonw_string(json_wtr, func_sig);
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
					jsonw_name(json_wtr, "name");
 | 
										jsonw_name(json_wtr, "name");
 | 
				
			||||||
					jsonw_string(json_wtr, sym_name);
 | 
										jsonw_string(json_wtr, sym_name);
 | 
				
			||||||
					jsonw_name(json_wtr, "insns");
 | 
										jsonw_name(json_wtr, "insns");
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
 | 
										if (func_info && func_sig[0] != '\0')
 | 
				
			||||||
 | 
											printf("%s:\n", func_sig);
 | 
				
			||||||
					printf("%s:\n", sym_name);
 | 
										printf("%s:\n", sym_name);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -682,6 +733,9 @@ static int do_dump(int argc, char **argv)
 | 
				
			||||||
		kernel_syms_load(&dd);
 | 
							kernel_syms_load(&dd);
 | 
				
			||||||
		dd.nr_jited_ksyms = info.nr_jited_ksyms;
 | 
							dd.nr_jited_ksyms = info.nr_jited_ksyms;
 | 
				
			||||||
		dd.jited_ksyms = (__u64 *) info.jited_ksyms;
 | 
							dd.jited_ksyms = (__u64 *) info.jited_ksyms;
 | 
				
			||||||
 | 
							dd.btf = btf;
 | 
				
			||||||
 | 
							dd.func_info = func_info;
 | 
				
			||||||
 | 
							dd.finfo_rec_size = finfo_rec_size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (json_output)
 | 
							if (json_output)
 | 
				
			||||||
			dump_xlated_json(&dd, buf, *member_len, opcodes);
 | 
								dump_xlated_json(&dd, buf, *member_len, opcodes);
 | 
				
			||||||
| 
						 | 
					@ -693,12 +747,14 @@ static int do_dump(int argc, char **argv)
 | 
				
			||||||
	free(buf);
 | 
						free(buf);
 | 
				
			||||||
	free(func_ksyms);
 | 
						free(func_ksyms);
 | 
				
			||||||
	free(func_lens);
 | 
						free(func_lens);
 | 
				
			||||||
 | 
						free(func_info);
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
err_free:
 | 
					err_free:
 | 
				
			||||||
	free(buf);
 | 
						free(buf);
 | 
				
			||||||
	free(func_ksyms);
 | 
						free(func_ksyms);
 | 
				
			||||||
	free(func_lens);
 | 
						free(func_lens);
 | 
				
			||||||
 | 
						free(func_info);
 | 
				
			||||||
	return -1;
 | 
						return -1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -242,11 +242,15 @@ void dump_xlated_json(struct dump_data *dd, void *buf, unsigned int len,
 | 
				
			||||||
		.cb_imm		= print_imm,
 | 
							.cb_imm		= print_imm,
 | 
				
			||||||
		.private_data	= dd,
 | 
							.private_data	= dd,
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
						struct bpf_func_info *record;
 | 
				
			||||||
	struct bpf_insn *insn = buf;
 | 
						struct bpf_insn *insn = buf;
 | 
				
			||||||
 | 
						struct btf *btf = dd->btf;
 | 
				
			||||||
	bool double_insn = false;
 | 
						bool double_insn = false;
 | 
				
			||||||
 | 
						char func_sig[1024];
 | 
				
			||||||
	unsigned int i;
 | 
						unsigned int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	jsonw_start_array(json_wtr);
 | 
						jsonw_start_array(json_wtr);
 | 
				
			||||||
 | 
						record = dd->func_info;
 | 
				
			||||||
	for (i = 0; i < len / sizeof(*insn); i++) {
 | 
						for (i = 0; i < len / sizeof(*insn); i++) {
 | 
				
			||||||
		if (double_insn) {
 | 
							if (double_insn) {
 | 
				
			||||||
			double_insn = false;
 | 
								double_insn = false;
 | 
				
			||||||
| 
						 | 
					@ -255,6 +259,20 @@ void dump_xlated_json(struct dump_data *dd, void *buf, unsigned int len,
 | 
				
			||||||
		double_insn = insn[i].code == (BPF_LD | BPF_IMM | BPF_DW);
 | 
							double_insn = insn[i].code == (BPF_LD | BPF_IMM | BPF_DW);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		jsonw_start_object(json_wtr);
 | 
							jsonw_start_object(json_wtr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (btf && record) {
 | 
				
			||||||
 | 
								if (record->insn_offset == i) {
 | 
				
			||||||
 | 
									btf_dumper_type_only(btf, record->type_id,
 | 
				
			||||||
 | 
											     func_sig,
 | 
				
			||||||
 | 
											     sizeof(func_sig));
 | 
				
			||||||
 | 
									if (func_sig[0] != '\0') {
 | 
				
			||||||
 | 
										jsonw_name(json_wtr, "proto");
 | 
				
			||||||
 | 
										jsonw_string(json_wtr, func_sig);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									record = (void *)record + dd->finfo_rec_size;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		jsonw_name(json_wtr, "disasm");
 | 
							jsonw_name(json_wtr, "disasm");
 | 
				
			||||||
		print_bpf_insn(&cbs, insn + i, true);
 | 
							print_bpf_insn(&cbs, insn + i, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -297,16 +315,31 @@ void dump_xlated_plain(struct dump_data *dd, void *buf, unsigned int len,
 | 
				
			||||||
		.cb_imm		= print_imm,
 | 
							.cb_imm		= print_imm,
 | 
				
			||||||
		.private_data	= dd,
 | 
							.private_data	= dd,
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
						struct bpf_func_info *record;
 | 
				
			||||||
	struct bpf_insn *insn = buf;
 | 
						struct bpf_insn *insn = buf;
 | 
				
			||||||
 | 
						struct btf *btf = dd->btf;
 | 
				
			||||||
	bool double_insn = false;
 | 
						bool double_insn = false;
 | 
				
			||||||
 | 
						char func_sig[1024];
 | 
				
			||||||
	unsigned int i;
 | 
						unsigned int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						record = dd->func_info;
 | 
				
			||||||
	for (i = 0; i < len / sizeof(*insn); i++) {
 | 
						for (i = 0; i < len / sizeof(*insn); i++) {
 | 
				
			||||||
		if (double_insn) {
 | 
							if (double_insn) {
 | 
				
			||||||
			double_insn = false;
 | 
								double_insn = false;
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (btf && record) {
 | 
				
			||||||
 | 
								if (record->insn_offset == i) {
 | 
				
			||||||
 | 
									btf_dumper_type_only(btf, record->type_id,
 | 
				
			||||||
 | 
											     func_sig,
 | 
				
			||||||
 | 
											     sizeof(func_sig));
 | 
				
			||||||
 | 
									if (func_sig[0] != '\0')
 | 
				
			||||||
 | 
										printf("%s:\n", func_sig);
 | 
				
			||||||
 | 
									record = (void *)record + dd->finfo_rec_size;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		double_insn = insn[i].code == (BPF_LD | BPF_IMM | BPF_DW);
 | 
							double_insn = insn[i].code == (BPF_LD | BPF_IMM | BPF_DW);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		printf("% 4d: ", i);
 | 
							printf("% 4d: ", i);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -51,6 +51,9 @@ struct dump_data {
 | 
				
			||||||
	__u32 sym_count;
 | 
						__u32 sym_count;
 | 
				
			||||||
	__u64 *jited_ksyms;
 | 
						__u64 *jited_ksyms;
 | 
				
			||||||
	__u32 nr_jited_ksyms;
 | 
						__u32 nr_jited_ksyms;
 | 
				
			||||||
 | 
						struct btf *btf;
 | 
				
			||||||
 | 
						void *func_info;
 | 
				
			||||||
 | 
						__u32 finfo_rec_size;
 | 
				
			||||||
	char scratch_buff[SYM_MAX_NAME + 8];
 | 
						char scratch_buff[SYM_MAX_NAME + 8];
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue