<commit_before>/**
 * BPF Disassembler
 *
 * Copyright (c) 2012 Red Hat <<EMAIL>>
 * Author: <NAME> <<EMAIL>>
 */

/*
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of version 2 of the GNU General Public License as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>

#include "bpf.h"

#define _OP_FMT			"%-3s"

/**
 * Decode the BPF operand
 * @param bpf the BPF instruction
 *
 * Decode the BPF operand and print it to stdout.
 *
 */
static void bpf_decode_op(const bpf_instr_raw *bpf)
{
	switch (bpf->code) {
		case BPF_LD+BPF_W+BPF_IMM:
		case BPF_LD+BPF_W+BPF_ABS:
		case BPF_LD+BPF_W+BPF_IND:
		case BPF_LD+BPF_W+BPF_MEM:
		case BPF_LD+BPF_W+BPF_LEN:
		case BPF_LD+BPF_W+BPF_MSH:
			printf(_OP_FMT, "ld");
			break;
		case BPF_LD+BPF_H+BPF_IMM:
		case BPF_LD+BPF_H+BPF_ABS:
		case BPF_LD+BPF_H+BPF_IND:
		case BPF_LD+BPF_H+BPF_MEM:
		case BPF_LD+BPF_H+BPF_LEN:
		case BPF_LD+BPF_H+BPF_MSH:
			printf(_OP_FMT, "ldh");
			break;
		case BPF_LD+BPF_B+BPF_IMM:
		case BPF_LD+BPF_B+BPF_ABS:
		case BPF_LD+BPF_B+BPF_IND:
		case BPF_LD+BPF_B+BPF_MEM:
		case BPF_LD+BPF_B+BPF_LEN:
		case BPF_LD+BPF_B+BPF_MSH:
			printf(_OP_FMT, "ldb");
			break;
		case BPF_LDX+BPF_W+BPF_IMM:
		case BPF_LDX+BPF_W+BPF_ABS:
		case BPF_LDX+BPF_W+BPF_IND:
		case BPF_LDX+BPF_W+BPF_MEM:
		case BPF_LDX+BPF_W+BPF_LEN:
		case BPF_LDX+BPF_W+BPF_MSH:
		case BPF_LDX+BPF_H+BPF_IMM:
		case BPF_LDX+BPF_H+BPF_ABS:
		case BPF_LDX+BPF_H+BPF_IND:
		case BPF_LDX+BPF_H+BPF_MEM:
		case BPF_LDX+BPF_H+BPF_LEN:
		case BPF_LDX+BPF_H+BPF_MSH:
		case BPF_LDX+BPF_B+BPF_IMM:
		case BPF_LDX+BPF_B+BPF_ABS:
		case BPF_LDX+BPF_B+BPF_IND:
		case BPF_LDX+BPF_B+BPF_MEM:
		case BPF_LDX+BPF_B+BPF_LEN:
		case BPF_LDX+BPF_B+BPF_MSH:
			printf(_OP_FMT, "ldx");
			break;
		case BPF_ST:
			printf(_OP_FMT, "st");
			break;
		case BPF_STX:
			printf(_OP_FMT, "stx");
			break;
		case BPF_ALU+BPF_ADD+BPF_K:
		case BPF_ALU+BPF_ADD+BPF_X:
			printf(_OP_FMT, "add");
			break;
		case BPF_ALU+BPF_SUB+BPF_K:
		case BPF_ALU+BPF_SUB+BPF_X:
			printf(_OP_FMT, "sub");
			break;
		case BPF_ALU+BPF_MUL+BPF_K:
		case BPF_ALU+BPF_MUL+BPF_X:
			printf(_OP_FMT, "mul");
			break;
		case BPF_ALU+BPF_DIV+BPF_K:
		case BPF_ALU+BPF_DIV+BPF_X:
			printf(_OP_FMT, "div");
			break;
		case BPF_ALU+BPF_OR+BPF_K:
		case BPF_ALU+BPF_OR+BPF_X:
			printf(_OP_FMT, "or");
			break;
		case BPF_ALU+BPF_AND+BPF_K:
		case BPF_ALU+BPF_AND+BPF_X:
			printf(_OP_FMT, "and");
			break;
		case BPF_ALU+BPF_LSH+BPF_K:
		case BPF_ALU+BPF_LSH+BPF_X:
			printf(_OP_FMT, "lsh");
			break;
		case BPF_ALU+BPF_RSH+BPF_K:
		case BPF_ALU+BPF_RSH+BPF_X:
			printf(_OP_FMT, "rsh");
			break;
		case BPF_ALU+BPF_NEG+BPF_K:
		case BPF_ALU+BPF_NEG+BPF_X:
			printf(_OP_FMT, "neg");
			break;
		case BPF_JMP+BPF_JA+BPF_K:
		case BPF_JMP+BPF_JA+BPF_X:
			printf(_OP_FMT, "jmp");
			break;
		case BPF_JMP+BPF_JEQ+BPF_K:
		case BPF_JMP+BPF_JEQ+BPF_X:
			printf(_OP_FMT, "jeq");
			break;
		case BPF_JMP+BPF_JGT+BPF_K:
		case BPF_JMP+BPF_JGT+BPF_X:
			printf(_OP_FMT, "jgt");
			break;
		case BPF_JMP+BPF_JGE+BPF_K:
		case BPF_JMP+BPF_JGE+BPF_X:
			printf(_OP_FMT, "jge");
			break;
		case BPF_JMP+BPF_JSET+BPF_K:
		case BPF_JMP+BPF_JSET+BPF_X:
			printf(_OP_FMT, "jset");
			break;
		case BPF_RET+BPF_K:
		case BPF_RET+BPF_X:
		case BPF_RET+BPF_A:
			printf(_OP_FMT, "ret");
			break;
		case BPF_MISC+BPF_TAX:
			printf(_OP_FMT, "tax");
			break;
		case BPF_MISC+BPF_TXA:
			printf(_OP_FMT, "txa");
			break;
		default:
			printf(_OP_FMT, "???");
	}
}

