netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Re: [PATCH bpf-next 1/2] bpftool: add ability to dump BTF types
       [not found] ` <20190424052200.1625142-2-andrii.nakryiko@gmail.com>
@ 2019-04-24 17:12   ` Yonghong Song
  2019-04-24 18:12     ` Andrii Nakryiko
  2019-04-24 17:17   ` Yonghong Song
  1 sibling, 1 reply; 7+ messages in thread
From: Yonghong Song @ 2019-04-24 17:12 UTC (permalink / raw)
  To: andrii.nakryiko, Kernel Team, netdev, bpf, Alexei Starovoitov,
	daniel, Song Liu, Martin Lau, acme
  Cc: Andrii Nakryiko, Arnaldo Carvalho de Melo



On 4/23/19 10:21 PM, andrii.nakryiko@gmail.com wrote:
> From: Andrii Nakryiko <andriin@fb.com>
> 
> Add new `btf dump` sub-command to bpftool. It allows to dump
> human-readable low-level BTF types representation of BTF types. BTF can
> be retrieved from few different sources:
>    - from BTF object by ID;
>    - from PROG, if it has associated BTF;
>    - from MAP, if it has associated BTF data; it's possible to narrow
>      down types to either key type, value type, both, or all BTF types;
>    - from ELF file (.BTF section).
This is great. Thanks!
> 
> Output format mostly follows BPF verifier log format with few notable
> exceptions:
>    - all the type/field/param/etc names are enclosed in single quotes to
>      allow easier grepping and to stand out a little bit more;
>    - FUNC_PROTO output follows STRUCT/UNION/ENUM format of having one
>      line per each argument; this is more uniform and allows easy
>      grepping, as opposed to succinct, but inconvenient format that BPF
>      verifier log is using.
> 
> Cc: Daniel Borkmann <daniel@iogearbox.net>
> Cc: Alexei Starovoitov <ast@fb.com>
> Cc: Yonghong Song <yhs@fb.com>
> Cc: Martin KaFai Lau <kafai@fb.com>
> Cc: Song Liu <songliubraving@fb.com>
> Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
> Signed-off-by: Andrii Nakryiko <andriin@fb.com>
> ---
>   tools/bpf/bpftool/btf.c  | 576 +++++++++++++++++++++++++++++++++++++++
>   tools/bpf/bpftool/main.c |   1 +
>   tools/bpf/bpftool/main.h |   1 +
>   3 files changed, 578 insertions(+)
>   create mode 100644 tools/bpf/bpftool/btf.c
> 
> diff --git a/tools/bpf/bpftool/btf.c b/tools/bpf/bpftool/btf.c
> new file mode 100644
> index 000000000000..afe5cb7bab0c
> --- /dev/null
> +++ b/tools/bpf/bpftool/btf.c
> @@ -0,0 +1,576 @@
> +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +/* Copyright (C) 2019 Facebook */
> +
> +#include <errno.h>
> +#include <fcntl.h>
> +#include <linux/err.h>
> +#include <stdbool.h>
> +#include <stdio.h>
> +#include <string.h>
> +#include <unistd.h>
> +#include <gelf.h>
> +#include <bpf.h>
> +#include <linux/btf.h>
> +
[.....]
> +
> +static int do_dump(int argc, char **argv)
> +{
> +	struct btf *btf = NULL;
> +	__u32 root_type_ids[2];
> +	int root_type_cnt = 0;
> +	__u32 btf_id = -1;
> +	const char *src;
> +	int fd = -1;
> +	int err;
> +
> +	if (!REQ_ARGS(2)) {
> +		usage();
> +		return -1;
> +	}
> +	src = GET_ARG();
> +
> +	if (is_prefix(src, "map")) {
> +		struct bpf_map_info info = {};
> +		__u32 len = sizeof(info);
> +
> +		if (!REQ_ARGS(2)) {
> +			usage();
> +			return -1;
> +		}
> +
> +		fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
> +		if (fd < 0)
> +			return -1;
> +
> +		btf_id = info.btf_id;
> +		if (argc && is_prefix(*argv, "key")) {
> +			root_type_ids[root_type_cnt++] = info.btf_key_type_id;
> +			NEXT_ARG();
> +		} else if (argc && is_prefix(*argv, "value")) {
> +			root_type_ids[root_type_cnt++] = info.btf_value_type_id;
> +			NEXT_ARG();
> +		} else if (argc && is_prefix(*argv, "all")) {
> +			NEXT_ARG();
> +		} else if (argc && is_prefix(*argv, "kv")) {
> +			root_type_ids[root_type_cnt++] = info.btf_key_type_id;
> +			root_type_ids[root_type_cnt++] = info.btf_value_type_id;
> +			NEXT_ARG();
> +		} else {
> +			root_type_ids[root_type_cnt++] = info.btf_key_type_id;
> +			root_type_ids[root_type_cnt++] = info.btf_value_type_id;
> +		}
> +	} else if (is_prefix(src, "prog")) {
> +		struct bpf_prog_info info = {};
> +		__u32 len = sizeof(info);
> +
> +		if (!REQ_ARGS(2)) {
> +			usage();
> +			return -1;
> +		}
> +
> +		fd = prog_parse_fd(&argc, &argv);
> +		if (fd < 0)
> +			return -1;
> +
> +		err = bpf_obj_get_info_by_fd(fd, &info, &len);
> +		if (err) {
> +			p_err("can't get prog info: %s", strerror(errno));
> +			goto done;
> +		}
> +
> +		btf_id = info.btf_id;
> +	} else if (is_prefix(src, "id")) {
> +		char *endptr;
> +
> +		btf_id = strtoul(*argv, &endptr, 0);
> +		if (*endptr) {
> +			p_err("can't parse %s as ID", **argv);
> +			return -1;
> +		}
> +		NEXT_ARG();
> +	} else if (is_prefix(src, "file")) {
> +		err = btf_load_from_elf(*argv, &btf);
> +		if (err)
> +			goto done;
> +		NEXT_ARG();
> +	}

Another "else" branch here to handle wrong prefix? Otherwise, it will 
fall down to "can't find btf with ID (4294967295)" where "4294967295 == 
-1) which is a little misleading for users.

> +
> +	if (!btf) {
> +		err = btf__get_from_id(btf_id, &btf);
> +		if (err) {
> +			p_err("get btf by id (%u): %s", btf_id, strerror(err));
> +			goto done;
> +		}
> +		if (!btf) {
> +			err = ENOENT;
> +			p_err("can't find btf with ID (%u)", btf_id);
> +			goto done;
> +		}
> +	}
> +
> +	dump_btf_raw(btf, root_type_ids, root_type_cnt);
> +
> +done:
> +	close(fd);
> +	btf__free(btf);
> +	return err;
> +}
> +
> +static int do_help(int argc, char **argv)
> +{
> +	if (json_output) {
> +		jsonw_null(json_wtr);
> +		return 0;
> +	}
> +
> +	fprintf(stderr,
> +		"Usage: %s btf dump       BTF_SRC\n"
> +		"       %s btf help\n"
> +		"\n"
> +		"       BTF_SRC := { id BTF_ID | prog PROG | map MAP [{key | value | kv | all}] | elf FILE }\n"

"elf FILE" is not consistent with implementation. The implementation 
uses "file FILE". I prefer to use "file FILE".

> +		"       " HELP_SPEC_MAP "\n"
> +		"       " HELP_SPEC_PROGRAM "\n"
> +		"       " HELP_SPEC_OPTIONS "\n"
> +		"",
> +		bin_name, bin_name);
> +
> +	return 0;
> +}
> +
> +static const struct cmd cmds[] = {
> +	{ "help",	do_help },
> +	{ "dump",	do_dump },
> +	{ 0 }
> +};
> +
> +int do_btf(int argc, char **argv)
> +{
> +	return cmd_select(cmds, argc, argv, do_help);
> +}
> diff --git a/tools/bpf/bpftool/main.c b/tools/bpf/bpftool/main.c
> index a9d5e9e6a732..eba56edd7c77 100644
> --- a/tools/bpf/bpftool/main.c
> +++ b/tools/bpf/bpftool/main.c
> @@ -188,6 +188,7 @@ static const struct cmd cmds[] = {
>   	{ "perf",	do_perf },
>   	{ "net",	do_net },
>   	{ "feature",	do_feature },
> +	{ "btf",	do_btf },
>   	{ "version",	do_version },
>   	{ 0 }
>   };
> diff --git a/tools/bpf/bpftool/main.h b/tools/bpf/bpftool/main.h
> index 1ccc46169a19..3d63feb7f852 100644
> --- a/tools/bpf/bpftool/main.h
> +++ b/tools/bpf/bpftool/main.h
> @@ -150,6 +150,7 @@ int do_perf(int argc, char **arg);
>   int do_net(int argc, char **arg);
>   int do_tracelog(int argc, char **arg);
>   int do_feature(int argc, char **argv);
> +int do_btf(int argc, char **argv);
>   
>   int parse_u32_arg(int *argc, char ***argv, __u32 *val, const char *what);
>   int prog_parse_fd(int *argc, char ***argv);
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH bpf-next 1/2] bpftool: add ability to dump BTF types
       [not found] ` <20190424052200.1625142-2-andrii.nakryiko@gmail.com>
  2019-04-24 17:12   ` [PATCH bpf-next 1/2] bpftool: add ability to dump BTF types Yonghong Song
@ 2019-04-24 17:17   ` Yonghong Song
  2019-04-24 18:16     ` Andrii Nakryiko
  1 sibling, 1 reply; 7+ messages in thread
From: Yonghong Song @ 2019-04-24 17:17 UTC (permalink / raw)
  To: andrii.nakryiko, Kernel Team, netdev, bpf, Alexei Starovoitov,
	daniel, Song Liu, Martin Lau, acme
  Cc: Andrii Nakryiko, Arnaldo Carvalho de Melo



