Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /* Copyright (C) 2018 Netronome Systems, Inc. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4) #define _GNU_SOURCE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5) #include <stdarg.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include <string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <sys/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <bpf/libbpf.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include "disasm.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include "json_writer.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include "main.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include "xlated_dumper.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) static int kernel_syms_cmp(const void *sym_a, const void *sym_b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) 	return ((struct kernel_sym *)sym_a)->address -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 	       ((struct kernel_sym *)sym_b)->address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) void kernel_syms_load(struct dump_data *dd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 	struct kernel_sym *sym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 	char buff[256];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 	void *tmp, *address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	FILE *fp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 	fp = fopen("/proc/kallsyms", "r");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 	if (!fp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	while (fgets(buff, sizeof(buff), fp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 		tmp = reallocarray(dd->sym_mapping, dd->sym_count + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 				   sizeof(*dd->sym_mapping));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 		if (!tmp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 			free(dd->sym_mapping);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 			dd->sym_mapping = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 			fclose(fp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 			return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 		dd->sym_mapping = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 		sym = &dd->sym_mapping[dd->sym_count];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 		if (sscanf(buff, "%p %*c %s", &address, sym->name) != 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 		sym->address = (unsigned long)address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 		if (!strcmp(sym->name, "__bpf_call_base")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 			dd->address_call_base = sym->address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 			/* sysctl kernel.kptr_restrict was set */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 			if (!sym->address)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 				goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 		if (sym->address)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 			dd->sym_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	fclose(fp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	qsort(dd->sym_mapping, dd->sym_count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	      sizeof(*dd->sym_mapping), kernel_syms_cmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) void kernel_syms_destroy(struct dump_data *dd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	free(dd->sym_mapping);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) struct kernel_sym *kernel_syms_search(struct dump_data *dd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 				      unsigned long key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	struct kernel_sym sym = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 		.address = key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	return dd->sym_mapping ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	       bsearch(&sym, dd->sym_mapping, dd->sym_count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 		       sizeof(*dd->sym_mapping), kernel_syms_cmp) : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) static void __printf(2, 3) print_insn(void *private_data, const char *fmt, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	va_list args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	va_start(args, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	vprintf(fmt, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	va_end(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) static void __printf(2, 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) print_insn_for_graph(void *private_data, const char *fmt, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	char buf[64], *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	va_list args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	va_start(args, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	vsnprintf(buf, sizeof(buf), fmt, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	va_end(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	p = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	while (*p != '\0') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 		if (*p == '\n') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 			memmove(p + 3, p, strlen(buf) + 1 - (p - buf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 			/* Align each instruction dump row left. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 			*p++ = '\\';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 			*p++ = 'l';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 			/* Output multiline concatenation. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 			*p++ = '\\';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 		} else if (*p == '<' || *p == '>' || *p == '|' || *p == '&') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 			memmove(p + 1, p, strlen(buf) + 1 - (p - buf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 			/* Escape special character. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 			*p++ = '\\';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 		p++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	printf("%s", buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) static void __printf(2, 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) print_insn_json(void *private_data, const char *fmt, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	unsigned int l = strlen(fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	char chomped_fmt[l];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	va_list args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	va_start(args, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	if (l > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 		strncpy(chomped_fmt, fmt, l - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 		chomped_fmt[l - 1] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	jsonw_vprintf_enquote(json_wtr, chomped_fmt, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	va_end(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) static const char *print_call_pcrel(struct dump_data *dd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 				    struct kernel_sym *sym,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 				    unsigned long address,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 				    const struct bpf_insn *insn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	if (!dd->nr_jited_ksyms)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 		/* Do not show address for interpreted programs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 		snprintf(dd->scratch_buff, sizeof(dd->scratch_buff),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 			"%+d", insn->off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	else if (sym)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 		snprintf(dd->scratch_buff, sizeof(dd->scratch_buff),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 			 "%+d#%s", insn->off, sym->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 		snprintf(dd->scratch_buff, sizeof(dd->scratch_buff),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 			 "%+d#0x%lx", insn->off, address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	return dd->scratch_buff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) static const char *print_call_helper(struct dump_data *dd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 				     struct kernel_sym *sym,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 				     unsigned long address)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	if (sym)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 		snprintf(dd->scratch_buff, sizeof(dd->scratch_buff),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 			 "%s", sym->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 		snprintf(dd->scratch_buff, sizeof(dd->scratch_buff),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 			 "0x%lx", address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	return dd->scratch_buff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) static const char *print_call(void *private_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 			      const struct bpf_insn *insn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	struct dump_data *dd = private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	unsigned long address = dd->address_call_base + insn->imm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	struct kernel_sym *sym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	if (insn->src_reg == BPF_PSEUDO_CALL &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 	    (__u32) insn->imm < dd->nr_jited_ksyms && dd->jited_ksyms)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 		address = dd->jited_ksyms[insn->imm];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	sym = kernel_syms_search(dd, address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	if (insn->src_reg == BPF_PSEUDO_CALL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 		return print_call_pcrel(dd, sym, address, insn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 		return print_call_helper(dd, sym, address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) static const char *print_imm(void *private_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 			     const struct bpf_insn *insn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 			     __u64 full_imm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	struct dump_data *dd = private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	if (insn->src_reg == BPF_PSEUDO_MAP_FD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 		snprintf(dd->scratch_buff, sizeof(dd->scratch_buff),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 			 "map[id:%u]", insn->imm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	else if (insn->src_reg == BPF_PSEUDO_MAP_VALUE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 		snprintf(dd->scratch_buff, sizeof(dd->scratch_buff),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 			 "map[id:%u][0]+%u", insn->imm, (insn + 1)->imm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 		snprintf(dd->scratch_buff, sizeof(dd->scratch_buff),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 			 "0x%llx", (unsigned long long)full_imm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	return dd->scratch_buff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) void dump_xlated_json(struct dump_data *dd, void *buf, unsigned int len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 		      bool opcodes, bool linum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 	const struct bpf_prog_linfo *prog_linfo = dd->prog_linfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 	const struct bpf_insn_cbs cbs = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 		.cb_print	= print_insn_json,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 		.cb_call	= print_call,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 		.cb_imm		= print_imm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 		.private_data	= dd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 	struct bpf_func_info *record;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 	struct bpf_insn *insn = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 	struct btf *btf = dd->btf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 	bool double_insn = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 	unsigned int nr_skip = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	char func_sig[1024];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 	unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 	jsonw_start_array(json_wtr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	record = dd->func_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 	for (i = 0; i < len / sizeof(*insn); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 		if (double_insn) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 			double_insn = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 		double_insn = insn[i].code == (BPF_LD | BPF_IMM | BPF_DW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 		jsonw_start_object(json_wtr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 		if (btf && record) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 			if (record->insn_off == i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 				btf_dumper_type_only(btf, record->type_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 						     func_sig,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 						     sizeof(func_sig));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 				if (func_sig[0] != '\0') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 					jsonw_name(json_wtr, "proto");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 					jsonw_string(json_wtr, func_sig);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 				record = (void *)record + dd->finfo_rec_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 		if (prog_linfo) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 			const struct bpf_line_info *linfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 			linfo = bpf_prog_linfo__lfind(prog_linfo, i, nr_skip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 			if (linfo) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 				btf_dump_linfo_json(btf, linfo, linum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 				nr_skip++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 		jsonw_name(json_wtr, "disasm");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 		print_bpf_insn(&cbs, insn + i, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 		if (opcodes) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 			jsonw_name(json_wtr, "opcodes");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 			jsonw_start_object(json_wtr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 			jsonw_name(json_wtr, "code");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 			jsonw_printf(json_wtr, "\"0x%02hhx\"", insn[i].code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 			jsonw_name(json_wtr, "src_reg");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 			jsonw_printf(json_wtr, "\"0x%hhx\"", insn[i].src_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 			jsonw_name(json_wtr, "dst_reg");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 			jsonw_printf(json_wtr, "\"0x%hhx\"", insn[i].dst_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 			jsonw_name(json_wtr, "off");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 			print_hex_data_json((uint8_t *)(&insn[i].off), 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 			jsonw_name(json_wtr, "imm");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 			if (double_insn && i < len - 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 				print_hex_data_json((uint8_t *)(&insn[i].imm),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 						    12);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 				print_hex_data_json((uint8_t *)(&insn[i].imm),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 						    4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 			jsonw_end_object(json_wtr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 		jsonw_end_object(json_wtr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 	jsonw_end_array(json_wtr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) void dump_xlated_plain(struct dump_data *dd, void *buf, unsigned int len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 		       bool opcodes, bool linum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 	const struct bpf_prog_linfo *prog_linfo = dd->prog_linfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 	const struct bpf_insn_cbs cbs = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 		.cb_print	= print_insn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 		.cb_call	= print_call,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 		.cb_imm		= print_imm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 		.private_data	= dd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 	struct bpf_func_info *record;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 	struct bpf_insn *insn = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 	struct btf *btf = dd->btf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 	unsigned int nr_skip = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	bool double_insn = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 	char func_sig[1024];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 	unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 	record = dd->func_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 	for (i = 0; i < len / sizeof(*insn); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 		if (double_insn) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 			double_insn = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 		if (btf && record) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 			if (record->insn_off == i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 				btf_dumper_type_only(btf, record->type_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 						     func_sig,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 						     sizeof(func_sig));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 				if (func_sig[0] != '\0')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 					printf("%s:\n", func_sig);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 				record = (void *)record + dd->finfo_rec_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 		if (prog_linfo) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 			const struct bpf_line_info *linfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 			linfo = bpf_prog_linfo__lfind(prog_linfo, i, nr_skip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 			if (linfo) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 				btf_dump_linfo_plain(btf, linfo, "; ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 						     linum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 				nr_skip++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 		double_insn = insn[i].code == (BPF_LD | BPF_IMM | BPF_DW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 		printf("% 4d: ", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 		print_bpf_insn(&cbs, insn + i, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 		if (opcodes) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 			printf("       ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 			fprint_hex(stdout, insn + i, 8, " ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 			if (double_insn && i < len - 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 				printf(" ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 				fprint_hex(stdout, insn + i + 1, 8, " ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 			printf("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) void dump_xlated_for_graph(struct dump_data *dd, void *buf_start, void *buf_end,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 			   unsigned int start_idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 	const struct bpf_insn_cbs cbs = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 		.cb_print	= print_insn_for_graph,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 		.cb_call	= print_call,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 		.cb_imm		= print_imm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 		.private_data	= dd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 	struct bpf_insn *insn_start = buf_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 	struct bpf_insn *insn_end = buf_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 	struct bpf_insn *cur = insn_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 	for (; cur <= insn_end; cur++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 		printf("% 4d: ", (int)(cur - insn_start + start_idx));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 		print_bpf_insn(&cbs, cur, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 		if (cur != insn_end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 			printf(" | ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) }