/**
 * Decode the BPF arguments (JT, JF, and K)
 * @param bpf the BPF instruction
 * @param line the current line number
 *
 * Decode the BPF arguments (JT, JF, and K) and print the relevant information
 * to stdout based on the operand.
 *
 */
static void bpf_decode_args(const bpf_instr_raw *bpf, unsigned int line)
{
	switch (BPF_CLASS(bpf->code)) {
		case BPF_LD:
		case BPF_LDX:
			switch (BPF_MODE(bpf->code)) {
				case BPF_ABS:
					printf("$data[%u]", bpf->k);
					break;
				case BPF_MEM:
					printf("$temp[%u]", bpf->k);
					break;
			}
			break;
		case BPF_ST:
		case BPF_STX:
			printf("$temp[%u]", bpf->k);
			break;
		case BPF_ALU:
			printf("%u", bpf->k);
			break;
		case BPF_JMP:
			if (BPF_OP(bpf->code) == BPF_JA) {
				printf("%.4u", (line + 1) + bpf->k);
			} else {
				printf("%-4u true:%.4u false:%.4u",
				       bpf->k,
				       (line + 1) + bpf->jt,
				       (line + 1) + bpf->jf);
			}
			break;
		case BPF_RET:
			if (BPF_RVAL(bpf->code) == BPF_A) {
				/* XXX - accumulator? */
				printf("$acc");
			} else if (BPF_SRC(bpf->code) == BPF_K) {
				uint32_t act = bpf->k & SECCOMP_RET_ACTION;
				uint32_t data = bpf->k & SECCOMP_RET_DATA;

				switch (act) {
				case SECCOMP_RET_KILL:
					printf("KILL");
					break;
				case SECCOMP_RET_TRAP:
					printf("TRAP");
					break;
				case SECCOMP_RET_ERRNO:
					printf("ERRNO(%u)", data);
					break;
				case SECCOMP_RET_TRACE:
					printf("TRACE(%u)", data);
					break;
				case SECCOMP_RET_ALLOW:
					printf("ALLOW");
					break;
				default:
					printf("0x%.8x", bpf->k);
				}
			} else if (BPF_SRC(bpf->code) == BPF_X) {
				/* XXX - any idea? */
				printf("???");
			}
			break;
		case BPF_MISC:
			break;
		default:
			printf("???");
	}
}