On 4/23/19 10:21 PM, andrii.nakryiko@gmail.com wrote:
> From: Andrii Nakryiko <andriin@fb.com>
> 
> Add new `btf dump` sub-command to bpftool. It allows to dump
> human-readable low-level BTF types representation of BTF types. BTF can
> be retrieved from few different sources:
>    - from BTF object by ID;
>    - from PROG, if it has associated BTF;
>    - from MAP, if it has associated BTF data; it's possible to narrow
>      down types to either key type, value type, both, or all BTF types;
>    - from ELF file (.BTF section).
> 
> Output format mostly follows BPF verifier log format with few notable
> exceptions:
>    - all the type/field/param/etc names are enclosed in single quotes to
>      allow easier grepping and to stand out a little bit more;
>    - FUNC_PROTO output follows STRUCT/UNION/ENUM format of having one
>      line per each argument; this is more uniform and allows easy
>      grepping, as opposed to succinct, but inconvenient format that BPF
>      verifier log is using.
> 
> Cc: Daniel Borkmann <daniel@iogearbox.net>
> Cc: Alexei Starovoitov <ast@fb.com>
> Cc: Yonghong Song <yhs@fb.com>
> Cc: Martin KaFai Lau <kafai@fb.com>
> Cc: Song Liu <songliubraving@fb.com>
> Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
> Signed-off-by: Andrii Nakryiko <andriin@fb.com>
> ---
>   tools/bpf/bpftool/btf.c  | 576 +++++++++++++++++++++++++++++++++++++++
>   tools/bpf/bpftool/main.c |   1 +
>   tools/bpf/bpftool/main.h |   1 +
>   3 files changed, 578 insertions(+)
>   create mode 100644 tools/bpf/bpftool/btf.c
> 
> diff --git a/tools/bpf/bpftool/btf.c b/tools/bpf/bpftool/btf.c
> new file mode 100644
> index 000000000000..afe5cb7bab0c
> --- /dev/null
> +++ b/tools/bpf/bpftool/btf.c
> @@ -0,0 +1,576 @@
> +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +/* Copyright (C) 2019 Facebook */
> +
> +#include <errno.h>
> +#include <fcntl.h>
> +#include <linux/err.h>
> +#include <stdbool.h>
> +#include <stdio.h>
> +#include <string.h>
> +#include <unistd.h>
> +#include <gelf.h>
> +#include <bpf.h>
> +#include <linux/btf.h>
> +
> +#include "btf.h"
> +#include "json_writer.h"
> +#include "main.h"
> +
> +static const char * const btf_kind_str[NR_BTF_KINDS] = {
> +	[BTF_KIND_UNKN]		= "UNKNOWN",
> +	[BTF_KIND_INT]		= "INT",
> +	[BTF_KIND_PTR]		= "PTR",
> +	[BTF_KIND_ARRAY]	= "ARRAY",
> +	[BTF_KIND_STRUCT]	= "STRUCT",
> +	[BTF_KIND_UNION]	= "UNION",
> +	[BTF_KIND_ENUM]		= "ENUM",
> +	[BTF_KIND_FWD]		= "FWD",
> +	[BTF_KIND_TYPEDEF]	= "TYPEDEF",
> +	[BTF_KIND_VOLATILE]	= "VOLATILE",
> +	[BTF_KIND_CONST]	= "CONST",
> +	[BTF_KIND_RESTRICT]	= "RESTRICT",
> +	[BTF_KIND_FUNC]		= "FUNC",
> +	[BTF_KIND_FUNC_PROTO]	= "FUNC_PROTO",
> +	[BTF_KIND_VAR]		= "VAR",
> +	[BTF_KIND_DATASEC]	= "DATASEC",
> +};
> +
> +static const char *btf_int_enc_str(__u8 encoding)
> +{
> +	switch (encoding) {
> +	case 0:
> +		return "(none)";
> +	case BTF_INT_SIGNED:
> +		return "SIGNED";
> +	case BTF_INT_CHAR:
> +		return "CHAR";
> +	case BTF_INT_BOOL:
> +		return "BOOL";
> +	default:
> +		return "UNKN";
> +	}
> +}
> +
> +static const char *btf_var_linkage_str(__u32 linkage)
> +{
> +	switch (linkage) {
> +	case BTF_VAR_STATIC:
> +		return "static";
> +	case BTF_VAR_GLOBAL_ALLOCATED:
> +		return "global-alloc";
> +	default:
> +		return "(unknown)";
> +	}
> +}
> +
[...]
> +
> +static bool check_btf_endianness(GElf_Ehdr *ehdr)
> +{
> +	static unsigned int const endian = 1;
> +
> +	switch (ehdr->e_ident[EI_DATA]) {
> +	case ELFDATA2LSB:
> +		return *(unsigned char const *)&endian == 1;
> +	case ELFDATA2MSB:
> +		return *(unsigned char const *)&endian == 0;
> +	default:
> +		return 0;
> +	}
> +}
> +
> +static int btf_load_from_elf(const char *path, struct btf **btf)
> +{
> +	int err = -1, fd = -1, idx = 0;
> +	Elf_Data *btf_data = NULL;
> +	Elf_Scn *scn = NULL;
> +	Elf *elf = NULL;
> +	GElf_Ehdr ehdr;
> +
> +	if (elf_version(EV_CURRENT) == EV_NONE) {
> +		p_err("failed to init libelf for %s", path);
> +		return -1;
> +	}
> +
> +	fd = open(path, O_RDONLY);
> +	if (fd < 0) {
> +		p_err("failed to open %s: %s", path, strerror(errno));
> +		return -1;
> +	}
> +
> +	elf = elf_begin(fd, ELF_C_READ, NULL);
> +	if (!elf) {
> +		p_err("failed to open %s as ELF file", path);
> +		goto done;
> +	}
> +	if (!gelf_getehdr(elf, &ehdr)) {
> +		p_err("failed to get EHDR from %s", path);
> +		goto done;
> +	}
> +	if (!check_btf_endianness(&ehdr)) {
> +		p_err("non-native ELF endianness is not supported");

We should relex this. It is possible that for some embedded system, 
bpftool is running on some x86 server examining a objfile file used
for an embedded system.

> +		goto done;
> +	}
> +	if (!elf_rawdata(elf_getscn(elf, ehdr.e_shstrndx), NULL)) {
> +		p_err("failed to get e_shstrndx from %s\n", path);
> +		goto done;
> +	}
> +
> +	while ((scn = elf_nextscn(elf, scn)) != NULL) {
> +		GElf_Shdr sh;
> +		char *name;
> +
> +		idx++;
> +		if (gelf_getshdr(scn, &sh) != &sh) {
> +			p_err("failed to get section(%d) header from %s",
> +			      idx, path);
> +			goto done;
> +		}
> +		name = elf_strptr(elf, ehdr.e_shstrndx, sh.sh_name);
> +		if (!name) {
> +			p_err("failed to get section(%d) name from %s",
> +			      idx, path);
> +			goto done;
> +		}
> +		if (strcmp(name, BTF_ELF_SEC) == 0) {
> +			btf_data = elf_getdata(scn, 0);
> +			if (!btf_data) {
> +				p_err("failed to get section(%d, %s) data from %s",
> +				      idx, name, path);
> +				goto done;
> +			}
> +			break;
> +		}
> +	}
> +
> +	if (!btf_data) {
> +		p_err("%s ELF section not found in %s", BTF_ELF_SEC, path);
> +		goto done;
> +	}
> +
> +	*btf = btf__new(btf_data->d_buf, btf_data->d_size);
> +	if (IS_ERR(*btf)) {
> +		err = PTR_ERR(*btf);
> +		*btf = NULL;
> +		p_err("failed to load BTF data from %s: %s",
> +		      path, strerror(err));
> +		goto done;
> +	}
> +
> +	err = 0;
> +done:
> +	if (err) {
> +		if (*btf) {
> +			btf__free(*btf);
> +			*btf = NULL;
> +		}
> +	}
> +	if (elf)
> +		elf_end(elf);
> +	close(fd);
> +	return err;
> +}
> +
[...]
> +}
> diff --git a/tools/bpf/bpftool/main.c b/tools/bpf/bpftool/main.c
> index a9d5e9e6a732..eba56edd7c77 100644
> --- a/tools/bpf/bpftool/main.c
> +++ b/tools/bpf/bpftool/main.c
> @@ -188,6 +188,7 @@ static const struct cmd cmds[] = {
>   	{ "perf",	do_perf },
>   	{ "net",	do_net },
>   	{ "feature",	do_feature },
> +	{ "btf",	do_btf },
>   	{ "version",	do_version },
>   	{ 0 }
>   };
> diff --git a/tools/bpf/bpftool/main.h b/tools/bpf/bpftool/main.h
> index 1ccc46169a19..3d63feb7f852 100644
> --- a/tools/bpf/bpftool/main.h
> +++ b/tools/bpf/bpftool/main.h
> @@ -150,6 +150,7 @@ int do_perf(int argc, char **arg);
>   int do_net(int argc, char **arg);
>   int do_tracelog(int argc, char **arg);
>   int do_feature(int argc, char **argv);
> +int do_btf(int argc, char **argv);
>   
>   int parse_u32_arg(int *argc, char ***argv, __u32 *val, const char *what);
>   int prog_parse_fd(int *argc, char ***argv);
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH bpf-next 2/2] bpftool/docs: add btf sub-command documentation
       [not found] ` <20190424052200.1625142-3-andrii.nakryiko@gmail.com>
@ 2019-04-24 17:21   ` Yonghong Song
  2019-04-24 19:01     ` Andrii Nakryiko
  0 siblings, 1 reply; 7+ messages in thread
From: Yonghong Song @ 2019-04-24 17:21 UTC (permalink / raw)
  To: andrii.nakryiko, Kernel Team, netdev, bpf, Alexei Starovoitov,
	daniel, Song Liu, Martin Lau, acme
  Cc: Andrii Nakryiko, Arnaldo Carvalho de Melo



On 4/23/19 10:22 PM, andrii.nakryiko@gmail.com wrote:
> From: Andrii Nakryiko <andriin@fb.com>
> 
> Document usage and sample output format for `btf dump` sub-command.

When applying the patch, I see a few trailing spaces.

===
p2.txt:113: trailing whitespace.

p2.txt:118: trailing whitespace.

p2.txt:120: trailing whitespace.

p2.txt:129: trailing whitespace.

p2.txt:134: trailing whitespace.
===

You may want to take a look.

Could you add bash completion as well?

> 
> Cc: Daniel Borkmann <daniel@iogearbox.net>
> Cc: Alexei Starovoitov <ast@fb.com>
> Cc: Yonghong Song <yhs@fb.com>
> Cc: Martin KaFai Lau <kafai@fb.com>
> Cc: Song Liu <songliubraving@fb.com>
> Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
> Signed-off-by: Andrii Nakryiko <andriin@fb.com>
> ---
>   .../bpf/bpftool/Documentation/bpftool-btf.rst | 205 ++++++++++++++++++
>   .../bpftool/Documentation/bpftool-cgroup.rst  |   3 +-
>   .../bpftool/Documentation/bpftool-feature.rst |   3 +-
>   .../bpf/bpftool/Documentation/bpftool-map.rst |   3 +-
>   .../bpf/bpftool/Documentation/bpftool-net.rst |   3 +-
>   .../bpftool/Documentation/bpftool-perf.rst    |   3 +-
>   .../bpftool/Documentation/bpftool-prog.rst    |   3 +-
>   tools/bpf/bpftool/Documentation/bpftool.rst   |   3 +-
>   8 files changed, 219 insertions(+), 7 deletions(-)
>   create mode 100644 tools/bpf/bpftool/Documentation/bpftool-btf.rst
> 
> diff --git a/tools/bpf/bpftool/Documentation/bpftool-btf.rst b/tools/bpf/bpftool/Documentation/bpftool-btf.rst
> new file mode 100644
> index 000000000000..955aaaba93a0
> --- /dev/null
> +++ b/tools/bpf/bpftool/Documentation/bpftool-btf.rst
> @@ -0,0 +1,205 @@
> +================
> +bpftool-btf
> +================
> +-------------------------------------------------------------------------------
> +tool for inspection of BTF data
> +-------------------------------------------------------------------------------
> +
> +:Manual section: 8
> +
> +SYNOPSIS
> +========
> +
> +	**bpftool** [*OPTIONS*] **btf** *COMMAND*
> +
> +	*OPTIONS* := { { **-j** | **--json** } [{ **-p** | **--pretty** }] }
> +
> +	*COMMANDS* :=
> +	{ **dump** | **help** }
> +
> +MAP COMMANDS
> +=============
> +
> +|	**bpftool** **btf dump**       *BTF_SRC*
> +|	**bpftool** **btf help**
> +|
> +|	*BTF_SRC* := { **id** *BTF_ID* | **prog** *PROG* | **map** *MAP* [{**key** | **value** | **kv** | **all**}] | **file** *FILE* }
> +|	*MAP* := { **id** *MAP_ID* | **pinned** *FILE* }
> +|	*PROG* := { **id** *PROG_ID* | **pinned** *FILE* | **tag** *PROG_TAG* }
> +
> +DESCRIPTION
> +===========
> +	**bpftool map dump**    *MAP*
> +		  Dump BTF entries from a given *BTF_SRC*.
> +
> +	**bpftool map help**
> +		  Print short help message.
> +
> +OPTIONS
> +=======
> +	-h, --help
> +		  Print short generic help message (similar to **bpftool help**).
> +
> +	-V, --version
> +		  Print version number (similar to **bpftool version**).
> +
> +	-j, --json
> +		  Generate JSON output. For commands that cannot produce JSON, this
> +		  option has no effect.
> +
> +	-p, --pretty
> +		  Generate human-readable JSON output. Implies **-j**.
> +
> +EXAMPLES
> +========
> +**# bpftool btf dump id 1226**
> +::
> +
> +  [1] PTR '(anon)' type_id=2
> +  [2] STRUCT 'dummy_tracepoint_args' size=16 vlen=2
> +          'pad' type_id=3 bits_offset=0
> +          'sock' type_id=4 bits_offset=64
> +  [3] INT 'long long unsigned int' size=8 bits_offset=0 nr_bits=64 encoding=(none)
> +  [4] PTR '(anon)' type_id=5
> +  [5] FWD 'sock' fwd_kind=union
> +
> +This gives an example of default output for all supported BTF kinds.
> +
> +**$ cat prog.c**
> +::
> +
> +  struct fwd_struct;
> +
> +  enum my_enum {
> +          VAL1 = 3,
> +          VAL2 = 7,
> +  };
> +
> +  typedef struct my_struct my_struct_t;
> +
> +  struct my_struct {
> +          const unsigned int const_int_field;
> +          int bitfield_field: 4;
> +          char arr_field[16];
> +          const struct fwd_struct *restrict fwd_field;
> +          enum my_enum enum_field;
> +          volatile my_struct_t *typedef_ptr_field;
> +  };
> +
> +  union my_union {
> +          int a;
> +          struct my_struct b;
> +  };
> +
> +  struct my_struct struct_global_var __attribute__((section("data_sec"))) = {
> +          .bitfield_field = 3,
> +          .enum_field = VAL1,
> +  };
> +  int global_var __attribute__((section("data_sec"))) = 7;
> +
> +  __attribute__((noinline))
> +  int my_func(union my_union *arg1, int arg2)
> +  {
> +          static int static_var __attribute__((section("data_sec"))) = 123;
> +          static_var++;
> +          return static_var;
> +  }
> +
> +**$ bpftool btf dump file prog.o**
> +::
> +
> +  [1] PTR '(anon)' type_id=2
> +  [2] UNION 'my_union' size=48 vlen=2
> +          'a' type_id=3 bits_offset=0
> +          'b' type_id=4 bits_offset=0
> +  [3] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
> +  [4] STRUCT 'my_struct' size=48 vlen=6
> +          'const_int_field' type_id=5 bits_offset=0
> +          'bitfield_field' type_id=3 bits_offset=32 bitfield_size=4
> +          'arr_field' type_id=8 bits_offset=40
> +          'fwd_field' type_id=10 bits_offset=192
> +          'enum_field' type_id=14 bits_offset=256
> +          'typedef_ptr_field' type_id=15 bits_offset=320
> +  [5] CONST '(anon)' type_id=6
> +  [6] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)
> +  [7] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=SIGNED
> +  [8] ARRAY '(anon)' type_id=7 index_type_id=9 nr_elems=16
> +  [9] INT '__ARRAY_SIZE_TYPE__' size=4 bits_offset=0 nr_bits=32 encoding=(none)
> +  [10] RESTRICT '(anon)' type_id=11
> +  [11] PTR '(anon)' type_id=12
> +  [12] CONST '(anon)' type_id=13
> +  [13] FWD 'fwd_struct' fwd_kind=union
> +  [14] ENUM 'my_enum' size=4 vlen=2
> +          'VAL1' val=3
> +          'VAL2' val=7
> +  [15] PTR '(anon)' type_id=16
> +  [16] VOLATILE '(anon)' type_id=17
> +  [17] TYPEDEF 'my_struct_t' type_id=4
> +  [18] FUNC_PROTO '(anon)' ret_type_id=3 vlen=2
> +          'arg1' type_id=1
> +          'arg2' type_id=3
> +  [19] FUNC 'my_func' type_id=18
> +  [20] VAR 'struct_global_var' type_id=4, linkage=global-alloc
> +  [21] VAR 'global_var' type_id=3, linkage=global-alloc
> +  [22] VAR 'my_func.static_var' type_id=3, linkage=static
> +  [23] DATASEC 'data_sec' size=0 vlen=3
> +          type_id=20 offset=0 size=48
> +          type_id=21 offset=0 size=4
> +          type_id=22 offset=52 size=4
> +
> +The following commands print BTF types associated with specified map's key,
> +value, both key and value, and all BTF types, respectively. By default, both
> +key and value types will be printed.
> +
> +**# bpftool btf dump map id 123 key**
> +
> +::
> +
> +  [39] TYPEDEF 'u32' type_id=37
> +
> +**# bpftool btf dump map id 123 value**
> +
> +::
> +
> +  [86] PTR '(anon)' type_id=87
> +
> +**# bpftool btf dump map id 123 kv**
> +
> +::
> +
> +  [39] TYPEDEF 'u32' type_id=37
> +  [86] PTR '(anon)' type_id=87
> +
> +**# bpftool btf dump map id 123 all**
> +
> +::
> +
> +  [1] PTR '(anon)' type_id=0
> +  .
> +  .
> +  .
> +  [2866] ARRAY '(anon)' type_id=52 index_type_id=51 nr_elems=4
> +
> +All the standard ways to specify map or program is supported:
> +
> +**# bpftool btf dump map id 123**
> +
> +**# bpftool btf dump map pinned /sys/fs/bpf/map_name**
> +
> +**# bpftool btf dump prog id 456**
> +
> +**# bpftool btf dump prog tag b88e0a09b1d9759d**
> +
> +**# bpftool btf dump prog pinned /sys/fs/bpf/prog_name**
> +
> +SEE ALSO
> +========
> +	**bpf**\ (2),
> +	**bpf-helpers**\ (7),
> +	**bpftool**\ (8),
> +	**bpftool-map**\ (8),
> +	**bpftool-prog**\ (8),
> +	**bpftool-cgroup**\ (8),
> +	**bpftool-feature**\ (8),
> +	**bpftool-net**\ (8),
> +	**bpftool-perf**\ (8)
> diff --git a/tools/bpf/bpftool/Documentation/bpftool-cgroup.rst b/tools/bpf/bpftool/Documentation/bpftool-cgroup.rst
> index 89b6b10e2183..ac26876389c2 100644
> --- a/tools/bpf/bpftool/Documentation/bpftool-cgroup.rst
> +++ b/tools/bpf/bpftool/Documentation/bpftool-cgroup.rst
> @@ -145,4 +145,5 @@ SEE ALSO
>   	**bpftool-map**\ (8),
>   	**bpftool-feature**\ (8),
>   	**bpftool-net**\ (8),
> -	**bpftool-perf**\ (8)
> +	**bpftool-perf**\ (8),
> +	**bpftool-btf**\ (8)
> diff --git a/tools/bpf/bpftool/Documentation/bpftool-feature.rst b/tools/bpf/bpftool/Documentation/bpftool-feature.rst
> index 10177343b7ce..14180e887082 100644
> --- a/tools/bpf/bpftool/Documentation/bpftool-feature.rst
> +++ b/tools/bpf/bpftool/Documentation/bpftool-feature.rst
> @@ -82,4 +82,5 @@ SEE ALSO
>   	**bpftool-map**\ (8),
>   	**bpftool-cgroup**\ (8),
>   	**bpftool-net**\ (8),
> -	**bpftool-perf**\ (8)
> +	**bpftool-perf**\ (8),
> +	**bpftool-btf**\ (8)
> diff --git a/tools/bpf/bpftool/Documentation/bpftool-map.rst b/tools/bpf/bpftool/Documentation/bpftool-map.rst
> index 55ecf80ca03e..13ef27b39f20 100644
> --- a/tools/bpf/bpftool/Documentation/bpftool-map.rst
> +++ b/tools/bpf/bpftool/Documentation/bpftool-map.rst
> @@ -258,4 +258,5 @@ SEE ALSO
>   	**bpftool-cgroup**\ (8),
>   	**bpftool-feature**\ (8),
>   	**bpftool-net**\ (8),
> -	**bpftool-perf**\ (8)
> +	**bpftool-perf**\ (8),
> +	**bpftool-btf**\ (8)
> diff --git a/tools/bpf/bpftool/Documentation/bpftool-net.rst b/tools/bpf/bpftool/Documentation/bpftool-net.rst
> index 6b692b428373..934580850f42 100644
> --- a/tools/bpf/bpftool/Documentation/bpftool-net.rst
> +++ b/tools/bpf/bpftool/Documentation/bpftool-net.rst
> @@ -143,4 +143,5 @@ SEE ALSO
>   	**bpftool-map**\ (8),
>   	**bpftool-cgroup**\ (8),
>   	**bpftool-feature**\ (8),
> -	**bpftool-perf**\ (8)
> +	**bpftool-perf**\ (8),
> +	**bpftool-btf**\ (8)
> diff --git a/tools/bpf/bpftool/Documentation/bpftool-perf.rst b/tools/bpf/bpftool/Documentation/bpftool-perf.rst
> index 86154740fabb..0c7576523a21 100644
> --- a/tools/bpf/bpftool/Documentation/bpftool-perf.rst
> +++ b/tools/bpf/bpftool/Documentation/bpftool-perf.rst
> @@ -85,4 +85,5 @@ SEE ALSO
>   	**bpftool-map**\ (8),
>   	**bpftool-cgroup**\ (8),
>   	**bpftool-feature**\ (8),
> -	**bpftool-net**\ (8)
> +	**bpftool-net**\ (8),
> +	**bpftool-btf**\ (8)
> diff --git a/tools/bpf/bpftool/Documentation/bpftool-prog.rst b/tools/bpf/bpftool/Documentation/bpftool-prog.rst
> index 2f183ffd8351..e8118544d118 100644
> --- a/tools/bpf/bpftool/Documentation/bpftool-prog.rst
> +++ b/tools/bpf/bpftool/Documentation/bpftool-prog.rst
> @@ -271,4 +271,5 @@ SEE ALSO
>   	**bpftool-cgroup**\ (8),
>   	**bpftool-feature**\ (8),
>   	**bpftool-net**\ (8),
> -	**bpftool-perf**\ (8)
> +	**bpftool-perf**\ (8),
> +	**bpftool-btf**\ (8)
> diff --git a/tools/bpf/bpftool/Documentation/bpftool.rst b/tools/bpf/bpftool/Documentation/bpftool.rst
> index deb2ca911ddf..3e562d7fd56f 100644
> --- a/tools/bpf/bpftool/Documentation/bpftool.rst
> +++ b/tools/bpf/bpftool/Documentation/bpftool.rst
> @@ -76,4 +76,5 @@ SEE ALSO
>   	**bpftool-cgroup**\ (8),
>   	**bpftool-feature**\ (8),
>   	**bpftool-net**\ (8),
> -	**bpftool-perf**\ (8)
> +	**bpftool-perf**\ (8),
> +	**bpftool-btf**\ (8)
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH bpf-next 1/2] bpftool: add ability to dump BTF types
  2019-04-24 17:12   ` [PATCH bpf-next 1/2] bpftool: add ability to dump BTF types Yonghong Song
