Merge branch 'bpftool-add-a-version-command-and-fix-several-items'
Jakub Kicinski says: ==================== tools: bpftool: add a "version" command, and fix several items Quentin says: The first seven patches of this series bring several minor fixes to bpftool. Please see individual commit logs for details. Last patch adds a "version" commands to bpftool, which is in fact the version of the kernel from which it was compiled. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
a8e8c0ecb4
|
@ -11,8 +11,8 @@ SYNOPSIS
|
||||||
========
|
========
|
||||||
|
|
||||||
| **bpftool** prog show [*PROG*]
|
| **bpftool** prog show [*PROG*]
|
||||||
| **bpftool** prog dump xlated *PROG* [file *FILE*] [opcodes]
|
| **bpftool** prog dump xlated *PROG* [{file *FILE* | opcodes }]
|
||||||
| **bpftool** prog dump jited *PROG* [file *FILE*] [opcodes]
|
| **bpftool** prog dump jited *PROG* [{file *FILE* | opcodes }]
|
||||||
| **bpftool** prog pin *PROG* *FILE*
|
| **bpftool** prog pin *PROG* *FILE*
|
||||||
| **bpftool** prog help
|
| **bpftool** prog help
|
||||||
|
|
|
|
||||||
|
@ -28,14 +28,14 @@ DESCRIPTION
|
||||||
Output will start with program ID followed by program type and
|
Output will start with program ID followed by program type and
|
||||||
zero or more named attributes (depending on kernel version).
|
zero or more named attributes (depending on kernel version).
|
||||||
|
|
||||||
**bpftool prog dump xlated** *PROG* [**file** *FILE*] [**opcodes**]
|
**bpftool prog dump xlated** *PROG* [{ **file** *FILE* | **opcodes** }]
|
||||||
Dump eBPF instructions of the program from the kernel.
|
Dump eBPF instructions of the program from the kernel.
|
||||||
If *FILE* is specified image will be written to a file,
|
If *FILE* is specified image will be written to a file,
|
||||||
otherwise it will be disassembled and printed to stdout.
|
otherwise it will be disassembled and printed to stdout.
|
||||||
|
|
||||||
**opcodes** controls if raw opcodes will be printed.
|
**opcodes** controls if raw opcodes will be printed.
|
||||||
|
|
||||||
**bpftool prog dump jited** *PROG* [**file** *FILE*] [**opcodes**]
|
**bpftool prog dump jited** *PROG* [{ **file** *FILE* | **opcodes** }]
|
||||||
Dump jited image (host machine code) of the program.
|
Dump jited image (host machine code) of the program.
|
||||||
If *FILE* is specified image will be written to a file,
|
If *FILE* is specified image will be written to a file,
|
||||||
otherwise it will be disassembled and printed to stdout.
|
otherwise it will be disassembled and printed to stdout.
|
||||||
|
|
|
@ -14,6 +14,8 @@ SYNOPSIS
|
||||||
|
|
||||||
**bpftool** batch file *FILE*
|
**bpftool** batch file *FILE*
|
||||||
|
|
||||||
|
**bpftool** version
|
||||||
|
|
||||||
*OBJECT* := { **map** | **program** }
|
*OBJECT* := { **map** | **program** }
|
||||||
|
|
||||||
*MAP-COMMANDS* :=
|
*MAP-COMMANDS* :=
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <linux/bpf.h>
|
#include <linux/bpf.h>
|
||||||
|
#include <linux/version.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -62,13 +63,23 @@ static int do_help(int argc, char **argv)
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Usage: %s OBJECT { COMMAND | help }\n"
|
"Usage: %s OBJECT { COMMAND | help }\n"
|
||||||
" %s batch file FILE\n"
|
" %s batch file FILE\n"
|
||||||
|
" %s version\n"
|
||||||
"\n"
|
"\n"
|
||||||
" OBJECT := { prog | map }\n",
|
" OBJECT := { prog | map }\n",
|
||||||
bin_name, bin_name);
|
bin_name, bin_name, bin_name);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int do_version(int argc, char **argv)
|
||||||
|
{
|
||||||
|
printf("%s v%d.%d.%d\n", bin_name,
|
||||||
|
LINUX_VERSION_CODE >> 16,
|
||||||
|
LINUX_VERSION_CODE >> 8 & 0xf,
|
||||||
|
LINUX_VERSION_CODE & 0xf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int cmd_select(const struct cmd *cmds, int argc, char **argv,
|
int cmd_select(const struct cmd *cmds, int argc, char **argv,
|
||||||
int (*help)(int argc, char **argv))
|
int (*help)(int argc, char **argv))
|
||||||
{
|
{
|
||||||
|
@ -100,7 +111,7 @@ bool is_prefix(const char *pfx, const char *str)
|
||||||
return !memcmp(str, pfx, strlen(pfx));
|
return !memcmp(str, pfx, strlen(pfx));
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_hex(void *arg, unsigned int n, const char *sep)
|
void fprint_hex(FILE *f, void *arg, unsigned int n, const char *sep)
|
||||||
{
|
{
|
||||||
unsigned char *data = arg;
|
unsigned char *data = arg;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
@ -111,13 +122,13 @@ void print_hex(void *arg, unsigned int n, const char *sep)
|
||||||
if (!i)
|
if (!i)
|
||||||
/* nothing */;
|
/* nothing */;
|
||||||
else if (!(i % 16))
|
else if (!(i % 16))
|
||||||
printf("\n");
|
fprintf(f, "\n");
|
||||||
else if (!(i % 8))
|
else if (!(i % 8))
|
||||||
printf(" ");
|
fprintf(f, " ");
|
||||||
else
|
else
|
||||||
pfx = sep;
|
pfx = sep;
|
||||||
|
|
||||||
printf("%s%02hhx", i ? pfx : "", data[i]);
|
fprintf(f, "%s%02hhx", i ? pfx : "", data[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,6 +139,7 @@ static const struct cmd cmds[] = {
|
||||||
{ "batch", do_batch },
|
{ "batch", do_batch },
|
||||||
{ "prog", do_prog },
|
{ "prog", do_prog },
|
||||||
{ "map", do_map },
|
{ "map", do_map },
|
||||||
|
{ "version", do_version },
|
||||||
{ 0 }
|
{ 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -67,7 +67,7 @@ enum bpf_obj_type {
|
||||||
extern const char *bin_name;
|
extern const char *bin_name;
|
||||||
|
|
||||||
bool is_prefix(const char *pfx, const char *str);
|
bool is_prefix(const char *pfx, const char *str);
|
||||||
void print_hex(void *arg, unsigned int n, const char *sep);
|
void fprint_hex(FILE *f, void *arg, unsigned int n, const char *sep);
|
||||||
void usage(void) __attribute__((noreturn));
|
void usage(void) __attribute__((noreturn));
|
||||||
|
|
||||||
struct cmd {
|
struct cmd {
|
||||||
|
|
|
@ -216,12 +216,12 @@ static void print_entry(struct bpf_map_info *info, unsigned char *key,
|
||||||
!break_names;
|
!break_names;
|
||||||
|
|
||||||
printf("key:%c", break_names ? '\n' : ' ');
|
printf("key:%c", break_names ? '\n' : ' ');
|
||||||
print_hex(key, info->key_size, " ");
|
fprint_hex(stdout, key, info->key_size, " ");
|
||||||
|
|
||||||
printf(single_line ? " " : "\n");
|
printf(single_line ? " " : "\n");
|
||||||
|
|
||||||
printf("value:%c", break_names ? '\n' : ' ');
|
printf("value:%c", break_names ? '\n' : ' ');
|
||||||
print_hex(value, info->value_size, " ");
|
fprint_hex(stdout, value, info->value_size, " ");
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
} else {
|
} else {
|
||||||
|
@ -230,12 +230,12 @@ static void print_entry(struct bpf_map_info *info, unsigned char *key,
|
||||||
n = get_possible_cpus();
|
n = get_possible_cpus();
|
||||||
|
|
||||||
printf("key:\n");
|
printf("key:\n");
|
||||||
print_hex(key, info->key_size, " ");
|
fprint_hex(stdout, key, info->key_size, " ");
|
||||||
printf("\n");
|
printf("\n");
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
printf("value (CPU %02d):%c",
|
printf("value (CPU %02d):%c",
|
||||||
i, info->value_size > 16 ? '\n' : ' ');
|
i, info->value_size > 16 ? '\n' : ' ');
|
||||||
print_hex(value + i * info->value_size,
|
fprint_hex(stdout, value + i * info->value_size,
|
||||||
info->value_size, " ");
|
info->value_size, " ");
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
@ -252,7 +252,7 @@ static char **parse_bytes(char **argv, const char *name, unsigned char *val,
|
||||||
val[i] = strtoul(argv[i], &endptr, 0);
|
val[i] = strtoul(argv[i], &endptr, 0);
|
||||||
if (*endptr) {
|
if (*endptr) {
|
||||||
err("error parsing byte: %s\n", argv[i]);
|
err("error parsing byte: %s\n", argv[i]);
|
||||||
break;
|
return NULL;
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
@ -492,8 +492,8 @@ static int do_dump(int argc, char **argv)
|
||||||
print_entry(&info, key, value);
|
print_entry(&info, key, value);
|
||||||
} else {
|
} else {
|
||||||
info("can't lookup element with key: ");
|
info("can't lookup element with key: ");
|
||||||
print_hex(key, info.key_size, " ");
|
fprint_hex(stderr, key, info.key_size, " ");
|
||||||
printf("\n");
|
fprintf(stderr, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
prev_key = key;
|
prev_key = key;
|
||||||
|
@ -587,7 +587,7 @@ static int do_lookup(int argc, char **argv)
|
||||||
print_entry(&info, key, value);
|
print_entry(&info, key, value);
|
||||||
} else if (errno == ENOENT) {
|
} else if (errno == ENOENT) {
|
||||||
printf("key:\n");
|
printf("key:\n");
|
||||||
print_hex(key, info.key_size, " ");
|
fprint_hex(stdout, key, info.key_size, " ");
|
||||||
printf("\n\nNot found\n");
|
printf("\n\nNot found\n");
|
||||||
} else {
|
} else {
|
||||||
err("lookup failed: %s\n", strerror(errno));
|
err("lookup failed: %s\n", strerror(errno));
|
||||||
|
@ -642,14 +642,14 @@ static int do_getnext(int argc, char **argv)
|
||||||
|
|
||||||
if (key) {
|
if (key) {
|
||||||
printf("key:\n");
|
printf("key:\n");
|
||||||
print_hex(key, info.key_size, " ");
|
fprint_hex(stdout, key, info.key_size, " ");
|
||||||
printf("\n");
|
printf("\n");
|
||||||
} else {
|
} else {
|
||||||
printf("key: None\n");
|
printf("key: None\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("next key:\n");
|
printf("next key:\n");
|
||||||
print_hex(nextkey, info.key_size, " ");
|
fprint_hex(stdout, nextkey, info.key_size, " ");
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
exit_free:
|
exit_free:
|
||||||
|
|
|
@ -224,7 +224,7 @@ static int show_prog(int fd)
|
||||||
printf("name %s ", info.name);
|
printf("name %s ", info.name);
|
||||||
|
|
||||||
printf("tag ");
|
printf("tag ");
|
||||||
print_hex(info.tag, BPF_TAG_SIZE, "");
|
fprint_hex(stdout, info.tag, BPF_TAG_SIZE, "");
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
if (info.load_time) {
|
if (info.load_time) {
|
||||||
|
@ -275,8 +275,10 @@ static int do_show(int argc, char **argv)
|
||||||
while (true) {
|
while (true) {
|
||||||
err = bpf_prog_get_next_id(id, &id);
|
err = bpf_prog_get_next_id(id, &id);
|
||||||
if (err) {
|
if (err) {
|
||||||
if (errno == ENOENT)
|
if (errno == ENOENT) {
|
||||||
|
err = 0;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
err("can't get next program: %s\n", strerror(errno));
|
err("can't get next program: %s\n", strerror(errno));
|
||||||
if (errno == EINVAL)
|
if (errno == EINVAL)
|
||||||
err("kernel too old?\n");
|
err("kernel too old?\n");
|
||||||
|
@ -311,20 +313,29 @@ static void print_insn(struct bpf_verifier_env *env, const char *fmt, ...)
|
||||||
static void dump_xlated(void *buf, unsigned int len, bool opcodes)
|
static void dump_xlated(void *buf, unsigned int len, bool opcodes)
|
||||||
{
|
{
|
||||||
struct bpf_insn *insn = buf;
|
struct bpf_insn *insn = buf;
|
||||||
|
bool double_insn = false;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
for (i = 0; i < len / sizeof(*insn); i++) {
|
for (i = 0; i < len / sizeof(*insn); i++) {
|
||||||
|
if (double_insn) {
|
||||||
|
double_insn = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
double_insn = insn[i].code == (BPF_LD | BPF_IMM | BPF_DW);
|
||||||
|
|
||||||
printf("% 4d: ", i);
|
printf("% 4d: ", i);
|
||||||
print_bpf_insn(print_insn, NULL, insn + i, true);
|
print_bpf_insn(print_insn, NULL, insn + i, true);
|
||||||
|
|
||||||
if (opcodes) {
|
if (opcodes) {
|
||||||
printf(" ");
|
printf(" ");
|
||||||
print_hex(insn + i, 8, " ");
|
fprint_hex(stdout, insn + i, 8, " ");
|
||||||
|
if (double_insn && i < len - 1) {
|
||||||
|
printf(" ");
|
||||||
|
fprint_hex(stdout, insn + i + 1, 8, " ");
|
||||||
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (insn[i].code == (BPF_LD | BPF_IMM | BPF_DW))
|
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -414,7 +425,7 @@ static int do_dump(int argc, char **argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*member_len > buf_size) {
|
if (*member_len > buf_size) {
|
||||||
info("too many instructions returned\n");
|
err("too many instructions returned\n");
|
||||||
goto err_free;
|
goto err_free;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -458,8 +469,8 @@ static int do_help(int argc, char **argv)
|
||||||
{
|
{
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Usage: %s %s show [PROG]\n"
|
"Usage: %s %s show [PROG]\n"
|
||||||
" %s %s dump xlated PROG [file FILE] [opcodes]\n"
|
" %s %s dump xlated PROG [{ file FILE | opcodes }]\n"
|
||||||
" %s %s dump jited PROG [file FILE] [opcodes]\n"
|
" %s %s dump jited PROG [{ file FILE | opcodes }]\n"
|
||||||
" %s %s pin PROG FILE\n"
|
" %s %s pin PROG FILE\n"
|
||||||
" %s %s help\n"
|
" %s %s help\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
@ -473,6 +484,7 @@ static int do_help(int argc, char **argv)
|
||||||
|
|
||||||
static const struct cmd cmds[] = {
|
static const struct cmd cmds[] = {
|
||||||
{ "show", do_show },
|
{ "show", do_show },
|
||||||
|
{ "help", do_help },
|
||||||
{ "dump", do_dump },
|
{ "dump", do_dump },
|
||||||
{ "pin", do_pin },
|
{ "pin", do_pin },
|
||||||
{ 0 }
|
{ 0 }
|
||||||
|
|
Loading…
Reference in New Issue