/**
 * Perform a simple decoding of the BPF program
 * @param file the BPF program
 *
 * Read the BPF program and display the instructions.  Returns zero on success,
 * negative values on failure.
 *
 */
static int bpf_decode(FILE *file)
{
	unsigned int line = 0;
	size_t len;
	bpf_instr_raw bpf;

	/* header */
	printf(" line  OP   JT   JF   K\n");
	printf("=================================\n");

	while ((len = fread(&bpf, sizeof(bpf), 1, file))) {
		printf(" %.4u: 0x%.2x 0x%.2x 0x%.2x 0x%.8x",
		       line, bpf.code, bpf.jt, bpf.jf, bpf.k);

		printf("   ");
		bpf_decode_op(&bpf);
		printf(" ");
		bpf_decode_args(&bpf, line);
		printf("\n");

		line++;
	}

	if (ferror(file))
		return errno;
	return 0;
}

/**
 * main
 */
int main(int argc, char *argv[])
{
	int rc;
	FILE *file;

	if (argc > 2) {
		fprintf(stderr, "usage: %s [<bpf_file>]\n", argv[0]);
		return EINVAL;
	}

	if (argc == 2) {
		file = fopen(argv[1], "r");
		if (file == NULL) {
			fprintf(stderr, "error: unable to open \"%s\" (%s)\n",
				argv[1], strerror(errno));
			return errno;
		}
	} else
		file = stdin;

	rc = bpf_decode(file);
	fclose(file);

	return rc;
}

<commit_msg>bpf_disasm: display the ALU bitmasks in hex<commit_after>/**
 * BPF Disassembler
 *
 * Copyright (c) 2012 Red Hat <<EMAIL>>
 * Author: <NAME> <<EMAIL>>
 */

/*
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of version 2 of the GNU General Public License as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>

#include "bpf.h"

#define _OP_FMT			"%-3s"

/**
 * Decode the BPF operand
 * @param bpf the BPF instruction
 *
 * Decode the BPF operand and print it to stdout.
 *
 */