@ 2019-04-24 18:12     ` Andrii Nakryiko
  0 siblings, 0 replies; 7+ messages in thread
From: Andrii Nakryiko @ 2019-04-24 18:12 UTC (permalink / raw)
  To: Yonghong Song
  Cc: Kernel Team, netdev, bpf, Alexei Starovoitov, daniel, Song Liu,
	Martin Lau, acme, Andrii Nakryiko, Arnaldo Carvalho de Melo

On Wed, Apr 24, 2019 at 10:12 AM Yonghong Song <yhs@fb.com> wrote:
>
>
>
> On 4/23/19 10:21 PM, andrii.nakryiko@gmail.com wrote:
> > From: Andrii Nakryiko <andriin@fb.com>
> >
> > Add new `btf dump` sub-command to bpftool. It allows to dump
> > human-readable low-level BTF types representation of BTF types. BTF can
> > be retrieved from few different sources:
> >    - from BTF object by ID;
> >    - from PROG, if it has associated BTF;
> >    - from MAP, if it has associated BTF data; it's possible to narrow
> >      down types to either key type, value type, both, or all BTF types;
> >    - from ELF file (.BTF section).
> This is great. Thanks!
> >
> > Output format mostly follows BPF verifier log format with few notable
> > exceptions:
> >    - all the type/field/param/etc names are enclosed in single quotes to
> >      allow easier grepping and to stand out a little bit more;
> >    - FUNC_PROTO output follows STRUCT/UNION/ENUM format of having one
> >      line per each argument; this is more uniform and allows easy
> >      grepping, as opposed to succinct, but inconvenient format that BPF
> >      verifier log is using.
> >
> > Cc: Daniel Borkmann <daniel@iogearbox.net>
> > Cc: Alexei Starovoitov <ast@fb.com>
> > Cc: Yonghong Song <yhs@fb.com>
> > Cc: Martin KaFai Lau <kafai@fb.com>
> > Cc: Song Liu <songliubraving@fb.com>
> > Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
> > Signed-off-by: Andrii Nakryiko <andriin@fb.com>
> > ---
> >   tools/bpf/bpftool/btf.c  | 576 +++++++++++++++++++++++++++++++++++++++
> >   tools/bpf/bpftool/main.c |   1 +
> >   tools/bpf/bpftool/main.h |   1 +
> >   3 files changed, 578 insertions(+)
> >   create mode 100644 tools/bpf/bpftool/btf.c
> >
> > diff --git a/tools/bpf/bpftool/btf.c b/tools/bpf/bpftool/btf.c
> > new file mode 100644
> > index 000000000000..afe5cb7bab0c
> > --- /dev/null
> > +++ b/tools/bpf/bpftool/btf.c
> > @@ -0,0 +1,576 @@
> > +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > +/* Copyright (C) 2019 Facebook */
> > +
> > +#include <errno.h>
> > +#include <fcntl.h>
> > +#include <linux/err.h>
> > +#include <stdbool.h>
> > +#include <stdio.h>
> > +#include <string.h>
> > +#include <unistd.h>
> > +#include <gelf.h>
> > +#include <bpf.h>
> > +#include <linux/btf.h>
> > +
> [.....]
> > +
> > +static int do_dump(int argc, char **argv)
> > +{
> > +     struct btf *btf = NULL;
> > +     __u32 root_type_ids[2];
> > +     int root_type_cnt = 0;
> > +     __u32 btf_id = -1;
> > +     const char *src;
> > +     int fd = -1;
> > +     int err;
> > +
> > +     if (!REQ_ARGS(2)) {
> > +             usage();
> > +             return -1;
> > +     }
> > +     src = GET_ARG();
> > +
> > +     if (is_prefix(src, "map")) {
> > +             struct bpf_map_info info = {};
> > +             __u32 len = sizeof(info);
> > +
> > +             if (!REQ_ARGS(2)) {
> > +                     usage();
> > +                     return -1;
> > +             }
> > +
> > +             fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
> > +             if (fd < 0)
> > +                     return -1;
> > +
> > +             btf_id = info.btf_id;
> > +             if (argc && is_prefix(*argv, "key")) {
> > +                     root_type_ids[root_type_cnt++] = info.btf_key_type_id;
> > +                     NEXT_ARG();
> > +             } else if (argc && is_prefix(*argv, "value")) {
> > +                     root_type_ids[root_type_cnt++] = info.btf_value_type_id;
> > +                     NEXT_ARG();
> > +             } else if (argc && is_prefix(*argv, "all")) {
> > +                     NEXT_ARG();
> > +             } else if (argc && is_prefix(*argv, "kv")) {
> > +                     root_type_ids[root_type_cnt++] = info.btf_key_type_id;
> > +                     root_type_ids[root_type_cnt++] = info.btf_value_type_id;
> > +                     NEXT_ARG();
> > +             } else {
> > +                     root_type_ids[root_type_cnt++] = info.btf_key_type_id;
> > +                     root_type_ids[root_type_cnt++] = info.btf_value_type_id;
> > +             }
> > +     } else if (is_prefix(src, "prog")) {
> > +             struct bpf_prog_info info = {};
> > +             __u32 len = sizeof(info);
> > +
> > +             if (!REQ_ARGS(2)) {
> > +                     usage();
> > +                     return -1;
> > +             }
> > +
> > +             fd = prog_parse_fd(&argc, &argv);
> > +             if (fd < 0)
> > +                     return -1;
> > +
> > +             err = bpf_obj_get_info_by_fd(fd, &info, &len);
> > +             if (err) {
> > +                     p_err("can't get prog info: %s", strerror(errno));
> > +                     goto done;
> > +             }
> > +
> > +             btf_id = info.btf_id;
> > +     } else if (is_prefix(src, "id")) {
> > +             char *endptr;
> > +
> > +             btf_id = strtoul(*argv, &endptr, 0);
> > +             if (*endptr) {
> > +                     p_err("can't parse %s as ID", **argv);
> > +                     return -1;
> > +             }
> > +             NEXT_ARG();
> > +     } else if (is_prefix(src, "file")) {
> > +             err = btf_load_from_elf(*argv, &btf);
> > +             if (err)
> > +                     goto done;
> > +             NEXT_ARG();
> > +     }
>
> Another "else" branch here to handle wrong prefix? Otherwise, it will
> fall down to "can't find btf with ID (4294967295)" where "4294967295 ==
> -1) which is a little misleading for users.

Yep, makes sense, will add, not sure why I haven't done that in the
first place...

>
> > +
> > +     if (!btf) {
> > +             err = btf__get_from_id(btf_id, &btf);
> > +             if (err) {
> > +                     p_err("get btf by id (%u): %s", btf_id, strerror(err));
> > +                     goto done;
> > +             }
> > +             if (!btf) {
> > +                     err = ENOENT;
> > +                     p_err("can't find btf with ID (%u)", btf_id);
> > +                     goto done;
> > +             }
> > +     }
> > +
> > +     dump_btf_raw(btf, root_type_ids, root_type_cnt);
> > +
> > +done:
> > +     close(fd);
> > +     btf__free(btf);
> > +     return err;
> > +}
> > +
> > +static int do_help(int argc, char **argv)
> > +{
> > +     if (json_output) {
> > +             jsonw_null(json_wtr);
> > +             return 0;
> > +     }
> > +
> > +     fprintf(stderr,
> > +             "Usage: %s btf dump       BTF_SRC\n"
> > +             "       %s btf help\n"
> > +             "\n"
> > +             "       BTF_SRC := { id BTF_ID | prog PROG | map MAP [{key | value | kv | all}] | elf FILE }\n"
>
> "elf FILE" is not consistent with implementation. The implementation
> uses "file FILE". I prefer to use "file FILE".

Oops, yep, it should be file.

>
> > +             "       " HELP_SPEC_MAP "\n"
> > +             "       " HELP_SPEC_PROGRAM "\n"
> > +             "       " HELP_SPEC_OPTIONS "\n"
> > +             "",
> > +             bin_name, bin_name);
> > +
> > +     return 0;
> > +}
> > +
> > +static const struct cmd cmds[] = {
> > +     { "help",       do_help },
> > +     { "dump",       do_dump },
> > +     { 0 }
> > +};
> > +
> > +int do_btf(int argc, char **argv)
> > +{
> > +     return cmd_select(cmds, argc, argv, do_help);
> > +}
> > diff --git a/tools/bpf/bpftool/main.c b/tools/bpf/bpftool/main.c
> > index a9d5e9e6a732..eba56edd7c77 100644
> > --- a/tools/bpf/bpftool/main.c
> > +++ b/tools/bpf/bpftool/main.c
> > @@ -188,6 +188,7 @@ static const struct cmd cmds[] = {
> >       { "perf",       do_perf },
> >       { "net",        do_net },
> >       { "feature",    do_feature },
> > +     { "btf",        do_btf },
> >       { "version",    do_version },
> >       { 0 }
> >   };
> > diff --git a/tools/bpf/bpftool/main.h b/tools/bpf/bpftool/main.h
> > index 1ccc46169a19..3d63feb7f852 100644
> > --- a/tools/bpf/bpftool/main.h
> > +++ b/tools/bpf/bpftool/main.h
> > @@ -150,6 +150,7 @@ int do_perf(int argc, char **arg);
> >   int do_net(int argc, char **arg);
> >   int do_tracelog(int argc, char **arg);
> >   int do_feature(int argc, char **argv);
> > +int do_btf(int argc, char **argv);
> >
> >   int parse_u32_arg(int *argc, char ***argv, __u32 *val, const char *what);
> >   int prog_parse_fd(int *argc, char ***argv);
> >

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH bpf-next 1/2] bpftool: add ability to dump BTF types
  2019-04-24 17:17   ` Yonghong Song
