^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) }