static void bpf_decode_op(const bpf_instr_raw *bpf)
{
	switch (bpf->code) {
		case BPF_LD+BPF_W+BPF_IMM:
		case BPF_LD+BPF_W+BPF_ABS:
		case BPF_LD+BPF_W+BPF_IND:
		case BPF_LD+BPF_W+BPF_MEM:
		case BPF_LD+BPF_W+BPF_LEN:
		case BPF_LD+BPF_W+BPF_MSH:
			printf(_OP_FMT, "ld");
			break;
		case BPF_LD+BPF_H+BPF_IMM:
		case BPF_LD+BPF_H+BPF_ABS:
		case BPF_LD+BPF_H+BPF_IND:
		case BPF_LD+BPF_H+BPF_MEM:
		case BPF_LD+BPF_H+BPF_LEN:
		case BPF_LD+BPF_H+BPF_MSH:
			printf(_OP_FMT, "ldh");
			break;
		case BPF_LD+BPF_B+BPF_IMM:
		case BPF_LD+BPF_B+BPF_ABS:
		case BPF_LD+BPF_B+BPF_IND:
		case BPF_LD+BPF_B+BPF_MEM:
		case BPF_LD+BPF_B+BPF_LEN:
		case BPF_LD+BPF_B+BPF_MSH:
			printf(_OP_FMT, "ldb");
			break;
		case BPF_LDX+BPF_W+BPF_IMM:
		case BPF_LDX+BPF_W+BPF_ABS:
		case BPF_LDX+BPF_W+BPF_IND:
		case BPF_LDX+BPF_W+BPF_MEM:
		case BPF_LDX+BPF_W+BPF_LEN:
		case BPF_LDX+BPF_W+BPF_MSH:
		case BPF_LDX+BPF_H+BPF_IMM:
		case BPF_LDX+BPF_H+BPF_ABS:
		case BPF_LDX+BPF_H+BPF_IND:
		case BPF_LDX+BPF_H+BPF_MEM:
		case BPF_LDX+BPF_H+BPF_LEN:
		case BPF_LDX+BPF_H+BPF_MSH:
		case BPF_LDX+BPF_B+BPF_IMM:
		case BPF_LDX+BPF_B+BPF_ABS:
		case BPF_LDX+BPF_B+BPF_IND:
		case BPF_LDX+BPF_B+BPF_MEM:
		case BPF_LDX+BPF_B+BPF_LEN:
		case BPF_LDX+BPF_B+BPF_MSH:
			printf(_OP_FMT, "ldx");
			break;
		case BPF_ST:
			printf(_OP_FMT, "st");
			break;
		case BPF_STX:
			printf(_OP_FMT, "stx");
			break;
		case BPF_ALU+BPF_ADD+BPF_K:
		case BPF_ALU+BPF_ADD+BPF_X:
			printf(_OP_FMT, "add");
			break;
		case BPF_ALU+BPF_SUB+BPF_K:
		case BPF_ALU+BPF_SUB+BPF_X:
			printf(_OP_FMT, "sub");
			break;
		case BPF_ALU+BPF_MUL+BPF_K:
		case BPF_ALU+BPF_MUL+BPF_X:
			printf(_OP_FMT, "mul");
			break;
		case BPF_ALU+BPF_DIV+BPF_K:
		case BPF_ALU+BPF_DIV+BPF_X:
			printf(_OP_FMT, "div");
			break;
		case BPF_ALU+BPF_OR+BPF_K:
		case BPF_ALU+BPF_OR+BPF_X:
			printf(_OP_FMT, "or");
			break;
		case BPF_ALU+BPF_AND+BPF_K:
		case BPF_ALU+BPF_AND+BPF_X:
			printf(_OP_FMT, "and");
			break;
		case BPF_ALU+BPF_LSH+BPF_K:
		case BPF_ALU+BPF_LSH+BPF_X:
			printf(_OP_FMT, "lsh");
			break;
		case BPF_ALU+BPF_RSH+BPF_K:
		case BPF_ALU+BPF_RSH+BPF_X:
			printf(_OP_FMT, "rsh");
			break;
		case BPF_ALU+BPF_NEG+BPF_K:
		case BPF_ALU+BPF_NEG+BPF_X:
			printf(_OP_FMT, "neg");
			break;
		case BPF_JMP+BPF_JA+BPF_K:
		case BPF_JMP+BPF_JA+BPF_X:
			printf(_OP_FMT, "jmp");
			break;
		case BPF_JMP+BPF_JEQ+BPF_K:
		case BPF_JMP+BPF_JEQ+BPF_X:
			printf(_OP_FMT, "jeq");
			break;
		case BPF_JMP+BPF_JGT+BPF_K:
		case BPF_JMP+BPF_JGT+BPF_X:
			printf(_OP_FMT, "jgt");
			break;
		case BPF_JMP+BPF_JGE+BPF_K:
		case BPF_JMP+BPF_JGE+BPF_X:
			printf(_OP_FMT, "jge");
			break;
		case BPF_JMP+BPF_JSET+BPF_K:
		case BPF_JMP+BPF_JSET+BPF_X:
			printf(_OP_FMT, "jset");
			break;
		case BPF_RET+BPF_K:
		case BPF_RET+BPF_X:
		case BPF_RET+BPF_A:
			printf(_OP_FMT, "ret");
			break;
		case BPF_MISC+BPF_TAX:
			printf(_OP_FMT, "tax");
			break;
		case BPF_MISC+BPF_TXA:
			printf(_OP_FMT, "txa");
			break;
		default:
			printf(_OP_FMT, "???");
	}
}

/**
 * Decode the BPF arguments (JT, JF, and K)
 * @param bpf the BPF instruction
 * @param line the current line number
 *
 * Decode the BPF arguments (JT, JF, and K) and print the relevant information
 * to stdout based on the operand.
 *
 */