@ 2019-04-24 18:16     ` Andrii Nakryiko
  2019-04-24 18:40       ` Yonghong Song
  0 siblings, 1 reply; 7+ messages in thread
From: Andrii Nakryiko @ 2019-04-24 18:16 UTC (permalink / raw)
  To: Yonghong Song
  Cc: Kernel Team, netdev, bpf, Alexei Starovoitov, daniel, Song Liu,
	Martin Lau, acme, Andrii Nakryiko, Arnaldo Carvalho de Melo

On Wed, Apr 24, 2019 at 10:17 AM Yonghong Song <yhs@fb.com> wrote:
>
>
>
> On 4/23/19 10:21 PM, andrii.nakryiko@gmail.com wrote:
> > From: Andrii Nakryiko <andriin@fb.com>
> >
> > Add new `btf dump` sub-command to bpftool. It allows to dump
> > human-readable low-level BTF types representation of BTF types. BTF can
> > be retrieved from few different sources:
> >    - from BTF object by ID;
> >    - from PROG, if it has associated BTF;
> >    - from MAP, if it has associated BTF data; it's possible to narrow
> >      down types to either key type, value type, both, or all BTF types;
> >    - from ELF file (.BTF section).
> >
> > Output format mostly follows BPF verifier log format with few notable
> > exceptions:
> >    - all the type/field/param/etc names are enclosed in single quotes to
> >      allow easier grepping and to stand out a little bit more;
> >    - FUNC_PROTO output follows STRUCT/UNION/ENUM format of having one
> >      line per each argument; this is more uniform and allows easy
> >      grepping, as opposed to succinct, but inconvenient format that BPF
> >      verifier log is using.
> >
> > Cc: Daniel Borkmann <daniel@iogearbox.net>
> > Cc: Alexei Starovoitov <ast@fb.com>
> > Cc: Yonghong Song <yhs@fb.com>
> > Cc: Martin KaFai Lau <kafai@fb.com>
> > Cc: Song Liu <songliubraving@fb.com>
> > Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
> > Signed-off-by: Andrii Nakryiko <andriin@fb.com>
> > ---
> >   tools/bpf/bpftool/btf.c  | 576 +++++++++++++++++++++++++++++++++++++++
> >   tools/bpf/bpftool/main.c |   1 +
> >   tools/bpf/bpftool/main.h |   1 +
> >   3 files changed, 578 insertions(+)
> >   create mode 100644 tools/bpf/bpftool/btf.c
> >
> > diff --git a/tools/bpf/bpftool/btf.c b/tools/bpf/bpftool/btf.c
> > new file mode 100644
> > index 000000000000..afe5cb7bab0c
> > --- /dev/null
> > +++ b/tools/bpf/bpftool/btf.c
> > @@ -0,0 +1,576 @@
> > +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > +/* Copyright (C) 2019 Facebook */
> > +
> > +#include <errno.h>
> > +#include <fcntl.h>
> > +#include <linux/err.h>
> > +#include <stdbool.h>
> > +#include <stdio.h>
> > +#include <string.h>
> > +#include <unistd.h>
> > +#include <gelf.h>
> > +#include <bpf.h>
> > +#include <linux/btf.h>
> > +
> > +#include "btf.h"
> > +#include "json_writer.h"
> > +#include "main.h"
> > +
> > +static const char * const btf_kind_str[NR_BTF_KINDS] = {
> > +     [BTF_KIND_UNKN]         = "UNKNOWN",
> > +     [BTF_KIND_INT]          = "INT",
> > +     [BTF_KIND_PTR]          = "PTR",
> > +     [BTF_KIND_ARRAY]        = "ARRAY",
> > +     [BTF_KIND_STRUCT]       = "STRUCT",
> > +     [BTF_KIND_UNION]        = "UNION",
> > +     [BTF_KIND_ENUM]         = "ENUM",
> > +     [BTF_KIND_FWD]          = "FWD",
> > +     [BTF_KIND_TYPEDEF]      = "TYPEDEF",
> > +     [BTF_KIND_VOLATILE]     = "VOLATILE",
> > +     [BTF_KIND_CONST]        = "CONST",
> > +     [BTF_KIND_RESTRICT]     = "RESTRICT",
> > +     [BTF_KIND_FUNC]         = "FUNC",
> > +     [BTF_KIND_FUNC_PROTO]   = "FUNC_PROTO",
> > +     [BTF_KIND_VAR]          = "VAR",
> > +     [BTF_KIND_DATASEC]      = "DATASEC",
> > +};
> > +
> > +static const char *btf_int_enc_str(__u8 encoding)
> > +{
> > +     switch (encoding) {
> > +     case 0:
> > +             return "(none)";
> > +     case BTF_INT_SIGNED:
> > +             return "SIGNED";
> > +     case BTF_INT_CHAR:
> > +             return "CHAR";
> > +     case BTF_INT_BOOL:
> > +             return "BOOL";
> > +     default:
> > +             return "UNKN";
> > +     }
> > +}
> > +
> > +static const char *btf_var_linkage_str(__u32 linkage)
> > +{
> > +     switch (linkage) {
> > +     case BTF_VAR_STATIC:
> > +             return "static";
> > +     case BTF_VAR_GLOBAL_ALLOCATED:
> > +             return "global-alloc";
> > +     default:
> > +             return "(unknown)";
> > +     }
> > +}
> > +
> [...]
> > +
> > +static bool check_btf_endianness(GElf_Ehdr *ehdr)
> > +{
> > +     static unsigned int const endian = 1;
> > +
> > +     switch (ehdr->e_ident[EI_DATA]) {
> > +     case ELFDATA2LSB:
> > +             return *(unsigned char const *)&endian == 1;
> > +     case ELFDATA2MSB:
> > +             return *(unsigned char const *)&endian == 0;
> > +     default:
> > +             return 0;
> > +     }
> > +}
> > +
> > +static int btf_load_from_elf(const char *path, struct btf **btf)
> > +{
> > +     int err = -1, fd = -1, idx = 0;
> > +     Elf_Data *btf_data = NULL;
> > +     Elf_Scn *scn = NULL;
> > +     Elf *elf = NULL;
> > +     GElf_Ehdr ehdr;
> > +
> > +     if (elf_version(EV_CURRENT) == EV_NONE) {
> > +             p_err("failed to init libelf for %s", path);
> > +             return -1;
> > +     }
> > +
> > +     fd = open(path, O_RDONLY);
> > +     if (fd < 0) {
> > +             p_err("failed to open %s: %s", path, strerror(errno));
> > +             return -1;
> > +     }
> > +
> > +     elf = elf_begin(fd, ELF_C_READ, NULL);
> > +     if (!elf) {
> > +             p_err("failed to open %s as ELF file", path);
> > +             goto done;
> > +     }
> > +     if (!gelf_getehdr(elf, &ehdr)) {
> > +             p_err("failed to get EHDR from %s", path);
> > +             goto done;
> > +     }
> > +     if (!check_btf_endianness(&ehdr)) {
> > +             p_err("non-native ELF endianness is not supported");
>
> We should relex this. It is possible that for some embedded system,
> bpftool is running on some x86 server examining a objfile file used
> for an embedded system.

I agree, but I think that should be done in libbpf. I've been meaning
to add that for a while now, but never got around to that, it's still
on my TODO list.

My intent is to teach btf__new to look at BTF header, and if it's
endianness is not native, convert all the integers to native
endianness. That way, struct btf is always of native endianness in
memory and won't require any extra checks from other code. I'll do it
some time soonish at which point both pahole (which handles this
explicitly right now) and bpftool can greatly benefit from that. How
does that sound?

>
> > +             goto done;
> > +     }
> > +     if (!elf_rawdata(elf_getscn(elf, ehdr.e_shstrndx), NULL)) {
> > +             p_err("failed to get e_shstrndx from %s\n", path);
> > +             goto done;
> > +     }
> > +
> > +     while ((scn = elf_nextscn(elf, scn)) != NULL) {
> > +             GElf_Shdr sh;
> > +             char *name;
> > +
> > +             idx++;
> > +             if (gelf_getshdr(scn, &sh) != &sh) {
> > +                     p_err("failed to get section(%d) header from %s",
> > +                           idx, path);
> > +                     goto done;
> > +             }
> > +             name = elf_strptr(elf, ehdr.e_shstrndx, sh.sh_name);
> > +             if (!name) {
> > +                     p_err("failed to get section(%d) name from %s",
> > +                           idx, path);
> > +                     goto done;
> > +             }
> > +             if (strcmp(name, BTF_ELF_SEC) == 0) {
> > +                     btf_data = elf_getdata(scn, 0);
> > +                     if (!btf_data) {
> > +                             p_err("failed to get section(%d, %s) data from %s",
> > +                                   idx, name, path);
> > +                             goto done;
> > +                     }
> > +                     break;
> > +             }
> > +     }
> > +
> > +     if (!btf_data) {
> > +             p_err("%s ELF section not found in %s", BTF_ELF_SEC, path);
> > +             goto done;
> > +     }
> > +
> > +     *btf = btf__new(btf_data->d_buf, btf_data->d_size);
> > +     if (IS_ERR(*btf)) {
> > +             err = PTR_ERR(*btf);
> > +             *btf = NULL;
> > +             p_err("failed to load BTF data from %s: %s",
> > +                   path, strerror(err));
> > +             goto done;
> > +     }
> > +
> > +     err = 0;
> > +done:
> > +     if (err) {
> > +             if (*btf) {
> > +                     btf__free(*btf);
> > +                     *btf = NULL;
> > +             }
> > +     }
> > +     if (elf)
> > +             elf_end(elf);
> > +     close(fd);
> > +     return err;
> > +}
> > +
> [...]
> > +}
> > diff --git a/tools/bpf/bpftool/main.c b/tools/bpf/bpftool/main.c
> > index a9d5e9e6a732..eba56edd7c77 100644
> > --- a/tools/bpf/bpftool/main.c
> > +++ b/tools/bpf/bpftool/main.c
> > @@ -188,6 +188,7 @@ static const struct cmd cmds[] = {
> >       { "perf",       do_perf },
> >       { "net",        do_net },
> >       { "feature",    do_feature },
> > +     { "btf",        do_btf },
> >       { "version",    do_version },
> >       { 0 }
> >   };
> > diff --git a/tools/bpf/bpftool/main.h b/tools/bpf/bpftool/main.h
> > index 1ccc46169a19..3d63feb7f852 100644
> > --- a/tools/bpf/bpftool/main.h
> > +++ b/tools/bpf/bpftool/main.h
> > @@ -150,6 +150,7 @@ int do_perf(int argc, char **arg);
> >   int do_net(int argc, char **arg);
> >   int do_tracelog(int argc, char **arg);
> >   int do_feature(int argc, char **argv);
> > +int do_btf(int argc, char **argv);
> >
> >   int parse_u32_arg(int *argc, char ***argv, __u32 *val, const char *what);
> >   int prog_parse_fd(int *argc, char ***argv);
> >

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH bpf-next 1/2] bpftool: add ability to dump BTF types
  2019-04-24 18:16     ` Andrii Nakryiko
@ 2019-04-24 18:40       ` Yonghong Song
  0 siblings, 0 replies; 7+ messages in thread
