Blame bpf.c

Packit Service 501009
/* bpf.c - core analysis suite
Packit Service 501009
 *
Packit Service 501009
 * Copyright (C) 2018 David Anderson
Packit Service 501009
 * Copyright (C) 2018 Red Hat, Inc. All rights reserved.
Packit Service 501009
 *
Packit Service 501009
 * This program is free software; you can redistribute it and/or modify
Packit Service 501009
 * it under the terms of the GNU General Public License as published by
Packit Service 501009
 * the Free Software Foundation; either version 2 of the License, or
Packit Service 501009
 * (at your option) any later version.
Packit Service 501009
 *
Packit Service 501009
 * This program is distributed in the hope that it will be useful,
Packit Service 501009
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 501009
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 501009
 * GNU General Public License for more details.
Packit Service 501009
 */
Packit Service 501009
Packit Service 501009
#include "defs.h"
Packit Service 501009
Packit Service 501009
struct bpf_info {
Packit Service 501009
	ulong status;
Packit Service 501009
	ulong progs, maps;
Packit Service 501009
	struct list_pair *proglist;
Packit Service 501009
	struct list_pair *maplist;
Packit Service 501009
	char *bpf_prog_buf;
Packit Service 501009
	char *bpf_prog_aux_buf;
Packit Service 501009
	char *bpf_map_buf;
Packit Service 501009
	char *bytecode_buf;
Packit Service 501009
	int bpf_prog_type_size;
Packit Service 501009
	int bpf_map_map_type_size;
Packit Service 501009
	int idr_type;
Packit Service 501009
#define IDR_ORIG   (1)
Packit Service 501009
#define IDR_RADIX  (2)
Packit Service 501009
#define IDR_XARRAY (3)
Packit Service 501009
	char prog_hdr1[81];
Packit Service 501009
	char map_hdr1[81];
Packit Service 501009
} bpf_info = { 
Packit Service 501009
	.status = UNINITIALIZED,
Packit Service 501009
};
Packit Service 501009
Packit Service 501009
static void do_bpf(ulong, ulong, ulong, int);
Packit Service 501009
static void bpf_init(struct bpf_info *);
Packit Service 501009
static int bpf_type_size_init(void);
Packit Service 501009
static char *bpf_prog_type_string(int, char *);
Packit Service 501009
static char *bpf_map_map_type_string(int, char *);
Packit Service 501009
static char *bpf_prog_used_maps(int, char *);
Packit Service 501009
static char *bpf_prog_tag_string(char *, char *);
Packit Service 501009
static void bpf_prog_gpl_compatible(char *, ulong);
Packit Service 501009
Packit Service 501009
static void dump_xlated_plain(void *, unsigned int, int);
Packit Service 501009
static void print_boot_time(unsigned long long, char *, unsigned int);
Packit Service 501009
Packit Service 501009
static int do_old_idr(int, ulong, struct list_pair *);
Packit Service 501009
#define IDR_ORIG_INIT   (1)
Packit Service 501009
#define IDR_ORIG_COUNT  (2)
Packit Service 501009
#define IDR_ORIG_GATHER (3)
Packit Service 501009
Packit Service 501009
#define PROG_ID        (0x1)
Packit Service 501009
#define MAP_ID         (0x2)
Packit Service 501009
#define DUMP_STRUCT    (0x4)
Packit Service 501009
#define JITED          (0x8)
Packit Service 501009
#define XLATED        (0x10)
Packit Service 501009
#define OPCODES       (0x20)
Packit Service 501009
#define PROG_VERBOSE  (0x40)
Packit Service 501009
#define MAP_VERBOSE   (0x80)
Packit Service 501009
Packit Service 501009
void
Packit Service 501009
cmd_bpf(void)
Packit Service 501009
{
Packit Service 501009
	int c, radix;
Packit Service 501009
	ulong flags, prog_id, map_id;
Packit Service 501009
Packit Service 501009
	flags = prog_id = map_id = radix = 0;
Packit Service 501009
Packit Service 501009
	while ((c = getopt(argcnt, args, "PMtTjsxdm:p:")) != EOF) {
Packit Service 501009
		switch(c)
Packit Service 501009
		{
Packit Service 501009
		case 'j':
Packit Service 501009
			flags |= JITED;
Packit Service 501009
			break;
Packit Service 501009
		case 'T':
Packit Service 501009
			flags |= (XLATED|OPCODES);
Packit Service 501009
			break;
Packit Service 501009
		case 't':
Packit Service 501009
			flags |= XLATED;
Packit Service 501009
			break;
Packit Service 501009
		case 'm':
Packit Service 501009
			map_id = stol(optarg, FAULT_ON_ERROR, NULL);
Packit Service 501009
			flags |= MAP_ID;
Packit Service 501009
			break;
Packit Service 501009
		case 'p':	
Packit Service 501009
			prog_id = stol(optarg, FAULT_ON_ERROR, NULL);
Packit Service 501009
			flags |= PROG_ID;
Packit Service 501009
			break;
Packit Service 501009
		case 's':
Packit Service 501009
			flags |= DUMP_STRUCT;
Packit Service 501009
			break;
Packit Service 501009
		case 'P':
Packit Service 501009
			flags |= PROG_VERBOSE;
Packit Service 501009
			break;
Packit Service 501009
		case 'M':
Packit Service 501009
			flags |= MAP_VERBOSE;
Packit Service 501009
			break;
Packit Service 501009
		case 'x':
Packit Service 501009
			if (radix == 10)
Packit Service 501009
				error(FATAL, "-d and -x are mutually exclusive\n");
Packit Service 501009
			radix = 16;
Packit Service 501009
			break;
Packit Service 501009
		case 'd':
Packit Service 501009
			if (radix == 16)
Packit Service 501009
				error(FATAL, "-d and -x are mutually exclusive\n");
Packit Service 501009
			radix = 16;
Packit Service 501009
			break;
Packit Service 501009
		default:
Packit Service 501009
			argerrs++;
Packit Service 501009
			break;
Packit Service 501009
		}
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (argerrs)
Packit Service 501009
		cmd_usage(pc->curcmd, SYNOPSIS);
Packit Service 501009
Packit Service 501009
	if ((flags & JITED) && !(flags & (PROG_ID|PROG_VERBOSE)))
Packit Service 501009
		error(FATAL, "-j option only applicable with -p or -P\n");
Packit Service 501009
	if ((flags & XLATED) && !(flags & (PROG_ID|PROG_VERBOSE)))
Packit Service 501009
		error(FATAL, "-t option only applicable with -p or -P\n");
Packit Service 501009
	if ((flags & DUMP_STRUCT) && !(flags & (PROG_ID|PROG_VERBOSE|MAP_ID|MAP_VERBOSE)))
Packit Service 501009
		error(FATAL, "-s option requires either -p, -P, -m or -M\n");
Packit Service 501009
Packit Service 501009
	if (radix && !(flags & (PROG_ID|PROG_VERBOSE|MAP_ID|MAP_VERBOSE)))
Packit Service 501009
		error(FATAL, "-%c option requires -s\n", radix == 10 ? 'd' : 'x');
Packit Service 501009
Packit Service 501009
	while (args[optind]) {
Packit Service 501009
		error(FATAL, "invalid argument: %s\n", args[optind]);
Packit Service 501009
		optind++;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	do_bpf(flags, prog_id, map_id, radix);
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static void
Packit Service 501009
bpf_init(struct bpf_info *bpf)
Packit Service 501009
{
Packit Service 501009
	long len;
Packit Service 501009
	char buf1[BUFSIZE];
Packit Service 501009
	char buf2[BUFSIZE];
Packit Service 501009
	char buf3[BUFSIZE];
Packit Service 501009
	char buf4[BUFSIZE];
Packit Service 501009
Packit Service 501009
	switch (bpf->status)
Packit Service 501009
	{
Packit Service 501009
	case UNINITIALIZED:
Packit Service 501009
		if (!kernel_symbol_exists("prog_idr") || 
Packit Service 501009
		    !kernel_symbol_exists("map_idr")) {
Packit Service 501009
			bpf->status = FALSE;
Packit Service 501009
			command_not_supported();
Packit Service 501009
		}
Packit Service 501009
		
Packit Service 501009
		STRUCT_SIZE_INIT(bpf_prog, "bpf_prog");
Packit Service 501009
		STRUCT_SIZE_INIT(bpf_prog_aux, "bpf_prog_aux");
Packit Service 501009
		STRUCT_SIZE_INIT(bpf_map, "bpf_map");
Packit Service 501009
		STRUCT_SIZE_INIT(bpf_insn, "bpf_insn");
Packit Service 501009
		MEMBER_OFFSET_INIT(bpf_prog_aux, "bpf_prog", "aux");
Packit Service 501009
		MEMBER_OFFSET_INIT(bpf_prog_type, "bpf_prog", "type");
Packit Service 501009
		MEMBER_OFFSET_INIT(bpf_prog_tag, "bpf_prog", "tag");
Packit Service 501009
		MEMBER_OFFSET_INIT(bpf_prog_jited_len, "bpf_prog", "jited_len");
Packit Service 501009
		MEMBER_OFFSET_INIT(bpf_prog_bpf_func, "bpf_prog", "bpf_func");
Packit Service 501009
		MEMBER_OFFSET_INIT(bpf_prog_len, "bpf_prog", "len");
Packit Service 501009
		MEMBER_OFFSET_INIT(bpf_prog_insnsi, "bpf_prog", "insnsi");
Packit Service 501009
		MEMBER_OFFSET_INIT(bpf_map_map_type, "bpf_map", "map_type");
Packit Service 501009
		MEMBER_OFFSET_INIT(bpf_map_map_flags, "bpf_map", "map_flags");
Packit Service 501009
		MEMBER_OFFSET_INIT(bpf_prog_aux_used_maps, "bpf_prog_aux", "used_maps");
Packit Service 501009
		MEMBER_OFFSET_INIT(bpf_prog_aux_used_map_cnt, "bpf_prog_aux", "used_map_cnt");
Packit Service 501009
		if (!VALID_STRUCT(bpf_prog) || 
Packit Service 501009
		    !VALID_STRUCT(bpf_prog_aux) ||
Packit Service 501009
		    !VALID_STRUCT(bpf_map) ||
Packit Service 501009
		    !VALID_STRUCT(bpf_insn) ||
Packit Service 501009
		    INVALID_MEMBER(bpf_prog_aux) ||
Packit Service 501009
		    INVALID_MEMBER(bpf_prog_type) ||
Packit Service 501009
		    INVALID_MEMBER(bpf_prog_tag) ||
Packit Service 501009
		    INVALID_MEMBER(bpf_prog_jited_len) ||
Packit Service 501009
		    INVALID_MEMBER(bpf_prog_bpf_func) ||
Packit Service 501009
		    INVALID_MEMBER(bpf_prog_len) ||
Packit Service 501009
		    INVALID_MEMBER(bpf_prog_insnsi) ||
Packit Service 501009
		    INVALID_MEMBER(bpf_map_map_flags) ||
Packit Service 501009
		    INVALID_MEMBER(bpf_map_map_type) ||
Packit Service 501009
		    INVALID_MEMBER(bpf_prog_aux_used_maps) ||
Packit Service 501009
		    INVALID_MEMBER(bpf_prog_aux_used_map_cnt)) {
Packit Service 501009
			bpf->status = FALSE;
Packit Service 501009
			command_not_supported();
Packit Service 501009
		}	
Packit Service 501009
		/*
Packit Service 501009
		 *  Not required for basic functionality
Packit Service 501009
		 */
Packit Service 501009
		MEMBER_OFFSET_INIT(bpf_prog_pages, "bpf_prog", "pages");
Packit Service 501009
		MEMBER_OFFSET_INIT(bpf_prog_aux_load_time, "bpf_prog_aux", "load_time");
Packit Service 501009
		MEMBER_OFFSET_INIT(bpf_prog_aux_user, "bpf_prog_aux", "user");
Packit Service 501009
		MEMBER_OFFSET_INIT(bpf_map_key_size, "bpf_map", "key_size");
Packit Service 501009
		MEMBER_OFFSET_INIT(bpf_map_value_size, "bpf_map", "value_size");
Packit Service 501009
		MEMBER_OFFSET_INIT(bpf_map_max_entries, "bpf_map", "max_entries");
Packit Service 501009
		MEMBER_OFFSET_INIT(bpf_map_pages, "bpf_map", "pages");
Packit Service 501009
		MEMBER_OFFSET_INIT(bpf_map_name, "bpf_map", "name");
Packit Service 501009
		MEMBER_OFFSET_INIT(bpf_map_user, "bpf_map", "user");
Packit Service 501009
		MEMBER_OFFSET_INIT(user_struct_uid, "user_struct", "uid");
Packit Service 501009
Packit Service 501009
		if (!bpf_type_size_init()) {
Packit Service 501009
			bpf->status = FALSE;
Packit Service 501009
			command_not_supported();
Packit Service 501009
		}
Packit Service 501009
		sprintf(bpf->prog_hdr1, "%s %s %s %s ",
Packit Service 501009
			mkstring(buf1, 4, CENTER|LJUST, "ID"),
Packit Service 501009
			mkstring(buf2, VADDR_PRLEN, CENTER|LJUST, "BPF_PROG"),
Packit Service 501009
			mkstring(buf3, VADDR_PRLEN, CENTER|LJUST, "BPF_PROG_AUX"),
Packit Service 501009
			mkstring(buf4, bpf->bpf_prog_type_size, CENTER|LJUST, "BPF_PROG_TYPE"));
Packit Service 501009
		strcat(bpf->prog_hdr1, "      TAG        USED_MAPS");
Packit Service 501009
		sprintf(bpf->map_hdr1, "%s %s %s MAP_FLAGS",
Packit Service 501009
			mkstring(buf1, 4, CENTER|LJUST, "ID"),
Packit Service 501009
			mkstring(buf2, VADDR_PRLEN, CENTER|LJUST, "BPF_MAP"),
Packit Service 501009
			mkstring(buf3, bpf->bpf_map_map_type_size, CENTER|LJUST, "BPF_MAP_TYPE"));
Packit Service 501009
Packit Service 501009
		if (INVALID_MEMBER(idr_idr_rt)) {
Packit Service 501009
			bpf->idr_type = IDR_ORIG;
Packit Service 501009
			do_old_idr(IDR_ORIG_INIT, 0, NULL);
Packit Service 501009
		} else if (STREQ(MEMBER_TYPE_NAME("idr", "idr_rt"), "radix_tree_root"))
Packit Service 501009
			if (MEMBER_EXISTS("radix_tree_root", "rnode"))
Packit Service 501009
				bpf->idr_type = IDR_RADIX;
Packit Service 501009
			else if (MEMBER_EXISTS("radix_tree_root", "xa_head"))
Packit Service 501009
				bpf->idr_type = IDR_XARRAY;
Packit Service 501009
			else
Packit Service 501009
				error(FATAL, "cannot determine IDR list type\n");
Packit Service 501009
		else if (STREQ(MEMBER_TYPE_NAME("idr", "idr_rt"), "xarray"))
Packit Service 501009
			bpf->idr_type = IDR_XARRAY;
Packit Service 501009
		else
Packit Service 501009
			error(FATAL, "cannot determine IDR list type\n");
Packit Service 501009
Packit Service 501009
		bpf->status = TRUE;
Packit Service 501009
		break;
Packit Service 501009
Packit Service 501009
	case TRUE:
Packit Service 501009
		break;
Packit Service 501009
Packit Service 501009
	case FALSE:
Packit Service 501009
		command_not_supported();
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	switch (bpf->idr_type)
Packit Service 501009
	{
Packit Service 501009
	case IDR_ORIG:
Packit Service 501009
		bpf->progs = do_old_idr(IDR_ORIG_COUNT, symbol_value("prog_idr"), NULL);
Packit Service 501009
		break;
Packit Service 501009
	case IDR_RADIX:
Packit Service 501009
		bpf->progs = do_radix_tree(symbol_value("prog_idr") + OFFSET(idr_idr_rt),
Packit Service 501009
			RADIX_TREE_COUNT, NULL);
Packit Service 501009
		break;
Packit Service 501009
	case IDR_XARRAY:
Packit Service 501009
		bpf->progs = do_xarray(symbol_value("prog_idr") + OFFSET(idr_idr_rt),
Packit Service 501009
			XARRAY_COUNT, NULL);
Packit Service 501009
		break;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (bpf->progs) {
Packit Service 501009
		len = sizeof(struct list_pair) * (bpf->progs+1);
Packit Service 501009
		bpf->proglist = (struct list_pair *)GETBUF(len);
Packit Service 501009
		bpf->proglist[0].index = bpf->progs;
Packit Service 501009
Packit Service 501009
		switch (bpf->idr_type)
Packit Service 501009
		{
Packit Service 501009
		case IDR_ORIG:
Packit Service 501009
			bpf->progs = do_old_idr(IDR_ORIG_GATHER, symbol_value("prog_idr"), bpf->proglist);
Packit Service 501009
			break;
Packit Service 501009
		case IDR_RADIX:
Packit Service 501009
			bpf->progs = do_radix_tree(symbol_value("prog_idr") + OFFSET(idr_idr_rt),
Packit Service 501009
				RADIX_TREE_GATHER, bpf->proglist);
Packit Service 501009
			break;
Packit Service 501009
		case IDR_XARRAY:
Packit Service 501009
			bpf->progs = do_xarray(symbol_value("prog_idr") + OFFSET(idr_idr_rt),
Packit Service 501009
				XARRAY_GATHER, bpf->proglist);
Packit Service 501009
			break;
Packit Service 501009
		}
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	switch (bpf->idr_type)
Packit Service 501009
	{
Packit Service 501009
	case IDR_ORIG:
Packit Service 501009
		bpf->maps = do_old_idr(IDR_ORIG_COUNT, symbol_value("map_idr"), NULL);
Packit Service 501009
		break;
Packit Service 501009
	case IDR_RADIX:
Packit Service 501009
		bpf->maps = do_radix_tree(symbol_value("map_idr") + OFFSET(idr_idr_rt), 
Packit Service 501009
			RADIX_TREE_COUNT, NULL);
Packit Service 501009
		break;
Packit Service 501009
	case IDR_XARRAY:
Packit Service 501009
		bpf->maps = do_xarray(symbol_value("map_idr") + OFFSET(idr_idr_rt), 
Packit Service 501009
			XARRAY_COUNT, NULL);
Packit Service 501009
		break;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (bpf->maps) {
Packit Service 501009
		len = sizeof(struct list_pair) * (bpf->maps+1);
Packit Service 501009
		bpf->maplist = (struct list_pair *)GETBUF(len);
Packit Service 501009
		bpf->maplist[0].index = bpf->maps;
Packit Service 501009
Packit Service 501009
		switch (bpf->idr_type)
Packit Service 501009
		{
Packit Service 501009
		case IDR_ORIG:
Packit Service 501009
			bpf->maps = do_old_idr(IDR_ORIG_GATHER, symbol_value("map_idr"), bpf->maplist);
Packit Service 501009
			break;
Packit Service 501009
		case IDR_RADIX:
Packit Service 501009
			bpf->maps = do_radix_tree(symbol_value("map_idr") + OFFSET(idr_idr_rt),
Packit Service 501009
				RADIX_TREE_GATHER, bpf->maplist);
Packit Service 501009
			break;
Packit Service 501009
		case IDR_XARRAY:
Packit Service 501009
			bpf->maps = do_xarray(symbol_value("map_idr") + OFFSET(idr_idr_rt),
Packit Service 501009
				XARRAY_GATHER, bpf->maplist);
Packit Service 501009
			break;
Packit Service 501009
		}
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	bpf->bpf_prog_buf = GETBUF(SIZE(bpf_prog));
Packit Service 501009
	bpf->bpf_prog_aux_buf = GETBUF(SIZE(bpf_prog_aux));
Packit Service 501009
	bpf->bpf_map_buf = GETBUF(SIZE(bpf_map));
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static void
Packit Service 501009
do_bpf(ulong flags, ulong prog_id, ulong map_id, int radix)
Packit Service 501009
{
Packit Service 501009
	struct bpf_info *bpf;
Packit Service 501009
	int i, c, found, entries, type;
Packit Service 501009
	uint uid, map_pages, key_size, value_size, max_entries;
Packit Service 501009
	ulong bpf_prog_aux, bpf_func, end_func, addr, insnsi, user;
Packit Service 501009
	ulong do_progs, do_maps;
Packit Service 501009
	ulonglong load_time;
Packit Service 501009
	char *symbol;
Packit Service 501009
	ushort prog_pages;
Packit Service 501009
	int jited_len, len;
Packit Service 501009
	char *arglist[MAXARGS];
Packit Service 501009
	char buf1[BUFSIZE];
Packit Service 501009
	char buf2[BUFSIZE];
Packit Service 501009
	char buf3[BUFSIZE];
Packit Service 501009
	char buf4[BUFSIZE];
Packit Service 501009
	char buf5[BUFSIZE/2];
Packit Service 501009
	
Packit Service 501009
	bpf = &bpf_info;
Packit Service 501009
	bpf->proglist = NULL;
Packit Service 501009
	bpf->maplist = NULL;
Packit Service 501009
	bpf->bpf_prog_buf = bpf->bpf_prog_aux_buf = bpf->bpf_map_buf = NULL;
Packit Service 501009
	bpf->bytecode_buf = NULL;
Packit Service 501009
Packit Service 501009
	bpf_init(bpf);
Packit Service 501009
Packit Service 501009
	if (flags & PROG_ID) {
Packit Service 501009
		for (i = found = 0; i < bpf->progs; i++) {
Packit Service 501009
			if (prog_id == bpf->proglist[i].index) {
Packit Service 501009
				found++;
Packit Service 501009
				break;
Packit Service 501009
			}
Packit Service 501009
		}
Packit Service 501009
		if (!found) {
Packit Service 501009
			error(INFO, "invalid program ID: %ld\n", prog_id);
Packit Service 501009
			goto bailout;
Packit Service 501009
		}
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (flags & MAP_ID) {
Packit Service 501009
		for (i = found = 0; i < bpf->maps; i++) {
Packit Service 501009
			if (map_id == bpf->maplist[i].index) {
Packit Service 501009
				found++;
Packit Service 501009
				break;
Packit Service 501009
			}
Packit Service 501009
		}
Packit Service 501009
		if (!found) {
Packit Service 501009
			error(INFO, "invalid map ID: %ld\n", map_id);
Packit Service 501009
			goto bailout;
Packit Service 501009
		}
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (!(flags & (PROG_ID|PROG_VERBOSE|MAP_ID|MAP_VERBOSE)))
Packit Service 501009
		do_progs = do_maps = TRUE;
Packit Service 501009
	else {
Packit Service 501009
		do_progs = do_maps = FALSE;
Packit Service 501009
		if (flags & (PROG_ID|PROG_VERBOSE))
Packit Service 501009
			do_progs = TRUE;
Packit Service 501009
		if (flags & (MAP_ID|MAP_VERBOSE))
Packit Service 501009
			do_maps = TRUE;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (!do_progs)
Packit Service 501009
		goto do_map_only;
Packit Service 501009
Packit Service 501009
	for (i = entries = 0; i < bpf->progs; i++) {
Packit Service 501009
		if (bpf->proglist[i].value == 0) 
Packit Service 501009
			continue;
Packit Service 501009
Packit Service 501009
		if (((flags & (PROG_ID|PROG_VERBOSE)) == PROG_ID) && 
Packit Service 501009
		    (prog_id != bpf->proglist[i].index)) 
Packit Service 501009
			continue;
Packit Service 501009
Packit Service 501009
		if (!readmem((ulong)bpf->proglist[i].value, KVADDR, bpf->bpf_prog_buf, 
Packit Service 501009
		    SIZE(bpf_prog), "struct bpf_prog", RETURN_ON_ERROR))
Packit Service 501009
			goto bailout;
Packit Service 501009
		bpf_prog_aux = ULONG(bpf->bpf_prog_buf + OFFSET(bpf_prog_aux));
Packit Service 501009
		if (!readmem(bpf_prog_aux, KVADDR, bpf->bpf_prog_aux_buf, 
Packit Service 501009
		    SIZE(bpf_prog_aux), "struct bpf_prog_aux", RETURN_ON_ERROR))
Packit Service 501009
			goto bailout;
Packit Service 501009
Packit Service 501009
		if (entries && (flags & PROG_VERBOSE))
Packit Service 501009
			fprintf(fp, "\n%s\n", bpf->prog_hdr1);
Packit Service 501009
		if (entries++ == 0)
Packit Service 501009
			fprintf(fp, "%s\n", bpf->prog_hdr1);
Packit Service 501009
Packit Service 501009
		fprintf(fp, "%s %s %s ", 
Packit Service 501009
			mkstring(buf1, 4, CENTER|LJUST|LONG_DEC, MKSTR(bpf->proglist[i].index)),
Packit Service 501009
			mkstring(buf2, VADDR_PRLEN, CENTER|LJUST|LONG_HEX, MKSTR(bpf->proglist[i].value)),
Packit Service 501009
			mkstring(buf3, VADDR_PRLEN, CENTER|LJUST|LONG_HEX, MKSTR(bpf_prog_aux)));
Packit Service 501009
		type = INT(bpf->bpf_prog_buf + OFFSET(bpf_prog_type));
Packit Service 501009
		fprintf(fp, "%s ", 
Packit Service 501009
			mkstring(buf1, bpf->bpf_prog_type_size, CENTER|LJUST, bpf_prog_type_string(type, buf2)));
Packit Service 501009
		fprintf(fp, "%s ", bpf_prog_tag_string(bpf->bpf_prog_buf + OFFSET(bpf_prog_tag), buf1));
Packit Service 501009
		fprintf(fp, "%s ", 
Packit Service 501009
			mkstring(buf1, strlen("USED_MAPS"), CENTER|LJUST, bpf_prog_used_maps(i, buf2)));
Packit Service 501009
		fprintf(fp, "\n");
Packit Service 501009
Packit Service 501009
		if (flags & (PROG_ID|PROG_VERBOSE)) {
Packit Service 501009
			jited_len = UINT(bpf->bpf_prog_buf + OFFSET(bpf_prog_jited_len));
Packit Service 501009
			len = UINT(bpf->bpf_prog_buf + OFFSET(bpf_prog_len));
Packit Service 501009
			len *= SIZE(bpf_insn);
Packit Service 501009
			if (VALID_MEMBER(bpf_prog_pages)) {
Packit Service 501009
				prog_pages = USHORT(bpf->bpf_prog_buf + OFFSET(bpf_prog_pages));
Packit Service 501009
				prog_pages *= PAGESIZE();
Packit Service 501009
			} else
Packit Service 501009
				prog_pages = 0;
Packit Service 501009
Packit Service 501009
			fprintf(fp, "     XLATED: %d  JITED: %d  MEMLOCK: ", len, jited_len);
Packit Service 501009
			if (VALID_MEMBER(bpf_prog_pages)) {
Packit Service 501009
				fprintf(fp, "%d\n", prog_pages);
Packit Service 501009
			} else
Packit Service 501009
				fprintf(fp, "(unknown)\n");
Packit Service 501009
Packit Service 501009
			fprintf(fp, "     LOAD_TIME: ");
Packit Service 501009
			if (VALID_MEMBER(bpf_prog_aux_load_time)) {
Packit Service 501009
				load_time = ULONGLONG(bpf->bpf_prog_aux_buf + OFFSET(bpf_prog_aux_load_time));
Packit Service 501009
				print_boot_time(load_time, buf5, BUFSIZE/2);
Packit Service 501009
				fprintf(fp, "%s\n", buf5);
Packit Service 501009
			} else
Packit Service 501009
				fprintf(fp, "(unknown)\n");
Packit Service 501009
Packit Service 501009
			bpf_prog_gpl_compatible(buf1, (ulong)bpf->proglist[i].value);
Packit Service 501009
			fprintf(fp, "     GPL_COMPATIBLE: %s", buf1);
Packit Service 501009
Packit Service 501009
			fprintf(fp, "  UID: ");
Packit Service 501009
			if (VALID_MEMBER(bpf_prog_aux_user) && VALID_MEMBER(user_struct_uid)) {
Packit Service 501009
				user = ULONG(bpf->bpf_prog_aux_buf + OFFSET(bpf_prog_aux_user));
Packit Service 501009
				if (readmem(user + OFFSET(user_struct_uid), KVADDR, &uid, sizeof(uint), 
Packit Service 501009
				    "user_struct.uid", QUIET|RETURN_ON_ERROR))
Packit Service 501009
					fprintf(fp, "%d\n", uid);
Packit Service 501009
				else
Packit Service 501009
					fprintf(fp, "(unknown)\n");
Packit Service 501009
			} else
Packit Service 501009
				fprintf(fp, "(unknown)\n");
Packit Service 501009
		}
Packit Service 501009
Packit Service 501009
		if (flags & JITED) {
Packit Service 501009
			fprintf(fp, "\n");
Packit Service 501009
			jited_len = UINT(bpf->bpf_prog_buf + OFFSET(bpf_prog_jited_len));
Packit Service 501009
			bpf_func = ULONG(bpf->bpf_prog_buf + OFFSET(bpf_prog_bpf_func));
Packit Service 501009
			end_func = bpf_func + jited_len;
Packit Service 501009
Packit Service 501009
			if (jited_len) {
Packit Service 501009
				open_tmpfile();
Packit Service 501009
				pc->curcmd_private = (ulonglong)end_func;
Packit Service 501009
				sprintf(buf1, "x/%di 0x%lx", jited_len, bpf_func);
Packit Service 501009
				gdb_pass_through(buf1, NULL, GNU_RETURN_ON_ERROR);
Packit Service 501009
				rewind(pc->tmpfile);
Packit Service 501009
				while (fgets(buf1, BUFSIZE, pc->tmpfile)) {
Packit Service 501009
					strcpy(buf2, strip_linefeeds(buf1));
Packit Service 501009
					c = parse_line(buf1, arglist);
Packit Service 501009
					if (STRNEQ(arglist[0], "0x") && 
Packit Service 501009
					    (LASTCHAR(arglist[0]) == ':')) {
Packit Service 501009
						addr = htol(strip_ending_char(arglist[0], ':'), 
Packit Service 501009
							RETURN_ON_ERROR, NULL);
Packit Service 501009
						if (addr >= end_func)
Packit Service 501009
							break;
Packit Service 501009
					}
Packit Service 501009
					symbol = NULL;
Packit Service 501009
					if ((c > 1) && IS_A_NUMBER(arglist[c-1])) {
Packit Service 501009
						addr = htol(arglist[c-1], RETURN_ON_ERROR, NULL);
Packit Service 501009
						symbol = value_to_symstr(addr, buf3, radix); 
Packit Service 501009
						if (strlen(symbol)) {
Packit Service 501009
							sprintf(buf4, "<%s>", symbol);
Packit Service 501009
							symbol = buf4;
Packit Service 501009
						}
Packit Service 501009
					}
Packit Service 501009
					fprintf(pc->saved_fp, "%s %s\n", buf2, symbol ? symbol : "");
Packit Service 501009
				}
Packit Service 501009
				pc->curcmd_private = 0;
Packit Service 501009
				close_tmpfile();
Packit Service 501009
			} else
Packit Service 501009
				fprintf(fp, "(program not jited)\n");
Packit Service 501009
		}
Packit Service 501009
Packit Service 501009
		if (flags & XLATED) {
Packit Service 501009
			fprintf(fp, "\n");
Packit Service 501009
			len = UINT(bpf->bpf_prog_buf + OFFSET(bpf_prog_len));
Packit Service 501009
			insnsi = (ulong)bpf->proglist[i].value + OFFSET(bpf_prog_insnsi);
Packit Service 501009
			bpf->bytecode_buf = GETBUF(len * SIZE(bpf_insn));
Packit Service 501009
			if (CRASHDEBUG(1))
Packit Service 501009
				fprintf(fp, "bytecode_buf: [%lx] len %d * size %ld = %ld  from: %lx\n", 
Packit Service 501009
					(ulong)bpf->bytecode_buf,
Packit Service 501009
					len, SIZE(bpf_insn), len * SIZE(bpf_insn), insnsi);
Packit Service 501009
			if (!readmem(insnsi, KVADDR, bpf->bytecode_buf, len * SIZE(bpf_insn), 
Packit Service 501009
			    "bpf_prog.insnsi contents", RETURN_ON_ERROR))
Packit Service 501009
				goto bailout;
Packit Service 501009
			dump_xlated_plain((void *)bpf->bytecode_buf, len * SIZE(bpf_insn), flags & OPCODES);
Packit Service 501009
		}
Packit Service 501009
Packit Service 501009
		if (flags & DUMP_STRUCT) {
Packit Service 501009
			fprintf(fp, "\n");
Packit Service 501009
			dump_struct("bpf_prog", (ulong)bpf->proglist[i].value, radix);
Packit Service 501009
			fprintf(fp, "\n");
Packit Service 501009
			dump_struct("bpf_prog_aux", bpf_prog_aux, radix);
Packit Service 501009
		}
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (!do_maps)
Packit Service 501009
		goto bailout;
Packit Service 501009
	else
Packit Service 501009
		fprintf(fp, "\n");
Packit Service 501009
Packit Service 501009
do_map_only:
Packit Service 501009
Packit Service 501009
	for (i = entries = 0; i < bpf->maps; i++) {
Packit Service 501009
		if (bpf->maplist[i].value == 0) 
Packit Service 501009
			continue;
Packit Service 501009
Packit Service 501009
		if (((flags & (MAP_ID|MAP_VERBOSE)) == MAP_ID) && 
Packit Service 501009
		    (map_id != bpf->maplist[i].index))
Packit Service 501009
			continue;
Packit Service 501009
Packit Service 501009
		if (entries && (flags & MAP_VERBOSE))
Packit Service 501009
			fprintf(fp, "\n%s\n", bpf->map_hdr1);
Packit Service 501009
		if (entries++ == 0)
Packit Service 501009
			fprintf(fp, "%s\n", bpf->map_hdr1);
Packit Service 501009
Packit Service 501009
		if (!readmem((ulong)bpf->maplist[i].value, KVADDR, bpf->bpf_map_buf, 
Packit Service 501009
		    SIZE(bpf_map), "struct bpf_map", RETURN_ON_ERROR))
Packit Service 501009
			goto bailout;
Packit Service 501009
Packit Service 501009
		fprintf(fp, "%s %s ", 
Packit Service 501009
			mkstring(buf1, 4, CENTER|LJUST|LONG_DEC, MKSTR(bpf->maplist[i].index)),
Packit Service 501009
			mkstring(buf2, VADDR_PRLEN, CENTER|LJUST|LONG_HEX, MKSTR(bpf->maplist[i].value)));
Packit Service 501009
		type = INT(bpf->bpf_map_buf + OFFSET(bpf_map_map_type));
Packit Service 501009
		fprintf(fp, "%s ", 
Packit Service 501009
			mkstring(buf1, bpf->bpf_map_map_type_size, CENTER|LJUST, bpf_map_map_type_string(type, buf2)));
Packit Service 501009
		fprintf(fp, " %08x ", UINT(bpf->bpf_map_buf + OFFSET(bpf_map_map_flags)));
Packit Service 501009
		fprintf(fp, "\n");
Packit Service 501009
Packit Service 501009
		if (flags & (MAP_ID|MAP_VERBOSE)) {
Packit Service 501009
			fprintf(fp, "     KEY_SIZE: ");
Packit Service 501009
			if (VALID_MEMBER(bpf_map_key_size)) {
Packit Service 501009
				key_size = UINT(bpf->bpf_map_buf + OFFSET(bpf_map_key_size));
Packit Service 501009
				fprintf(fp, "%d", key_size);
Packit Service 501009
			} else
Packit Service 501009
				fprintf(fp, "(unknown)");
Packit Service 501009
Packit Service 501009
			fprintf(fp, "  VALUE_SIZE: ");
Packit Service 501009
			if (VALID_MEMBER(bpf_map_value_size)) {
Packit Service 501009
				value_size = UINT(bpf->bpf_map_buf + OFFSET(bpf_map_value_size));
Packit Service 501009
				fprintf(fp, "%d", value_size);
Packit Service 501009
			} else
Packit Service 501009
				fprintf(fp, "(unknown)");
Packit Service 501009
Packit Service 501009
			fprintf(fp, "  MAX_ENTRIES: ");
Packit Service 501009
			if (VALID_MEMBER(bpf_map_max_entries)) {
Packit Service 501009
				max_entries = UINT(bpf->bpf_map_buf + OFFSET(bpf_map_max_entries));
Packit Service 501009
				fprintf(fp, "%d", max_entries);
Packit Service 501009
Packit Service 501009
			} else
Packit Service 501009
				fprintf(fp, "(unknown)");
Packit Service 501009
Packit Service 501009
			fprintf(fp, "  MEMLOCK: ");
Packit Service 501009
			if (VALID_MEMBER(bpf_map_pages)) {
Packit Service 501009
				map_pages = UINT(bpf->bpf_map_buf + OFFSET(bpf_map_pages));
Packit Service 501009
				fprintf(fp, "%d\n", map_pages * PAGESIZE());
Packit Service 501009
			} else
Packit Service 501009
				fprintf(fp, "(unknown)\n");
Packit Service 501009
Packit Service 501009
			fprintf(fp, "     NAME: ");
Packit Service 501009
			if (VALID_MEMBER(bpf_map_name)) {
Packit Service 501009
				BCOPY(&bpf->bpf_map_buf[OFFSET(bpf_map_name)], buf1, 16);
Packit Service 501009
				buf1[17] = NULLCHAR;
Packit Service 501009
				if (strlen(buf1))
Packit Service 501009
					fprintf(fp, "\"%s\"", buf1);
Packit Service 501009
				else
Packit Service 501009
					fprintf(fp, "(unused)");
Packit Service 501009
			} else
Packit Service 501009
				fprintf(fp, "(unknown)\n");
Packit Service 501009
Packit Service 501009
			fprintf(fp, "  UID: ");
Packit Service 501009
			if (VALID_MEMBER(bpf_map_user) && VALID_MEMBER(user_struct_uid)) {
Packit Service 501009
				user = ULONG(bpf->bpf_map_buf + OFFSET(bpf_map_user));
Packit Service 501009
				if (readmem(user + OFFSET(user_struct_uid), KVADDR, &uid, sizeof(uint), 
Packit Service 501009
				    "user_struct.uid", QUIET|RETURN_ON_ERROR))
Packit Service 501009
					fprintf(fp, "%d\n", uid);
Packit Service 501009
				else
Packit Service 501009
					fprintf(fp, "(unknown)\n");
Packit Service 501009
			} else
Packit Service 501009
				fprintf(fp, "(unknown)\n");
Packit Service 501009
		}
Packit Service 501009
Packit Service 501009
		if (flags & DUMP_STRUCT) {
Packit Service 501009
			fprintf(fp, "\n");
Packit Service 501009
			dump_struct("bpf_map", (ulong)bpf->maplist[i].value, radix);
Packit Service 501009
		}
Packit Service 501009
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
bailout:
Packit Service 501009
	if (bpf->proglist)
Packit Service 501009
		FREEBUF(bpf->proglist);
Packit Service 501009
	if (bpf->maplist)
Packit Service 501009
		FREEBUF(bpf->maplist);
Packit Service 501009
	FREEBUF(bpf->bpf_prog_buf);
Packit Service 501009
	FREEBUF(bpf->bpf_prog_aux_buf);
Packit Service 501009
	FREEBUF(bpf->bpf_map_buf);
Packit Service 501009
	if (bpf->bytecode_buf)
Packit Service 501009
		FREEBUF(bpf->bytecode_buf);
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static int 
Packit Service 501009
bpf_type_size_init(void)
Packit Service 501009
{
Packit Service 501009
	int c ATTRIBUTE_UNUSED; 
Packit Service 501009
	size_t max;
Packit Service 501009
	char *arglist[MAXARGS];
Packit Service 501009
	char buf[BUFSIZE];
Packit Service 501009
	struct bpf_info *bpf = &bpf_info;
Packit Service 501009
Packit Service 501009
	open_tmpfile();
Packit Service 501009
	if (dump_enumerator_list("bpf_prog_type")) {
Packit Service 501009
		max = 0;
Packit Service 501009
		rewind(pc->tmpfile);
Packit Service 501009
		while (fgets(buf, BUFSIZE, pc->tmpfile)) {
Packit Service 501009
			if (!strstr(buf, " = "))
Packit Service 501009
				continue;
Packit Service 501009
			c = parse_line(buf, arglist);
Packit Service 501009
			if (CRASHDEBUG(1))
Packit Service 501009
				fprintf(pc->saved_fp, "%s\n", arglist[0]);
Packit Service 501009
			max = MAX(max, strlen(arglist[0]));
Packit Service 501009
		}
Packit Service 501009
		bpf->bpf_prog_type_size = max - strlen("BPF_PROG_TYPE_");
Packit Service 501009
	} else {
Packit Service 501009
		close_tmpfile();
Packit Service 501009
		return FALSE;
Packit Service 501009
	}
Packit Service 501009
	/*
Packit Service 501009
	 * Keep bpf program header at 80 columns
Packit Service 501009
	 */
Packit Service 501009
	bpf->bpf_prog_type_size = MIN(13, bpf->bpf_prog_type_size);
Packit Service 501009
	close_tmpfile();
Packit Service 501009
Packit Service 501009
	open_tmpfile();
Packit Service 501009
	if (dump_enumerator_list("bpf_map_type")) {
Packit Service 501009
		max = 0;
Packit Service 501009
		rewind(pc->tmpfile);
Packit Service 501009
		while (fgets(buf, BUFSIZE, pc->tmpfile)) {
Packit Service 501009
			if (!strstr(buf, " = "))
Packit Service 501009
				continue;
Packit Service 501009
			c = parse_line(buf, arglist);
Packit Service 501009
			if (CRASHDEBUG(1))
Packit Service 501009
				fprintf(pc->saved_fp, "%s\n", arglist[0]);
Packit Service 501009
			max = MAX(max, strlen(arglist[0]));
Packit Service 501009
		}
Packit Service 501009
		bpf->bpf_map_map_type_size = max - strlen("BPF_PROG_TYPE_");
Packit Service 501009
	} else {
Packit Service 501009
		close_tmpfile();
Packit Service 501009
		return FALSE;
Packit Service 501009
	}
Packit Service 501009
	close_tmpfile();
Packit Service 501009
Packit Service 501009
	return TRUE;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static char *
Packit Service 501009
bpf_prog_type_string(int type, char *retbuf)
Packit Service 501009
{
Packit Service 501009
	char *p;	
Packit Service 501009
	int c ATTRIBUTE_UNUSED; 
Packit Service 501009
	char *arglist[MAXARGS];
Packit Service 501009
	char buf[BUFSIZE];
Packit Service 501009
	
Packit Service 501009
	retbuf[0] = NULLCHAR;
Packit Service 501009
Packit Service 501009
	open_tmpfile();
Packit Service 501009
	if (dump_enumerator_list("bpf_prog_type")) {
Packit Service 501009
		rewind(pc->tmpfile);
Packit Service 501009
		while (fgets(buf, BUFSIZE, pc->tmpfile)) {
Packit Service 501009
			if (!strstr(buf, " = "))
Packit Service 501009
				continue;
Packit Service 501009
			c = parse_line(buf, arglist);
Packit Service 501009
			if (atoi(arglist[2]) == type) {
Packit Service 501009
				p = arglist[0];
Packit Service 501009
				p += strlen("BPF_PROG_TYPE_");
Packit Service 501009
				strcpy(retbuf, p);
Packit Service 501009
				break;
Packit Service 501009
			}
Packit Service 501009
		}
Packit Service 501009
	} 
Packit Service 501009
Packit Service 501009
	close_tmpfile();
Packit Service 501009
	return retbuf;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static char *
Packit Service 501009
bpf_map_map_type_string(int map_type, char *retbuf)
Packit Service 501009
{
Packit Service 501009
	char *p;	
Packit Service 501009
	int c ATTRIBUTE_UNUSED; 
Packit Service 501009
	char *arglist[MAXARGS];
Packit Service 501009
	char buf[BUFSIZE];
Packit Service 501009
	
Packit Service 501009
	retbuf[0] = NULLCHAR;
Packit Service 501009
Packit Service 501009
	open_tmpfile();
Packit Service 501009
	if (dump_enumerator_list("bpf_map_type")) {
Packit Service 501009
		rewind(pc->tmpfile);
Packit Service 501009
		while (fgets(buf, BUFSIZE, pc->tmpfile)) {
Packit Service 501009
			if (!strstr(buf, " = "))
Packit Service 501009
				continue;
Packit Service 501009
			c = parse_line(buf, arglist);
Packit Service 501009
			if (atoi(arglist[2]) == map_type) {
Packit Service 501009
				p = arglist[0];
Packit Service 501009
				p += strlen("BPF_MAP_TYPE_");
Packit Service 501009
				strcpy(retbuf, p);
Packit Service 501009
				break;
Packit Service 501009
			}
Packit Service 501009
		}
Packit Service 501009
	} 
Packit Service 501009
Packit Service 501009
	close_tmpfile();
Packit Service 501009
	return retbuf;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static char *
Packit Service 501009
bpf_prog_used_maps(int idx, char *retbuf)
Packit Service 501009
{
Packit Service 501009
	int i, m, cnt;
Packit Service 501009
	struct bpf_info *bpf = &bpf_info;
Packit Service 501009
	uint used_map_cnt;
Packit Service 501009
	ulong used_maps, map;
Packit Service 501009
Packit Service 501009
	retbuf[0] = NULLCHAR;
Packit Service 501009
Packit Service 501009
	used_map_cnt = UINT(bpf->bpf_prog_aux_buf + OFFSET(bpf_prog_aux_used_map_cnt));
Packit Service 501009
	used_maps = ULONG(bpf->bpf_prog_aux_buf + OFFSET(bpf_prog_aux_used_maps));
Packit Service 501009
Packit Service 501009
	for (i = cnt = 0; i < used_map_cnt; i++) {
Packit Service 501009
		if (!readmem(used_maps + (sizeof(ulong)*i), KVADDR, &map,
Packit Service 501009
		    sizeof(ulong), "bpf_prog_aux.used_maps", RETURN_ON_ERROR))
Packit Service 501009
			return retbuf;
Packit Service 501009
		for (m = 0; m < bpf->maps; m++) {
Packit Service 501009
			if (map == (ulong)bpf->maplist[m].value) {
Packit Service 501009
				sprintf(&retbuf[strlen(retbuf)], "%s%ld", 
Packit Service 501009
					strlen(retbuf) ? "," : "",
Packit Service 501009
					bpf->maplist[m].index);
Packit Service 501009
			}
Packit Service 501009
		}
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	return retbuf;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static char *
Packit Service 501009
bpf_prog_tag_string(char *tag, char *buf)
Packit Service 501009
{
Packit Service 501009
	int i;
Packit Service 501009
Packit Service 501009
	buf[0] = NULLCHAR;
Packit Service 501009
	for (i = 0; i < 8; i++)
Packit Service 501009
		sprintf(&buf[strlen(buf)], "%02x", (unsigned char)tag[i]);
Packit Service 501009
Packit Service 501009
	return buf;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static void
Packit Service 501009
bpf_prog_gpl_compatible(char *retbuf, ulong bpf_prog)
Packit Service 501009
{
Packit Service 501009
	char buf[BUFSIZE];
Packit Service 501009
Packit Service 501009
	sprintf(retbuf, "(unknown)");
Packit Service 501009
Packit Service 501009
	open_tmpfile();
Packit Service 501009
        sprintf(buf, "p (*(struct bpf_prog *)0x%lx).gpl_compatible", bpf_prog);
Packit Service 501009
	gdb_pass_through(buf, NULL, GNU_RETURN_ON_ERROR);
Packit Service 501009
	rewind(pc->tmpfile);
Packit Service 501009
	while (fgets(buf, BUFSIZE, pc->tmpfile)) {
Packit Service 501009
		if (strstr(buf, " = 1")) {
Packit Service 501009
			sprintf(retbuf, "yes");
Packit Service 501009
			break;
Packit Service 501009
		} else if (strstr(buf, " = 0")) {
Packit Service 501009
			sprintf(retbuf, "no");
Packit Service 501009
			break;
Packit Service 501009
		}
Packit Service 501009
	}
Packit Service 501009
	close_tmpfile();
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
Packit Service 501009
// #include <linux/bpf_common.h>
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  Taken from: "/usr/include/linux/bpf_common.h"
Packit Service 501009
 */
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  bpf_common.h
Packit Service 501009
 */
Packit Service 501009
Packit Service 501009
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
Packit Service 501009
#ifndef __LINUX_BPF_COMMON_H__
Packit Service 501009
#define __LINUX_BPF_COMMON_H__
Packit Service 501009
Packit Service 501009
/* Instruction classes */
Packit Service 501009
#define BPF_CLASS(code) ((code) & 0x07)
Packit Service 501009
#define		BPF_LD		0x00
Packit Service 501009
#define		BPF_LDX		0x01
Packit Service 501009
#define		BPF_ST		0x02
Packit Service 501009
#define		BPF_STX		0x03
Packit Service 501009
#define		BPF_ALU		0x04
Packit Service 501009
#define		BPF_JMP		0x05
Packit Service 501009
#define		BPF_RET		0x06
Packit Service 501009
#define		BPF_MISC        0x07
Packit Service 501009
Packit Service 501009
/* ld/ldx fields */
Packit Service 501009
#define BPF_SIZE(code)  ((code) & 0x18)
Packit Service 501009
#define		BPF_W		0x00 /* 32-bit */
Packit Service 501009
#define		BPF_H		0x08 /* 16-bit */
Packit Service 501009
#define		BPF_B		0x10 /*  8-bit */
Packit Service 501009
/* eBPF		BPF_DW		0x18    64-bit */
Packit Service 501009
#define BPF_MODE(code)  ((code) & 0xe0)
Packit Service 501009
#define		BPF_IMM		0x00
Packit Service 501009
#define		BPF_ABS		0x20
Packit Service 501009
#define		BPF_IND		0x40
Packit Service 501009
#define		BPF_MEM		0x60
Packit Service 501009
#define		BPF_LEN		0x80
Packit Service 501009
#define		BPF_MSH		0xa0
Packit Service 501009
Packit Service 501009
/* alu/jmp fields */
Packit Service 501009
#define BPF_OP(code)    ((code) & 0xf0)
Packit Service 501009
#define		BPF_ADD		0x00
Packit Service 501009
#define		BPF_SUB		0x10
Packit Service 501009
#define		BPF_MUL		0x20
Packit Service 501009
#define		BPF_DIV		0x30
Packit Service 501009
#define		BPF_OR		0x40
Packit Service 501009
#define		BPF_AND		0x50
Packit Service 501009
#define		BPF_LSH		0x60
Packit Service 501009
#define		BPF_RSH		0x70
Packit Service 501009
#define		BPF_NEG		0x80
Packit Service 501009
#define		BPF_MOD		0x90
Packit Service 501009
#define		BPF_XOR		0xa0
Packit Service 501009
Packit Service 501009
#define		BPF_JA		0x00
Packit Service 501009
#define		BPF_JEQ		0x10
Packit Service 501009
#define		BPF_JGT		0x20
Packit Service 501009
#define		BPF_JGE		0x30
Packit Service 501009
#define		BPF_JSET        0x40
Packit Service 501009
#define BPF_SRC(code)   ((code) & 0x08)
Packit Service 501009
#define		BPF_K		0x00
Packit Service 501009
#define		BPF_X		0x08
Packit Service 501009
Packit Service 501009
#ifndef BPF_MAXINSNS
Packit Service 501009
#define BPF_MAXINSNS 4096
Packit Service 501009
#endif
Packit Service 501009
Packit Service 501009
#endif /* __LINUX_BPF_COMMON_H__ */
Packit Service 501009
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  Taken from: /usr/include/asm-generic/int-ll64.h
Packit Service 501009
 */
Packit Service 501009
typedef unsigned char __u8;
Packit Service 501009
typedef __signed__ short __s16;
Packit Service 501009
typedef __signed__ int __s32;
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  Taken from: "/usr/include/linux/bpf.h"
Packit Service 501009
 */
Packit Service 501009
Packit Service 501009
/* Extended instruction set based on top of classic BPF */
Packit Service 501009
Packit Service 501009
/* instruction classes */
Packit Service 501009
#define BPF_ALU64	0x07	/* alu mode in double word width */
Packit Service 501009
Packit Service 501009
/* ld/ldx fields */
Packit Service 501009
#define BPF_DW		0x18	/* double word (64-bit) */
Packit Service 501009
#define BPF_XADD	0xc0	/* exclusive add */
Packit Service 501009
Packit Service 501009
/* alu/jmp fields */
Packit Service 501009
#define BPF_MOV		0xb0	/* mov reg to reg */
Packit Service 501009
#define BPF_ARSH	0xc0	/* sign extending arithmetic shift right */
Packit Service 501009
Packit Service 501009
/* change endianness of a register */
Packit Service 501009
#define BPF_END		0xd0	/* flags for endianness conversion: */
Packit Service 501009
#define BPF_TO_LE	0x00	/* convert to little-endian */
Packit Service 501009
#define BPF_TO_BE	0x08	/* convert to big-endian */
Packit Service 501009
#define BPF_FROM_LE	BPF_TO_LE
Packit Service 501009
#define BPF_FROM_BE	BPF_TO_BE
Packit Service 501009
Packit Service 501009
/* jmp encodings */
Packit Service 501009
#define BPF_JNE		0x50	/* jump != */
Packit Service 501009
#define BPF_JLT		0xa0	/* LT is unsigned, '<' */
Packit Service 501009
#define BPF_JLE		0xb0	/* LE is unsigned, '<=' */
Packit Service 501009
#define BPF_JSGT	0x60	/* SGT is signed '>', GT in x86 */
Packit Service 501009
#define BPF_JSGE	0x70	/* SGE is signed '>=', GE in x86 */
Packit Service 501009
#define BPF_JSLT	0xc0	/* SLT is signed, '<' */
Packit Service 501009
#define BPF_JSLE	0xd0	/* SLE is signed, '<=' */
Packit Service 501009
#define BPF_CALL	0x80	/* function call */
Packit Service 501009
#define BPF_EXIT	0x90	/* function return */
Packit Service 501009
Packit Service 501009
/* Register numbers */
Packit Service 501009
enum {
Packit Service 501009
	BPF_REG_0 = 0,
Packit Service 501009
	BPF_REG_1,
Packit Service 501009
	BPF_REG_2,
Packit Service 501009
	BPF_REG_3,
Packit Service 501009
	BPF_REG_4,
Packit Service 501009
	BPF_REG_5,
Packit Service 501009
	BPF_REG_6,
Packit Service 501009
	BPF_REG_7,
Packit Service 501009
	BPF_REG_8,
Packit Service 501009
	BPF_REG_9,
Packit Service 501009
	BPF_REG_10,
Packit Service 501009
	__MAX_BPF_REG,
Packit Service 501009
};
Packit Service 501009
Packit Service 501009
struct bpf_insn {
Packit Service 501009
        __u8    code;           /* opcode */
Packit Service 501009
        __u8    dst_reg:4;      /* dest register */
Packit Service 501009
        __u8    src_reg:4;      /* source register */
Packit Service 501009
        __s16   off;            /* signed offset */
Packit Service 501009
        __s32   imm;            /* signed immediate constant */
Packit Service 501009
};
Packit Service 501009
Packit Service 501009
/* instruction classes */
Packit Service 501009
#define BPF_ALU64       0x07    /* alu mode in double word width */
Packit Service 501009
Packit Service 501009
/* ld/ldx fields */
Packit Service 501009
#define BPF_DW          0x18    /* double word (64-bit) */
Packit Service 501009
#define BPF_XADD        0xc0    /* exclusive add */
Packit Service 501009
Packit Service 501009
/* alu/jmp fields */
Packit Service 501009
#define BPF_MOV         0xb0    /* mov reg to reg */
Packit Service 501009
#define BPF_ARSH        0xc0    /* sign extending arithmetic shift right */
Packit Service 501009
Packit Service 501009
/* change endianness of a register */
Packit Service 501009
#define BPF_END         0xd0    /* flags for endianness conversion: */
Packit Service 501009
#define BPF_TO_LE       0x00    /* convert to little-endian */
Packit Service 501009
#define BPF_TO_BE       0x08    /* convert to big-endian */
Packit Service 501009
#define BPF_FROM_LE     BPF_TO_LE
Packit Service 501009
#define BPF_FROM_BE     BPF_TO_BE
Packit Service 501009
Packit Service 501009
/* when bpf_ldimm64->src_reg == BPF_PSEUDO_MAP_FD, bpf_ldimm64->imm == fd */
Packit Service 501009
#define BPF_PSEUDO_MAP_FD       1
Packit Service 501009
Packit Service 501009
/* when bpf_call->src_reg == BPF_PSEUDO_CALL, bpf_call->imm == pc-relative
Packit Service 501009
 * offset to another bpf function
Packit Service 501009
 */
Packit Service 501009
#define BPF_PSEUDO_CALL         1
Packit Service 501009
Packit Service 501009
Packit Service 501009
Packit Service 501009
Packit Service 501009
static void fprint_hex(FILE *, void *, unsigned int, const char *);
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  Taken from: tools/bpf/bpftool/main.c
Packit Service 501009
 */
Packit Service 501009
void fprint_hex(FILE *f, void *arg, unsigned int n, const char *sep)
Packit Service 501009
{
Packit Service 501009
	unsigned char *data = arg;
Packit Service 501009
	unsigned int i;
Packit Service 501009
Packit Service 501009
	for (i = 0; i < n; i++) {
Packit Service 501009
		const char *pfx = "";
Packit Service 501009
Packit Service 501009
		if (!i)
Packit Service 501009
			/* nothing */;
Packit Service 501009
		else if (!(i % 16))
Packit Service 501009
			fprintf(f, "\n");
Packit Service 501009
		else if (!(i % 8))
Packit Service 501009
			fprintf(f, "  ");
Packit Service 501009
		else
Packit Service 501009
			pfx = sep;
Packit Service 501009
Packit Service 501009
		fprintf(f, "%s%02hhx", i ? pfx : "", data[i]);
Packit Service 501009
	}
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
Packit Service 501009
Packit Service 501009
static void
Packit Service 501009
dump_bpf_insn(struct bpf_insn *insn)
Packit Service 501009
{
Packit Service 501009
	fprintf(fp, "          code: 0x%x / %d\n", insn->code, insn->code);
Packit Service 501009
	fprintf(fp, "       dst_reg: 0x%x / %d\n", insn->dst_reg, insn->dst_reg);
Packit Service 501009
	fprintf(fp, "       src_reg: 0x%x / %d\n", insn->src_reg, insn->src_reg);
Packit Service 501009
	fprintf(fp, "           off: 0x%x / %d\n", insn->off, insn->off);
Packit Service 501009
	fprintf(fp, "           imm: 0x%x / %d\n", insn->imm, insn->imm);
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static void print_bpf_insn(struct bpf_insn *, int);
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  Adapted from: "tools/bpf/bpftool/prog.c"
Packit Service 501009
 */
Packit Service 501009
static void 
Packit Service 501009
dump_xlated_plain(void *buf, unsigned int len, int opcodes)
Packit Service 501009
{
Packit Service 501009
	struct bpf_insn *insn = buf;
Packit Service 501009
	int double_insn = FALSE;
Packit Service 501009
	unsigned int i;
Packit Service 501009
Packit Service 501009
	for (i = 0; i < len / sizeof(*insn); i++) {
Packit Service 501009
		if (double_insn) {
Packit Service 501009
			double_insn = FALSE;
Packit Service 501009
			continue;
Packit Service 501009
		}
Packit Service 501009
Packit Service 501009
		double_insn = insn[i].code == (BPF_LD | BPF_IMM | BPF_DW);
Packit Service 501009
Packit Service 501009
		fprintf(fp, "% 4d: ", i);
Packit Service 501009
		print_bpf_insn(insn + i, TRUE);
Packit Service 501009
Packit Service 501009
		if (opcodes) {
Packit Service 501009
			fprintf(fp, "       ");
Packit Service 501009
			fprint_hex(fp, insn + i, 8, " ");
Packit Service 501009
			if (double_insn && i < len - 1) {
Packit Service 501009
				fprintf(fp, " ");
Packit Service 501009
				fprint_hex(fp, insn + i + 1, 8, " ");
Packit Service 501009
			}
Packit Service 501009
			fprintf(fp, "\n");
Packit Service 501009
		}
Packit Service 501009
Packit Service 501009
		if (CRASHDEBUG(1))
Packit Service 501009
			dump_bpf_insn(insn + i);
Packit Service 501009
	}
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  Adapted from: kernel/bpf/disasm.c
Packit Service 501009
 */
Packit Service 501009
Packit Service 501009
const char *const bpf_class_string[8] = {
Packit Service 501009
	[BPF_LD]    = "ld",
Packit Service 501009
	[BPF_LDX]   = "ldx",
Packit Service 501009
	[BPF_ST]    = "st",
Packit Service 501009
	[BPF_STX]   = "stx",
Packit Service 501009
	[BPF_ALU]   = "alu",
Packit Service 501009
	[BPF_JMP]   = "jmp",
Packit Service 501009
	[BPF_RET]   = "BUG",
Packit Service 501009
	[BPF_ALU64] = "alu64",
Packit Service 501009
};
Packit Service 501009
Packit Service 501009
const char *const bpf_alu_string[16] = {
Packit Service 501009
	[BPF_ADD >> 4]  = "+=",
Packit Service 501009
	[BPF_SUB >> 4]  = "-=",
Packit Service 501009
	[BPF_MUL >> 4]  = "*=",
Packit Service 501009
	[BPF_DIV >> 4]  = "/=",
Packit Service 501009
	[BPF_OR  >> 4]  = "|=",
Packit Service 501009
	[BPF_AND >> 4]  = "&=",
Packit Service 501009
	[BPF_LSH >> 4]  = "<<=",
Packit Service 501009
	[BPF_RSH >> 4]  = ">>=",
Packit Service 501009
	[BPF_NEG >> 4]  = "neg",
Packit Service 501009
	[BPF_MOD >> 4]  = "%=",
Packit Service 501009
	[BPF_XOR >> 4]  = "^=",
Packit Service 501009
	[BPF_MOV >> 4]  = "=",
Packit Service 501009
	[BPF_ARSH >> 4] = "s>>=",
Packit Service 501009
	[BPF_END >> 4]  = "endian",
Packit Service 501009
};
Packit Service 501009
Packit Service 501009
static const char *const bpf_ldst_string[] = {
Packit Service 501009
	[BPF_W >> 3]  = "u32",
Packit Service 501009
	[BPF_H >> 3]  = "u16",
Packit Service 501009
	[BPF_B >> 3]  = "u8",
Packit Service 501009
	[BPF_DW >> 3] = "u64",
Packit Service 501009
};
Packit Service 501009
Packit Service 501009
static const char *const bpf_jmp_string[16] = {
Packit Service 501009
	[BPF_JA >> 4]   = "jmp",
Packit Service 501009
	[BPF_JEQ >> 4]  = "==",
Packit Service 501009
	[BPF_JGT >> 4]  = ">",
Packit Service 501009
	[BPF_JLT >> 4]  = "<",
Packit Service 501009
	[BPF_JGE >> 4]  = ">=",
Packit Service 501009
	[BPF_JLE >> 4]  = "<=",
Packit Service 501009
	[BPF_JSET >> 4] = "&",
Packit Service 501009
	[BPF_JNE >> 4]  = "!=",
Packit Service 501009
	[BPF_JSGT >> 4] = "s>",
Packit Service 501009
	[BPF_JSLT >> 4] = "s<",
Packit Service 501009
	[BPF_JSGE >> 4] = "s>=",
Packit Service 501009
	[BPF_JSLE >> 4] = "s<=",
Packit Service 501009
	[BPF_CALL >> 4] = "call",
Packit Service 501009
	[BPF_EXIT >> 4] = "exit",
Packit Service 501009
};
Packit Service 501009
Packit Service 501009
typedef unsigned char u8;
Packit Service 501009
typedef unsigned int u32;
Packit Service 501009
Packit Service 501009
static const char *__func_imm_name(const struct bpf_insn *insn,
Packit Service 501009
                                   uint64_t full_imm, char *buff, size_t len)
Packit Service 501009
{
Packit Service 501009
	int m;
Packit Service 501009
	struct bpf_info *bpf = &bpf_info;
Packit Service 501009
Packit Service 501009
	for (m = 0; m < bpf->maps; m++) {
Packit Service 501009
		if (full_imm == (ulong)bpf->maplist[m].value) {
Packit Service 501009
			sprintf(buff, "map[id:%ld]", 
Packit Service 501009
				bpf->maplist[m].index);
Packit Service 501009
			if (CRASHDEBUG(1))
Packit Service 501009
				sprintf(&buff[strlen(buff)], " (%lx)",
Packit Service 501009
					(ulong)bpf->maplist[m].value); 
Packit Service 501009
			return buff;
Packit Service 501009
		}
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	snprintf(buff, len, "0x%llx", (unsigned long long)full_imm);
Packit Service 501009
	return buff;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static char *__func_get_name(const struct bpf_insn *insn,
Packit Service 501009
                                   char *buff, size_t len)
Packit Service 501009
{
Packit Service 501009
	long __BPF_FUNC_MAX_ID;
Packit Service 501009
	char func_id_str[BUFSIZE];
Packit Service 501009
	ulong func_id_ptr;
Packit Service 501009
	struct syment *sp;
Packit Service 501009
	ulong offset;
Packit Service 501009
Packit Service 501009
	if (!enumerator_value("__BPF_FUNC_MAX_ID", &__BPF_FUNC_MAX_ID))
Packit Service 501009
		return buff;
Packit Service 501009
Packit Service 501009
	if (insn->src_reg != BPF_PSEUDO_CALL &&
Packit Service 501009
	    insn->imm >= 0 && insn->imm < __BPF_FUNC_MAX_ID) {
Packit Service 501009
//              return func_id_str[insn->imm];
Packit Service 501009
		if (!readmem(symbol_value("func_id_str") + (insn->imm * sizeof(void *)), 
Packit Service 501009
		    KVADDR, &func_id_ptr, sizeof(void *), "func_id_str pointer", 
Packit Service 501009
		    QUIET|RETURN_ON_ERROR))
Packit Service 501009
			error(FATAL, "cannot read func_id_str[]");
Packit Service 501009
		if (!read_string(func_id_ptr, func_id_str, BUFSIZE-1))
Packit Service 501009
			error(FATAL, "cannot read func_id_str[] string");
Packit Service 501009
		sprintf(buff, "%s", func_id_str);
Packit Service 501009
		return buff;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if ((insn->src_reg != BPF_PSEUDO_CALL) &&
Packit Service 501009
	    (sp = value_search(symbol_value("__bpf_call_base") + insn->imm, &offset)) && 
Packit Service 501009
	    !offset)
Packit Service 501009
		return(sp->name);
Packit Service 501009
Packit Service 501009
	if (insn->src_reg == BPF_PSEUDO_CALL)
Packit Service 501009
		snprintf(buff, len, "%+d", insn->imm);
Packit Service 501009
Packit Service 501009
	return buff;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
Packit Service 501009
static void 
Packit Service 501009
print_bpf_insn(struct bpf_insn *insn, int allow_ptr_leaks)
Packit Service 501009
{
Packit Service 501009
	__u8 class = BPF_CLASS(insn->code);
Packit Service 501009
Packit Service 501009
	if (class == BPF_ALU || class == BPF_ALU64) {
Packit Service 501009
		if (BPF_OP(insn->code) == BPF_END) {
Packit Service 501009
			if (class == BPF_ALU64)
Packit Service 501009
				fprintf(fp, "BUG_alu64_%02x\n", insn->code);
Packit Service 501009
			else
Packit Service 501009
//				print_bpf_end_insn(verbose, env, insn);
Packit Service 501009
				fprintf(fp, "(%02x) r%d = %s%d r%d\n", insn->code, insn->dst_reg,
Packit Service 501009
					BPF_SRC(insn->code) == BPF_TO_BE ? "be" : "le",
Packit Service 501009
					insn->imm, insn->dst_reg);
Packit Service 501009
Packit Service 501009
		} else if (BPF_OP(insn->code) == BPF_NEG) {
Packit Service 501009
			fprintf(fp, "(%02x) r%d = %s-r%d\n",
Packit Service 501009
				insn->code, insn->dst_reg,
Packit Service 501009
				class == BPF_ALU ? "(u32) " : "",
Packit Service 501009
				insn->dst_reg);
Packit Service 501009
		} else if (BPF_SRC(insn->code) == BPF_X) {
Packit Service 501009
			fprintf(fp, "(%02x) %sr%d %s %sr%d\n",
Packit Service 501009
				insn->code, class == BPF_ALU ? "(u32) " : "",
Packit Service 501009
				insn->dst_reg,
Packit Service 501009
				bpf_alu_string[BPF_OP(insn->code) >> 4],
Packit Service 501009
				class == BPF_ALU ? "(u32) " : "",
Packit Service 501009
				insn->src_reg);
Packit Service 501009
		} else {
Packit Service 501009
			fprintf(fp, "(%02x) %sr%d %s %s%d\n",
Packit Service 501009
				insn->code, class == BPF_ALU ? "(u32) " : "",
Packit Service 501009
				insn->dst_reg,
Packit Service 501009
				bpf_alu_string[BPF_OP(insn->code) >> 4],
Packit Service 501009
				class == BPF_ALU ? "(u32) " : "",
Packit Service 501009
				insn->imm);
Packit Service 501009
		}
Packit Service 501009
	} else if (class == BPF_STX) {
Packit Service 501009
		if (BPF_MODE(insn->code) == BPF_MEM)
Packit Service 501009
			fprintf(fp, "(%02x) *(%s *)(r%d %+d) = r%d\n",
Packit Service 501009
				insn->code,
Packit Service 501009
				bpf_ldst_string[BPF_SIZE(insn->code) >> 3],
Packit Service 501009
				insn->dst_reg,
Packit Service 501009
				insn->off, insn->src_reg);
Packit Service 501009
		else if (BPF_MODE(insn->code) == BPF_XADD)
Packit Service 501009
			fprintf(fp, "(%02x) lock *(%s *)(r%d %+d) += r%d\n",
Packit Service 501009
				insn->code,
Packit Service 501009
				bpf_ldst_string[BPF_SIZE(insn->code) >> 3],
Packit Service 501009
				insn->dst_reg, insn->off,
Packit Service 501009
				insn->src_reg);
Packit Service 501009
		else
Packit Service 501009
			fprintf(fp, "BUG_%02x\n", insn->code);
Packit Service 501009
	} else if (class == BPF_ST) {
Packit Service 501009
		if (BPF_MODE(insn->code) != BPF_MEM) {
Packit Service 501009
			fprintf(fp, "BUG_st_%02x\n", insn->code);
Packit Service 501009
			return;
Packit Service 501009
		}
Packit Service 501009
		fprintf(fp, "(%02x) *(%s *)(r%d %+d) = %d\n",
Packit Service 501009
			insn->code,
Packit Service 501009
			bpf_ldst_string[BPF_SIZE(insn->code) >> 3],
Packit Service 501009
			insn->dst_reg,
Packit Service 501009
			insn->off, insn->imm);
Packit Service 501009
	} else if (class == BPF_LDX) {
Packit Service 501009
		if (BPF_MODE(insn->code) != BPF_MEM) {
Packit Service 501009
			fprintf(fp, "BUG_ldx_%02x\n", insn->code);
Packit Service 501009
			return;
Packit Service 501009
		}
Packit Service 501009
		fprintf(fp, "(%02x) r%d = *(%s *)(r%d %+d)\n",
Packit Service 501009
			insn->code, insn->dst_reg,
Packit Service 501009
			bpf_ldst_string[BPF_SIZE(insn->code) >> 3],
Packit Service 501009
			insn->src_reg, insn->off);
Packit Service 501009
	} else if (class == BPF_LD) {
Packit Service 501009
		if (BPF_MODE(insn->code) == BPF_ABS) {
Packit Service 501009
			fprintf(fp, "(%02x) r0 = *(%s *)skb[%d]\n",
Packit Service 501009
				insn->code,
Packit Service 501009
				bpf_ldst_string[BPF_SIZE(insn->code) >> 3],
Packit Service 501009
				insn->imm);
Packit Service 501009
		} else if (BPF_MODE(insn->code) == BPF_IND) {
Packit Service 501009
			fprintf(fp, "(%02x) r0 = *(%s *)skb[r%d + %d]\n",
Packit Service 501009
				insn->code,
Packit Service 501009
				bpf_ldst_string[BPF_SIZE(insn->code) >> 3],
Packit Service 501009
				insn->src_reg, insn->imm);
Packit Service 501009
		} else if (BPF_MODE(insn->code) == BPF_IMM &&
Packit Service 501009
			   BPF_SIZE(insn->code) == BPF_DW) {
Packit Service 501009
			/* At this point, we already made sure that the second
Packit Service 501009
			 * part of the ldimm64 insn is accessible.
Packit Service 501009
			 */
Packit Service 501009
			uint64_t imm = ((uint64_t)(insn + 1)->imm << 32) | (u32)insn->imm;
Packit Service 501009
			int map_ptr = insn->src_reg == BPF_PSEUDO_MAP_FD;
Packit Service 501009
			char tmp[64];
Packit Service 501009
Packit Service 501009
			if (map_ptr && !allow_ptr_leaks)
Packit Service 501009
				imm = 0;
Packit Service 501009
Packit Service 501009
			fprintf(fp, "(%02x) r%d = %s\n",
Packit Service 501009
				insn->code, insn->dst_reg,
Packit Service 501009
				__func_imm_name(insn, imm,
Packit Service 501009
						tmp, sizeof(tmp)));
Packit Service 501009
		} else {
Packit Service 501009
			fprintf(fp, "BUG_ld_%02x\n", insn->code);
Packit Service 501009
			return;
Packit Service 501009
		}
Packit Service 501009
	} else if (class == BPF_JMP) {
Packit Service 501009
		u8 opcode = BPF_OP(insn->code);
Packit Service 501009
Packit Service 501009
		if (opcode == BPF_CALL) {
Packit Service 501009
			char tmp[64];
Packit Service 501009
Packit Service 501009
			if (insn->src_reg == BPF_PSEUDO_CALL) {
Packit Service 501009
				fprintf(fp, "(%02x) call pc%s\n",
Packit Service 501009
					insn->code,
Packit Service 501009
					__func_get_name(insn,
Packit Service 501009
							tmp, sizeof(tmp)));
Packit Service 501009
			} else {
Packit Service 501009
				strcpy(tmp, "unknown");
Packit Service 501009
				fprintf(fp, "(%02x) call %s#%d\n", insn->code,
Packit Service 501009
					__func_get_name(insn,
Packit Service 501009
							tmp, sizeof(tmp)),
Packit Service 501009
					insn->imm);
Packit Service 501009
			}
Packit Service 501009
		} else if (insn->code == (BPF_JMP | BPF_JA)) {
Packit Service 501009
			fprintf(fp, "(%02x) goto pc%+d\n",
Packit Service 501009
				insn->code, insn->off);
Packit Service 501009
		} else if (insn->code == (BPF_JMP | BPF_EXIT)) {
Packit Service 501009
			fprintf(fp, "(%02x) exit\n", insn->code);
Packit Service 501009
		} else if (BPF_SRC(insn->code) == BPF_X) {
Packit Service 501009
			fprintf(fp, "(%02x) if r%d %s r%d goto pc%+d\n",
Packit Service 501009
				insn->code, insn->dst_reg,
Packit Service 501009
				bpf_jmp_string[BPF_OP(insn->code) >> 4],
Packit Service 501009
				insn->src_reg, insn->off);
Packit Service 501009
		} else {
Packit Service 501009
			fprintf(fp, "(%02x) if r%d %s 0x%x goto pc%+d\n",
Packit Service 501009
				insn->code, insn->dst_reg,
Packit Service 501009
				bpf_jmp_string[BPF_OP(insn->code) >> 4],
Packit Service 501009
				insn->imm, insn->off);
Packit Service 501009
		}
Packit Service 501009
	} else {
Packit Service 501009
		fprintf(fp, "(%02x) %s\n",
Packit Service 501009
			insn->code, bpf_class_string[class]);
Packit Service 501009
	}
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static void 
Packit Service 501009
print_boot_time(unsigned long long nsecs, char *buf, unsigned int size)
Packit Service 501009
{
Packit Service 501009
#ifdef CLOCK_BOOTTIME
Packit Service 501009
	struct timespec real_time_ts, boot_time_ts;
Packit Service 501009
	time_t wallclock_secs;
Packit Service 501009
	struct tm load_tm;
Packit Service 501009
Packit Service 501009
	buf[--size] = '\0';
Packit Service 501009
Packit Service 501009
	if (clock_gettime(CLOCK_REALTIME, &real_time_ts) ||
Packit Service 501009
	    clock_gettime(CLOCK_BOOTTIME, &boot_time_ts)) {
Packit Service 501009
		perror("Can't read clocks");
Packit Service 501009
		snprintf(buf, size, "%llu", nsecs / 1000000000);
Packit Service 501009
		return;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	wallclock_secs = (real_time_ts.tv_sec - boot_time_ts.tv_sec) +
Packit Service 501009
		nsecs / 1000000000;
Packit Service 501009
Packit Service 501009
	if (!localtime_r(&wallclock_secs, &load_tm)) {
Packit Service 501009
		snprintf(buf, size, "%llu", nsecs / 1000000000);
Packit Service 501009
		return;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
//	strftime(buf, size, "%b %d/%H:%M", &load_tm);
Packit Service 501009
	strftime(buf, size, "%a %b %d %H:%M:%S %Y", &load_tm);
Packit Service 501009
#else
Packit Service 501009
	sprintf(buf, "(unknown)");
Packit Service 501009
#endif
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  Borrow the old (pre-radix_tree) IDR facility code used by
Packit Service 501009
 *  the ipcs command.
Packit Service 501009
 */
Packit Service 501009
static int
Packit Service 501009
do_old_idr(int cmd, ulong idr, struct list_pair *lp)
Packit Service 501009
{
Packit Service 501009
	int i, max, cur, next_id, total = 0;
Packit Service 501009
	ulong entry;
Packit Service 501009
Packit Service 501009
	switch (cmd)
Packit Service 501009
	{
Packit Service 501009
	case IDR_ORIG_INIT:
Packit Service 501009
		ipcs_init();
Packit Service 501009
		break;
Packit Service 501009
Packit Service 501009
	case IDR_ORIG_COUNT:
Packit Service 501009
		readmem(idr + OFFSET(idr_cur), KVADDR, &cur, 
Packit Service 501009
			sizeof(int), "idr.cur", FAULT_ON_ERROR);
Packit Service 501009
		for (total = next_id = 0; next_id < cur; next_id++) {
Packit Service 501009
			entry = idr_find(idr, next_id);
Packit Service 501009
			if (entry == 0)
Packit Service 501009
				continue;
Packit Service 501009
			total++;
Packit Service 501009
		}
Packit Service 501009
		break;
Packit Service 501009
Packit Service 501009
	case IDR_ORIG_GATHER:
Packit Service 501009
		max = lp[0].index;
Packit Service 501009
		readmem(idr + OFFSET(idr_cur), KVADDR, &cur, 
Packit Service 501009
			sizeof(int), "idr.cur", FAULT_ON_ERROR);
Packit Service 501009
		for (i = total = next_id = 0; next_id < cur; next_id++) {
Packit Service 501009
			entry = idr_find(idr, next_id);
Packit Service 501009
			if (entry == 0)
Packit Service 501009
				continue;
Packit Service 501009
			total++;
Packit Service 501009
			lp[i].index = next_id;
Packit Service 501009
			lp[i].value = (void *)entry;
Packit Service 501009
			if (++i == max)
Packit Service 501009
				break;
Packit Service 501009
		}
Packit Service 501009
		break;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	return total;
Packit Service 501009
}