static void bpf_decode_args(const bpf_instr_raw *bpf, unsigned int line)
{
	switch (BPF_CLASS(bpf->code)) {
		case BPF_LD:
		case BPF_LDX:
			switch (BPF_MODE(bpf->code)) {
				case BPF_ABS:
					printf("$data[%u]", bpf->k);
					break;
				case BPF_MEM:
					printf("$temp[%u]", bpf->k);
					break;
			}
			break;
		case BPF_ST:
		case BPF_STX:
			printf("$temp[%u]", bpf->k);
			break;
		case BPF_ALU:
			if (BPF_SRC(bpf->code) == BPF_K) {
				switch (BPF_OP(bpf->code)) {
				case BPF_OR:
				case BPF_AND:
					printf("0x%.8x", bpf->k);
					break;
				default:
					printf("%u", bpf->k);
				}
			} else
				printf("%u", bpf->k);
			break;
		case BPF_JMP:
			if (BPF_OP(bpf->code) == BPF_JA) {
				printf("%.4u", (line + 1) + bpf->k);
			} else {
				printf("%-4u true:%.4u false:%.4u",
				       bpf->k,
				       (line + 1) + bpf->jt,
				       (line + 1) + bpf->jf);
			}
			break;
		case BPF_RET:
			if (BPF_RVAL(bpf->code) == BPF_A) {
				/* XXX - accumulator? */
				printf("$acc");
			} else if (BPF_SRC(bpf->code) == BPF_K) {
				uint32_t act = bpf->k & SECCOMP_RET_ACTION;
				uint32_t data = bpf->k & SECCOMP_RET_DATA;

				switch (act) {
				case SECCOMP_RET_KILL:
					printf("KILL");
					break;
				case SECCOMP_RET_TRAP:
					printf("TRAP");
					break;
				case SECCOMP_RET_ERRNO:
					printf("ERRNO(%u)", data);
					break;
				case SECCOMP_RET_TRACE:
					printf("TRACE(%u)", data);
					break;
				case SECCOMP_RET_ALLOW:
					printf("ALLOW");
					break;
				default:
					printf("0x%.8x", bpf->k);
				}
			} else if (BPF_SRC(bpf->code) == BPF_X) {
				/* XXX - any idea? */
				printf("???");
			}
			break;
		case BPF_MISC:
			break;
		default:
			printf("???");
	}
}

/**
 * Perform a simple decoding of the BPF program
 * @param file the BPF program
 *
 * Read the BPF program and display the instructions.  Returns zero on success,
 * negative values on failure.
 *
 */
static int bpf_decode(FILE *file)
{
	unsigned int line = 0;
	size_t len;
	bpf_instr_raw bpf;

	/* header */
	printf(" line  OP   JT   JF   K\n");
	printf("=================================\n");

	while ((len = fread(&bpf, sizeof(bpf), 1, file))) {
		printf(" %.4u: 0x%.2x 0x%.2x 0x%.2x 0x%.8x",
		       line, bpf.code, bpf.jt, bpf.jf, bpf.k);

		printf("   ");
		bpf_decode_op(&bpf);
		printf(" ");
		bpf_decode_args(&bpf, line);
		printf("\n");

		line++;
	}

	if (ferror(file))
		return errno;
	return 0;
}

/**
 * main
 */
int main(int argc, char *argv[])
{
	int rc;
	FILE *file;

	if (argc > 2) {
		fprintf(stderr, "usage: %s [<bpf_file>]\n", argv[0]);
		return EINVAL;
	}

	if (argc == 2) {
		file = fopen(argv[1], "r");
		if (file == NULL) {
			fprintf(stderr, "error: unable to open \"%s\" (%s)\n",
				argv[1], strerror(errno));
			return errno;
		}
	} else
		file = stdin;

	rc = bpf_decode(file);
	fclose(file);

	return rc;
}


{'fraction_non_alphanumeric': 0.14995076663384443, 'fraction_numerical': 0.005204670136446757, 'mean_word_length': 3.5326745298055466, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 79, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4468539', 'n_tokens_mistral': 7436, 'n_tokens_neox': 6404, 'n_words': 1322}