From: Yonghong Song @ 2019-04-24 18:40 UTC (permalink / raw)
  To: Andrii Nakryiko
  Cc: Kernel Team, netdev, bpf, Alexei Starovoitov, daniel, Song Liu,
	Martin Lau, acme, Andrii Nakryiko, Arnaldo Carvalho de Melo



On 4/24/19 11:16 AM, Andrii Nakryiko wrote:
> On Wed, Apr 24, 2019 at 10:17 AM Yonghong Song <yhs@fb.com> wrote:
>>
>>
>>
>> On 4/23/19 10:21 PM, andrii.nakryiko@gmail.com wrote:
>>> From: Andrii Nakryiko <andriin@fb.com>
>>>
>>> Add new `btf dump` sub-command to bpftool. It allows to dump
>>> human-readable low-level BTF types representation of BTF types. BTF can
>>> be retrieved from few different sources:
>>>     - from BTF object by ID;
>>>     - from PROG, if it has associated BTF;
>>>     - from MAP, if it has associated BTF data; it's possible to narrow
>>>       down types to either key type, value type, both, or all BTF types;
>>>     - from ELF file (.BTF section).
>>>
>>> Output format mostly follows BPF verifier log format with few notable
>>> exceptions:
>>>     - all the type/field/param/etc names are enclosed in single quotes to
>>>       allow easier grepping and to stand out a little bit more;
>>>     - FUNC_PROTO output follows STRUCT/UNION/ENUM format of having one
>>>       line per each argument; this is more uniform and allows easy
>>>       grepping, as opposed to succinct, but inconvenient format that BPF
>>>       verifier log is using.
>>>
>>> Cc: Daniel Borkmann <daniel@iogearbox.net>
>>> Cc: Alexei Starovoitov <ast@fb.com>
>>> Cc: Yonghong Song <yhs@fb.com>
>>> Cc: Martin KaFai Lau <kafai@fb.com>
>>> Cc: Song Liu <songliubraving@fb.com>
>>> Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
>>> Signed-off-by: Andrii Nakryiko <andriin@fb.com>
>>> ---
>>>    tools/bpf/bpftool/btf.c  | 576 +++++++++++++++++++++++++++++++++++++++
>>>    tools/bpf/bpftool/main.c |   1 +
>>>    tools/bpf/bpftool/main.h |   1 +
>>>    3 files changed, 578 insertions(+)
>>>    create mode 100644 tools/bpf/bpftool/btf.c
>>>
>>> diff --git a/tools/bpf/bpftool/btf.c b/tools/bpf/bpftool/btf.c
>>> new file mode 100644
>>> index 000000000000..afe5cb7bab0c
>>> --- /dev/null
>>> +++ b/tools/bpf/bpftool/btf.c
>>> @@ -0,0 +1,576 @@
>>> +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
>>> +/* Copyright (C) 2019 Facebook */
>>> +
>>> +#include <errno.h>
>>> +#include <fcntl.h>
>>> +#include <linux/err.h>
>>> +#include <stdbool.h>
>>> +#include <stdio.h>
>>> +#include <string.h>
>>> +#include <unistd.h>
>>> +#include <gelf.h>
>>> +#include <bpf.h>
>>> +#include <linux/btf.h>
>>> +
>>> +#include "btf.h"
>>> +#include "json_writer.h"
>>> +#include "main.h"
>>> +
>>> +static const char * const btf_kind_str[NR_BTF_KINDS] = {
>>> +     [BTF_KIND_UNKN]         = "UNKNOWN",
>>> +     [BTF_KIND_INT]          = "INT",
>>> +     [BTF_KIND_PTR]          = "PTR",
>>> +     [BTF_KIND_ARRAY]        = "ARRAY",
>>> +     [BTF_KIND_STRUCT]       = "STRUCT",
>>> +     [BTF_KIND_UNION]        = "UNION",
>>> +     [BTF_KIND_ENUM]         = "ENUM",
>>> +     [BTF_KIND_FWD]          = "FWD",
>>> +     [BTF_KIND_TYPEDEF]      = "TYPEDEF",
>>> +     [BTF_KIND_VOLATILE]     = "VOLATILE",
>>> +     [BTF_KIND_CONST]        = "CONST",
>>> +     [BTF_KIND_RESTRICT]     = "RESTRICT",
>>> +     [BTF_KIND_FUNC]         = "FUNC",
>>> +     [BTF_KIND_FUNC_PROTO]   = "FUNC_PROTO",
>>> +     [BTF_KIND_VAR]          = "VAR",
>>> +     [BTF_KIND_DATASEC]      = "DATASEC",
>>> +};
>>> +
>>> +static const char *btf_int_enc_str(__u8 encoding)
>>> +{
>>> +     switch (encoding) {
>>> +     case 0:
>>> +             return "(none)";
>>> +     case BTF_INT_SIGNED:
>>> +             return "SIGNED";
>>> +     case BTF_INT_CHAR:
>>> +             return "CHAR";
>>> +     case BTF_INT_BOOL:
>>> +             return "BOOL";
>>> +     default:
>>> +             return "UNKN";
>>> +     }
>>> +}
>>> +
>>> +static const char *btf_var_linkage_str(__u32 linkage)
>>> +{
>>> +     switch (linkage) {
>>> +     case BTF_VAR_STATIC:
>>> +             return "static";
>>> +     case BTF_VAR_GLOBAL_ALLOCATED:
>>> +             return "global-alloc";
>>> +     default:
>>> +             return "(unknown)";
>>> +     }
>>> +}
>>> +
>> [...]
>>> +
>>> +static bool check_btf_endianness(GElf_Ehdr *ehdr)
>>> +{
>>> +     static unsigned int const endian = 1;
>>> +
>>> +     switch (ehdr->e_ident[EI_DATA]) {
>>> +     case ELFDATA2LSB:
>>> +             return *(unsigned char const *)&endian == 1;
>>> +     case ELFDATA2MSB:
>>> +             return *(unsigned char const *)&endian == 0;
>>> +     default:
>>> +             return 0;
>>> +     }
>>> +}
>>> +
>>> +static int btf_load_from_elf(const char *path, struct btf **btf)
>>> +{
>>> +     int err = -1, fd = -1, idx = 0;
>>> +     Elf_Data *btf_data = NULL;
>>> +     Elf_Scn *scn = NULL;
>>> +     Elf *elf = NULL;
>>> +     GElf_Ehdr ehdr;
>>> +
>>> +     if (elf_version(EV_CURRENT) == EV_NONE) {
>>> +             p_err("failed to init libelf for %s", path);
>>> +             return -1;
>>> +     }
>>> +
>>> +     fd = open(path, O_RDONLY);
>>> +     if (fd < 0) {
>>> +             p_err("failed to open %s: %s", path, strerror(errno));
>>> +             return -1;
>>> +     }
>>> +
>>> +     elf = elf_begin(fd, ELF_C_READ, NULL);
>>> +     if (!elf) {
>>> +             p_err("failed to open %s as ELF file", path);
>>> +             goto done;
>>> +     }
>>> +     if (!gelf_getehdr(elf, &ehdr)) {
>>> +             p_err("failed to get EHDR from %s", path);
>>> +             goto done;
>>> +     }
>>> +     if (!check_btf_endianness(&ehdr)) {
>>> +             p_err("non-native ELF endianness is not supported");
>>
>> We should relex this. It is possible that for some embedded system,
>> bpftool is running on some x86 server examining a objfile file used
>> for an embedded system.
> 
> I agree, but I think that should be done in libbpf. I've been meaning
> to add that for a while now, but never got around to that, it's still
> on my TODO list.
> 
> My intent is to teach btf__new to look at BTF header, and if it's
> endianness is not native, convert all the integers to native
> endianness. That way, struct btf is always of native endianness in
> memory and won't require any extra checks from other code. I'll do it
> some time soonish at which point both pahole (which handles this
> explicitly right now) and bpftool can greatly benefit from that. How
> does that sound?

This sounds good. libbpf seems the right place to go.

> 
>>
>>> +             goto done;
>>> +     }
>>> +     if (!elf_rawdata(elf_getscn(elf, ehdr.e_shstrndx), NULL)) {
>>> +             p_err("failed to get e_shstrndx from %s\n", path);
>>> +             goto done;
>>> +     }
>>> +
>>> +     while ((scn = elf_nextscn(elf, scn)) != NULL) {
>>> +             GElf_Shdr sh;
>>> +             char *name;
>>> +
>>> +             idx++;
>>> +             if (gelf_getshdr(scn, &sh) != &sh) {
>>> +                     p_err("failed to get section(%d) header from %s",
>>> +                           idx, path);
>>> +                     goto done;
>>> +             }
>>> +             name = elf_strptr(elf, ehdr.e_shstrndx, sh.sh_name);
>>> +             if (!name) {
>>> +                     p_err("failed to get section(%d) name from %s",
>>> +                           idx, path);
>>> +                     goto done;
>>> +             }
>>> +             if (strcmp(name, BTF_ELF_SEC) == 0) {
>>> +                     btf_data = elf_getdata(scn, 0);
>>> +                     if (!btf_data) {
>>> +                             p_err("failed to get section(%d, %s) data from %s",
>>> +                                   idx, name, path);
>>> +                             goto done;
>>> +                     }
>>> +                     break;
>>> +             }
>>> +     }
>>> +
>>> +     if (!btf_data) {
>>> +             p_err("%s ELF section not found in %s", BTF_ELF_SEC, path);
>>> +             goto done;
>>> +     }
>>> +
>>> +     *btf = btf__new(btf_data->d_buf, btf_data->d_size);
>>> +     if (IS_ERR(*btf)) {
>>> +             err = PTR_ERR(*btf);
>>> +             *btf = NULL;
>>> +             p_err("failed to load BTF data from %s: %s",
>>> +                   path, strerror(err));
>>> +             goto done;
>>> +     }
>>> +
>>> +     err = 0;
>>> +done:
>>> +     if (err) {
>>> +             if (*btf) {
>>> +                     btf__free(*btf);
>>> +                     *btf = NULL;
>>> +             }
>>> +     }
>>> +     if (elf)
>>> +             elf_end(elf);
>>> +     close(fd);
>>> +     return err;
>>> +}
>>> +
>> [...]
>>> +}
>>> diff --git a/tools/bpf/bpftool/main.c b/tools/bpf/bpftool/main.c
>>> index a9d5e9e6a732..eba56edd7c77 100644
>>> --- a/tools/bpf/bpftool/main.c
>>> +++ b/tools/bpf/bpftool/main.c
>>> @@ -188,6 +188,7 @@ static const struct cmd cmds[] = {
>>>        { "perf",       do_perf },
>>>        { "net",        do_net },
>>>        { "feature",    do_feature },
>>> +     { "btf",        do_btf },
>>>        { "version",    do_version },
>>>        { 0 }
>>>    };
>>> diff --git a/tools/bpf/bpftool/main.h b/tools/bpf/bpftool/main.h
>>> index 1ccc46169a19..3d63feb7f852 100644
>>> --- a/tools/bpf/bpftool/main.h
>>> +++ b/tools/bpf/bpftool/main.h
>>> @@ -150,6 +150,7 @@ int do_perf(int argc, char **arg);
>>>    int do_net(int argc, char **arg);
>>>    int do_tracelog(int argc, char **arg);
>>>    int do_feature(int argc, char **argv);
>>> +int do_btf(int argc, char **argv);
>>>
>>>    int parse_u32_arg(int *argc, char ***argv, __u32 *val, const char *what);
>>>    int prog_parse_fd(int *argc, char ***argv);
>>>

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH bpf-next 2/2] bpftool/docs: add btf sub-command documentation
  2019-04-24 17:21   ` [PATCH bpf-next 2/2] bpftool/docs: add btf sub-command documentation Yonghong Song
@ 2019-04-24 19:01     ` Andrii Nakryiko
  0 siblings, 0 replies; 7+ messages in thread
From: Andrii Nakryiko @ 2019-04-24 19:01 UTC (permalink / raw)
  To: Yonghong Song
  Cc: Kernel Team, netdev, bpf, Alexei Starovoitov, daniel, Song Liu,
	Martin Lau, acme, Andrii Nakryiko, Arnaldo Carvalho de Melo

On Wed, Apr 24, 2019 at 10:21 AM Yonghong Song <yhs@fb.com> wrote:
>
>
>
> On 4/23/19 10:22 PM, andrii.nakryiko@gmail.com wrote:
> > From: Andrii Nakryiko <andriin@fb.com>
> >
> > Document usage and sample output format for `btf dump` sub-command.
>
> When applying the patch, I see a few trailing spaces.
>
> ===
> p2.txt:113: trailing whitespace.
>
> p2.txt:118: trailing whitespace.
>
> p2.txt:120: trailing whitespace.
>
> p2.txt:129: trailing whitespace.
>
> p2.txt:134: trailing whitespace.
> ===
>
> You may want to take a look.

I assumed they are necessary for single code block in ReST. But I just
tried to remove them and it seems the resulting generated man page
looks the same, so I'll remove them.

>
> Could you add bash completion as well?

Yeah, sure, I'll add it as third patch in v2.

>
> >
> > Cc: Daniel Borkmann <daniel@iogearbox.net>
> > Cc: Alexei Starovoitov <ast@fb.com>
> > Cc: Yonghong Song <yhs@fb.com>
> > Cc: Martin KaFai Lau <kafai@fb.com>
> > Cc: Song Liu <songliubraving@fb.com>
> > Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
> > Signed-off-by: Andrii Nakryiko <andriin@fb.com>
> > ---
> >   .../bpf/bpftool/Documentation/bpftool-btf.rst | 205 ++++++++++++++++++
> >   .../bpftool/Documentation/bpftool-cgroup.rst  |   3 +-
> >   .../bpftool/Documentation/bpftool-feature.rst |   3 +-
> >   .../bpf/bpftool/Documentation/bpftool-map.rst |   3 +-
> >   .../bpf/bpftool/Documentation/bpftool-net.rst |   3 +-
> >   .../bpftool/Documentation/bpftool-perf.rst    |   3 +-
> >   .../bpftool/Documentation/bpftool-prog.rst    |   3 +-
> >   tools/bpf/bpftool/Documentation/bpftool.rst   |   3 +-
> >   8 files changed, 219 insertions(+), 7 deletions(-)
> >   create mode 100644 tools/bpf/bpftool/Documentation/bpftool-btf.rst
> >
> > diff --git a/tools/bpf/bpftool/Documentation/bpftool-btf.rst b/tools/bpf/bpftool/Documentation/bpftool-btf.rst
> > new file mode 100644
> > index 000000000000..955aaaba93a0
> > --- /dev/null
> > +++ b/tools/bpf/bpftool/Documentation/bpftool-btf.rst
> > @@ -0,0 +1,205 @@
> > +================
> > +bpftool-btf
> > +================
> > +-------------------------------------------------------------------------------
> > +tool for inspection of BTF data
> > +-------------------------------------------------------------------------------
> > +
> > +:Manual section: 8
> > +
> > +SYNOPSIS
> > +========
> > +
> > +     **bpftool** [*OPTIONS*] **btf** *COMMAND*
> > +
> > +     *OPTIONS* := { { **-j** | **--json** } [{ **-p** | **--pretty** }] }
> > +
> > +     *COMMANDS* :=
> > +     { **dump** | **help** }
> > +
> > +MAP COMMANDS
> > +=============
> > +
> > +|    **bpftool** **btf dump**       *BTF_SRC*
> > +|    **bpftool** **btf help**
> > +|
> > +|    *BTF_SRC* := { **id** *BTF_ID* | **prog** *PROG* | **map** *MAP* [{**key** | **value** | **kv** | **all**}] | **file** *FILE* }
> > +|    *MAP* := { **id** *MAP_ID* | **pinned** *FILE* }
> > +|    *PROG* := { **id** *PROG_ID* | **pinned** *FILE* | **tag** *PROG_TAG* }
> > +
> > +DESCRIPTION
> > +===========
> > +     **bpftool map dump**    *MAP*
> > +               Dump BTF entries from a given *BTF_SRC*.
> > +
> > +     **bpftool map help**
> > +               Print short help message.
> > +
> > +OPTIONS
> > +=======
> > +     -h, --help
> > +               Print short generic help message (similar to **bpftool help**).
> > +
> > +     -V, --version
> > +               Print version number (similar to **bpftool version**).
> > +
> > +     -j, --json
> > +               Generate JSON output. For commands that cannot produce JSON, this
> > +               option has no effect.
> > +
> > +     -p, --pretty
> > +               Generate human-readable JSON output. Implies **-j**.
> > +
> > +EXAMPLES
> > +========
> > +**# bpftool btf dump id 1226**
> > +::
> > +
> > +  [1] PTR '(anon)' type_id=2
> > +  [2] STRUCT 'dummy_tracepoint_args' size=16 vlen=2
> > +          'pad' type_id=3 bits_offset=0
> > +          'sock' type_id=4 bits_offset=64
> > +  [3] INT 'long long unsigned int' size=8 bits_offset=0 nr_bits=64 encoding=(none)
> > +  [4] PTR '(anon)' type_id=5
> > +  [5] FWD 'sock' fwd_kind=union
> > +
> > +This gives an example of default output for all supported BTF kinds.
> > +
> > +**$ cat prog.c**
> > +::
> > +
> > +  struct fwd_struct;
> > +
> > +  enum my_enum {
> > +          VAL1 = 3,
> > +          VAL2 = 7,
> > +  };
> > +
> > +  typedef struct my_struct my_struct_t;
> > +
> > +  struct my_struct {
> > +          const unsigned int const_int_field;
> > +          int bitfield_field: 4;
> > +          char arr_field[16];
> > +          const struct fwd_struct *restrict fwd_field;
> > +          enum my_enum enum_field;
> > +          volatile my_struct_t *typedef_ptr_field;
> > +  };
> > +
> > +  union my_union {
> > +          int a;
> > +          struct my_struct b;
> > +  };
> > +
> > +  struct my_struct struct_global_var __attribute__((section("data_sec"))) = {
> > +          .bitfield_field = 3,
> > +          .enum_field = VAL1,
> > +  };
> > +  int global_var __attribute__((section("data_sec"))) = 7;
> > +
> > +  __attribute__((noinline))
> > +  int my_func(union my_union *arg1, int arg2)
> > +  {
> > +          static int static_var __attribute__((section("data_sec"))) = 123;
> > +          static_var++;
> > +          return static_var;
> > +  }
> > +
> > +**$ bpftool btf dump file prog.o**
> > +::
> > +
> > +  [1] PTR '(anon)' type_id=2
> > +  [2] UNION 'my_union' size=48 vlen=2
> > +          'a' type_id=3 bits_offset=0
> > +          'b' type_id=4 bits_offset=0
> > +  [3] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
> > +  [4] STRUCT 'my_struct' size=48 vlen=6
> > +          'const_int_field' type_id=5 bits_offset=0
> > +          'bitfield_field' type_id=3 bits_offset=32 bitfield_size=4
> > +          'arr_field' type_id=8 bits_offset=40
> > +          'fwd_field' type_id=10 bits_offset=192
> > +          'enum_field' type_id=14 bits_offset=256
> > +          'typedef_ptr_field' type_id=15 bits_offset=320
> > +  [5] CONST '(anon)' type_id=6
> > +  [6] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)
> > +  [7] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=SIGNED
> > +  [8] ARRAY '(anon)' type_id=7 index_type_id=9 nr_elems=16
> > +  [9] INT '__ARRAY_SIZE_TYPE__' size=4 bits_offset=0 nr_bits=32 encoding=(none)
> > +  [10] RESTRICT '(anon)' type_id=11
> > +  [11] PTR '(anon)' type_id=12
> > +  [12] CONST '(anon)' type_id=13
> > +  [13] FWD 'fwd_struct' fwd_kind=union
> > +  [14] ENUM 'my_enum' size=4 vlen=2
> > +          'VAL1' val=3
> > +          'VAL2' val=7
> > +  [15] PTR '(anon)' type_id=16
> > +  [16] VOLATILE '(anon)' type_id=17
> > +  [17] TYPEDEF 'my_struct_t' type_id=4
> > +  [18] FUNC_PROTO '(anon)' ret_type_id=3 vlen=2
> > +          'arg1' type_id=1
> > +          'arg2' type_id=3
> > +  [19] FUNC 'my_func' type_id=18
> > +  [20] VAR 'struct_global_var' type_id=4, linkage=global-alloc
> > +  [21] VAR 'global_var' type_id=3, linkage=global-alloc
> > +  [22] VAR 'my_func.static_var' type_id=3, linkage=static
> > +  [23] DATASEC 'data_sec' size=0 vlen=3
> > +          type_id=20 offset=0 size=48
> > +          type_id=21 offset=0 size=4
> > +          type_id=22 offset=52 size=4
> > +
> > +The following commands print BTF types associated with specified map's key,
> > +value, both key and value, and all BTF types, respectively. By default, both
> > +key and value types will be printed.
> > +
> > +**# bpftool btf dump map id 123 key**
> > +
> > +::
> > +
> > +  [39] TYPEDEF 'u32' type_id=37
> > +
> > +**# bpftool btf dump map id 123 value**
> > +
> > +::
> > +
> > +  [86] PTR '(anon)' type_id=87
> > +
> > +**# bpftool btf dump map id 123 kv**
> > +
> > +::
> > +
> > +  [39] TYPEDEF 'u32' type_id=37
> > +  [86] PTR '(anon)' type_id=87
> > +
> > +**# bpftool btf dump map id 123 all**
> > +
> > +::
> > +
> > +  [1] PTR '(anon)' type_id=0
> > +  .
> > +  .
> > +  .
> > +  [2866] ARRAY '(anon)' type_id=52 index_type_id=51 nr_elems=4
> > +
> > +All the standard ways to specify map or program is supported:
> > +
> > +**# bpftool btf dump map id 123**
> > +
> > +**# bpftool btf dump map pinned /sys/fs/bpf/map_name**
> > +
> > +**# bpftool btf dump prog id 456**
> > +
> > +**# bpftool btf dump prog tag b88e0a09b1d9759d**
> > +
> > +**# bpftool btf dump prog pinned /sys/fs/bpf/prog_name**
> > +
> > +SEE ALSO
> > +========
> > +     **bpf**\ (2),
> > +     **bpf-helpers**\ (7),
> > +     **bpftool**\ (8),
> > +     **bpftool-map**\ (8),
> > +     **bpftool-prog**\ (8),
> > +     **bpftool-cgroup**\ (8),
> > +     **bpftool-feature**\ (8),
> > +     **bpftool-net**\ (8),
> > +     **bpftool-perf**\ (8)
> > diff --git a/tools/bpf/bpftool/Documentation/bpftool-cgroup.rst b/tools/bpf/bpftool/Documentation/bpftool-cgroup.rst
> > index 89b6b10e2183..ac26876389c2 100644
> > --- a/tools/bpf/bpftool/Documentation/bpftool-cgroup.rst
> > +++ b/tools/bpf/bpftool/Documentation/bpftool-cgroup.rst
> > @@ -145,4 +145,5 @@ SEE ALSO
> >       **bpftool-map**\ (8),
> >       **bpftool-feature**\ (8),
> >       **bpftool-net**\ (8),
> > -     **bpftool-perf**\ (8)
> > +     **bpftool-perf**\ (8),
> > +     **bpftool-btf**\ (8)
> > diff --git a/tools/bpf/bpftool/Documentation/bpftool-feature.rst b/tools/bpf/bpftool/Documentation/bpftool-feature.rst
> > index 10177343b7ce..14180e887082 100644
> > --- a/tools/bpf/bpftool/Documentation/bpftool-feature.rst
> > +++ b/tools/bpf/bpftool/Documentation/bpftool-feature.rst
> > @@ -82,4 +82,5 @@ SEE ALSO
> >       **bpftool-map**\ (8),
> >       **bpftool-cgroup**\ (8),
> >       **bpftool-net**\ (8),
> > -     **bpftool-perf**\ (8)
> > +     **bpftool-perf**\ (8),
> > +     **bpftool-btf**\ (8)
> > diff --git a/tools/bpf/bpftool/Documentation/bpftool-map.rst b/tools/bpf/bpftool/Documentation/bpftool-map.rst
> > index 55ecf80ca03e..13ef27b39f20 100644
> > --- a/tools/bpf/bpftool/Documentation/bpftool-map.rst
> > +++ b/tools/bpf/bpftool/Documentation/bpftool-map.rst
> > @@ -258,4 +258,5 @@ SEE ALSO
> >       **bpftool-cgroup**\ (8),
> >       **bpftool-feature**\ (8),
> >       **bpftool-net**\ (8),
> > -     **bpftool-perf**\ (8)
> > +     **bpftool-perf**\ (8),
> > +     **bpftool-btf**\ (8)
> > diff --git a/tools/bpf/bpftool/Documentation/bpftool-net.rst b/tools/bpf/bpftool/Documentation/bpftool-net.rst
> > index 6b692b428373..934580850f42 100644
> > --- a/tools/bpf/bpftool/Documentation/bpftool-net.rst
> > +++ b/tools/bpf/bpftool/Documentation/bpftool-net.rst
> > @@ -143,4 +143,5 @@ SEE ALSO
> >       **bpftool-map**\ (8),
> >       **bpftool-cgroup**\ (8),
> >       **bpftool-feature**\ (8),
> > -     **bpftool-perf**\ (8)
> > +     **bpftool-perf**\ (8),
> > +     **bpftool-btf**\ (8)
> > diff --git a/tools/bpf/bpftool/Documentation/bpftool-perf.rst b/tools/bpf/bpftool/Documentation/bpftool-perf.rst
> > index 86154740fabb..0c7576523a21 100644
> > --- a/tools/bpf/bpftool/Documentation/bpftool-perf.rst
> > +++ b/tools/bpf/bpftool/Documentation/bpftool-perf.rst
> > @@ -85,4 +85,5 @@ SEE ALSO
> >       **bpftool-map**\ (8),
> >       **bpftool-cgroup**\ (8),
> >       **bpftool-feature**\ (8),
> > -     **bpftool-net**\ (8)
> > +     **bpftool-net**\ (8),
> > +     **bpftool-btf**\ (8)
> > diff --git a/tools/bpf/bpftool/Documentation/bpftool-prog.rst b/tools/bpf/bpftool/Documentation/bpftool-prog.rst
> > index 2f183ffd8351..e8118544d118 100644
> > --- a/tools/bpf/bpftool/Documentation/bpftool-prog.rst
> > +++ b/tools/bpf/bpftool/Documentation/bpftool-prog.rst
> > @@ -271,4 +271,5 @@ SEE ALSO
> >       **bpftool-cgroup**\ (8),
> >       **bpftool-feature**\ (8),
> >       **bpftool-net**\ (8),
> > -     **bpftool-perf**\ (8)
> > +     **bpftool-perf**\ (8),
> > +     **bpftool-btf**\ (8)
> > diff --git a/tools/bpf/bpftool/Documentation/bpftool.rst b/tools/bpf/bpftool/Documentation/bpftool.rst
> > index deb2ca911ddf..3e562d7fd56f 100644
> > --- a/tools/bpf/bpftool/Documentation/bpftool.rst
> > +++ b/tools/bpf/bpftool/Documentation/bpftool.rst
> > @@ -76,4 +76,5 @@ SEE ALSO
> >       **bpftool-cgroup**\ (8),
> >       **bpftool-feature**\ (8),
> >       **bpftool-net**\ (8),
> > -     **bpftool-perf**\ (8)
> > +     **bpftool-perf**\ (8),
> > +     **bpftool-btf**\ (8)
> >

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2019-04-24 19:01 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <20190424052200.1625142-1-andrii.nakryiko@gmail.com>
     [not found] ` <20190424052200.1625142-2-andrii.nakryiko@gmail.com>
2019-04-24 17:12   ` [PATCH bpf-next 1/2] bpftool: add ability to dump BTF types Yonghong Song
2019-04-24 18:12     ` Andrii Nakryiko
2019-04-24 17:17   ` Yonghong Song
2019-04-24 18:16     ` Andrii Nakryiko
2019-04-24 18:40       ` Yonghong Song
     [not found] ` <20190424052200.1625142-3-andrii.nakryiko@gmail.com>
2019-04-24 17:21   ` [PATCH bpf-next 2/2] bpftool/docs: add btf sub-command documentation Yonghong Song
2019-04-24 19:01     ` Andrii Nakryiko

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).