Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1278628 > unrolled thread

[PATCH v2 02/13] bpf tools: Extract and collect map names from BPF object file

Started byWang Nan <wangnan0@huawei.com>
First post2015-11-27 09:50 +0100
Last post2015-11-30 12:30 +0100
Articles 10 — 5 participants

Back to article view | Back to linux.kernel

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  [PATCH v2 02/13] bpf tools: Extract and collect map names from BPF object file Wang Nan <wangnan0@huawei.com> - 2015-11-27 09:50 +0100
    [tip:perf/core] tools lib bpf:   Extract and collect map names from BPF object file tip-bot for Wang Nan <tipbot@zytor.com> - 2015-11-29 09:00 +0100
    Re: [PATCH v2 02/13] bpf tools: Extract and collect map names from  BPF object file Namhyung Kim <namhyung@kernel.org> - 2015-11-29 17:20 +0100
      Re: [PATCH v2 02/13] bpf tools: Extract and collect map names from  BPF object file "Wangnan (F)" <wangnan0@huawei.com> - 2015-11-30 06:10 +0100
        Re: [PATCH v2 02/13] bpf tools: Extract and collect map names from  BPF object file Namhyung Kim <namhyung@kernel.org> - 2015-11-30 10:00 +0100
          Re: [PATCH v2 02/13] bpf tools: Extract and collect map names from  BPF object file "Wangnan (F)" <wangnan0@huawei.com> - 2015-11-30 10:30 +0100
            Re: [PATCH v2 02/13] bpf tools: Extract and collect map names from BPF object file Namhyung Kim <namhyung@gmail.com> - 2015-11-30 10:50 +0100
              Re: [PATCH v2 02/13] bpf tools: Extract and collect map names from  BPF object file "Wangnan (F)" <wangnan0@huawei.com> - 2015-11-30 10:50 +0100
              [PATCH] tools lib bpf: Fetch map names from correct strtab Wang Nan <wangnan0@huawei.com> - 2015-11-30 11:40 +0100
                Re: [PATCH] tools lib bpf: Fetch map names from correct strtab Namhyung Kim <namhyung@kernel.org> - 2015-11-30 12:30 +0100

#1278628 — [PATCH v2 02/13] bpf tools: Extract and collect map names from BPF object file

FromWang Nan <wangnan0@huawei.com>
Date2015-11-27 09:50 +0100
Subject[PATCH v2 02/13] bpf tools: Extract and collect map names from BPF object file
Message-ID<qzmT8-uQ-1@gated-at.bofh.it>
This patch collects name of maps in BPF object files and saves them into
'maps' field in 'struct bpf_object'. 'bpf_object__get_map_by_name' is
introduced to retrive fd and definitions of a map through its name.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Signed-off-by: He Kuang <hekuang@huawei.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
---
 tools/lib/bpf/libbpf.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++---
 tools/lib/bpf/libbpf.h |  3 +++
 2 files changed, 65 insertions(+), 3 deletions(-)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index f509825..a298614 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -165,6 +165,7 @@ struct bpf_program {
 
 struct bpf_map {
 	int fd;
+	char *name;
 	struct bpf_map_def def;
 	void *priv;
 	bpf_map_clear_priv_t clear_priv;
@@ -526,12 +527,46 @@ bpf_object__init_maps(struct bpf_object *obj, void *data,
 	return 0;
 }
 
+static void
+bpf_object__init_maps_name(struct bpf_object *obj, int maps_shndx)
+{
+	int i;
+	Elf_Data *symbols = obj->efile.symbols;
+
+	if (!symbols || maps_shndx < 0)
+		return;
+
+	for (i = 0; i < symbols->d_size / sizeof(GElf_Sym); i++) {
+		GElf_Sym sym;
+		size_t map_idx;
+		const char *map_name;
+
+		if (!gelf_getsym(symbols, i, &sym))
+			continue;
+		if (sym.st_shndx != maps_shndx)
+			continue;
+
+		map_name = elf_strptr(obj->efile.elf,
+				      obj->efile.ehdr.e_shstrndx,
+				      sym.st_name);
+		map_idx = sym.st_value / sizeof(struct bpf_map_def);
+		if (map_idx >= obj->nr_maps) {
+			pr_warning("index of map \"%s\" is buggy: %zu > %zu\n",
+				   map_name, map_idx, obj->nr_maps);
+			continue;
+		}
+		obj->maps[map_idx].name = strdup(map_name);
+		pr_debug("map %zu is \"%s\"\n", map_idx,
+			 obj->maps[map_idx].name);
+	}
+}
+
 static int bpf_object__elf_collect(struct bpf_object *obj)
 {
 	Elf *elf = obj->efile.elf;
 	GElf_Ehdr *ep = &obj->efile.ehdr;
 	Elf_Scn *scn = NULL;
-	int idx = 0, err = 0;
+	int idx = 0, err = 0, maps_shndx = -1;
 
 	/* Elf is corrupted/truncated, avoid calling elf_strptr. */
 	if (!elf_rawdata(elf_getscn(elf, ep->e_shstrndx), NULL)) {
@@ -581,10 +616,11 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
 			err = bpf_object__init_kversion(obj,
 							data->d_buf,
 							data->d_size);
-		else if (strcmp(name, "maps") == 0)
+		else if (strcmp(name, "maps") == 0) {
 			err = bpf_object__init_maps(obj, data->d_buf,
 						    data->d_size);
-		else if (sh.sh_type == SHT_SYMTAB) {
+			maps_shndx = idx;
+		} else if (sh.sh_type == SHT_SYMTAB) {
 			if (obj->efile.symbols) {
 				pr_warning("bpf: multiple SYMTAB in %s\n",
 					   obj->path);
@@ -625,6 +661,9 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
 		if (err)
 			goto out;
 	}
+
+	if (maps_shndx >= 0)
+		bpf_object__init_maps_name(obj, maps_shndx);
 out:
 	return err;
 }
@@ -1086,6 +1125,7 @@ void bpf_object__close(struct bpf_object *obj)
 	bpf_object__unload(obj);
 
 	for (i = 0; i < obj->nr_maps; i++) {
+		zfree(&obj->maps[i].name);
 		if (obj->maps[i].clear_priv)
 			obj->maps[i].clear_priv(&obj->maps[i],
 						obj->maps[i].priv);
@@ -1266,6 +1306,13 @@ int bpf_map__get_def(struct bpf_map *map, struct bpf_map_def *pdef)
 	return 0;
 }
 
+const char *bpf_map__get_name(struct bpf_map *map)
+{
+	if (!map)
+		return NULL;
+	return map->name;
+}
+
 int bpf_map__set_private(struct bpf_map *map, void *priv,
 			 bpf_map_clear_priv_t clear_priv)
 {
@@ -1318,3 +1365,15 @@ bpf_map__next(struct bpf_map *prev, struct bpf_object *obj)
 		return NULL;
 	return &obj->maps[idx];
 }
+
+struct bpf_map *
+bpf_object__get_map_by_name(struct bpf_object *obj, const char *name)
+{
+	struct bpf_map *pos;
+
+	bpf_map__for_each(pos, obj) {
+		if (strcmp(pos->name, name) == 0)
+			return pos;
+	}
+	return NULL;
+}
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index ef63125..a51594c 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -170,6 +170,8 @@ struct bpf_map_def {
  * it is not a uapi header so no need to consider name clash.
  */
 struct bpf_map;
+struct bpf_map *
+bpf_object__get_map_by_name(struct bpf_object *obj, const char *name);
 
 struct bpf_map *
 bpf_map__next(struct bpf_map *map, struct bpf_object *obj);
@@ -180,6 +182,7 @@ bpf_map__next(struct bpf_map *map, struct bpf_object *obj);
 
 int bpf_map__get_fd(struct bpf_map *map);
 int bpf_map__get_def(struct bpf_map *map, struct bpf_map_def *pdef);
+const char *bpf_map__get_name(struct bpf_map *map);
 
 typedef void (*bpf_map_clear_priv_t)(struct bpf_map *, void *);
 int bpf_map__set_private(struct bpf_map *map, void *priv,
-- 
1.8.3.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [next] | [standalone]


#1279283 — [tip:perf/core] tools lib bpf: Extract and collect map names from BPF object file

Fromtip-bot for Wang Nan <tipbot@zytor.com>
Date2015-11-29 09:00 +0100
Subject[tip:perf/core] tools lib bpf: Extract and collect map names from BPF object file
Message-ID<qA53P-3nY-3@gated-at.bofh.it>
In reply to#1278628
Commit-ID:  561bbccac72d08babafaa33fd7fa9100ec4c9fb6
Gitweb:     http://git.kernel.org/tip/561bbccac72d08babafaa33fd7fa9100ec4c9fb6
Author:     Wang Nan <wangnan0@huawei.com>
AuthorDate: Fri, 27 Nov 2015 08:47:36 +0000
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Fri, 27 Nov 2015 21:59:53 -0300

tools lib bpf: Extract and collect map names from BPF object file

This patch collects name of maps in BPF object files and saves them into
'maps' field in 'struct bpf_object'. 'bpf_object__get_map_by_name' is
introduced to retrive fd and definitions of a map through its name.

Signed-off-by: He Kuang <hekuang@huawei.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: He Kuang <hekuang@huawei.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/1448614067-197576-3-git-send-email-wangnan0@huawei.com
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/lib/bpf/libbpf.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++---
 tools/lib/bpf/libbpf.h |  3 +++
 2 files changed, 65 insertions(+), 3 deletions(-)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index f509825..a298614 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -165,6 +165,7 @@ struct bpf_program {
 
 struct bpf_map {
 	int fd;
+	char *name;
 	struct bpf_map_def def;
 	void *priv;
 	bpf_map_clear_priv_t clear_priv;
@@ -526,12 +527,46 @@ bpf_object__init_maps(struct bpf_object *obj, void *data,
 	return 0;
 }
 
+static void
+bpf_object__init_maps_name(struct bpf_object *obj, int maps_shndx)
+{
+	int i;
+	Elf_Data *symbols = obj->efile.symbols;
+
+	if (!symbols || maps_shndx < 0)
+		return;
+
+	for (i = 0; i < symbols->d_size / sizeof(GElf_Sym); i++) {
+		GElf_Sym sym;
+		size_t map_idx;
+		const char *map_name;
+
+		if (!gelf_getsym(symbols, i, &sym))
+			continue;
+		if (sym.st_shndx != maps_shndx)
+			continue;
+
+		map_name = elf_strptr(obj->efile.elf,
+				      obj->efile.ehdr.e_shstrndx,
+				      sym.st_name);
+		map_idx = sym.st_value / sizeof(struct bpf_map_def);
+		if (map_idx >= obj->nr_maps) {
+			pr_warning("index of map \"%s\" is buggy: %zu > %zu\n",
+				   map_name, map_idx, obj->nr_maps);
+			continue;
+		}
+		obj->maps[map_idx].name = strdup(map_name);
+		pr_debug("map %zu is \"%s\"\n", map_idx,
+			 obj->maps[map_idx].name);
+	}
+}
+
 static int bpf_object__elf_collect(struct bpf_object *obj)
 {
 	Elf *elf = obj->efile.elf;
 	GElf_Ehdr *ep = &obj->efile.ehdr;
 	Elf_Scn *scn = NULL;
-	int idx = 0, err = 0;
+	int idx = 0, err = 0, maps_shndx = -1;
 
 	/* Elf is corrupted/truncated, avoid calling elf_strptr. */
 	if (!elf_rawdata(elf_getscn(elf, ep->e_shstrndx), NULL)) {
@@ -581,10 +616,11 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
 			err = bpf_object__init_kversion(obj,
 							data->d_buf,
 							data->d_size);
-		else if (strcmp(name, "maps") == 0)
+		else if (strcmp(name, "maps") == 0) {
 			err = bpf_object__init_maps(obj, data->d_buf,
 						    data->d_size);
-		else if (sh.sh_type == SHT_SYMTAB) {
+			maps_shndx = idx;
+		} else if (sh.sh_type == SHT_SYMTAB) {
 			if (obj->efile.symbols) {
 				pr_warning("bpf: multiple SYMTAB in %s\n",
 					   obj->path);
@@ -625,6 +661,9 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
 		if (err)
 			goto out;
 	}
+
+	if (maps_shndx >= 0)
+		bpf_object__init_maps_name(obj, maps_shndx);
 out:
 	return err;
 }
@@ -1086,6 +1125,7 @@ void bpf_object__close(struct bpf_object *obj)
 	bpf_object__unload(obj);
 
 	for (i = 0; i < obj->nr_maps; i++) {
+		zfree(&obj->maps[i].name);
 		if (obj->maps[i].clear_priv)
 			obj->maps[i].clear_priv(&obj->maps[i],
 						obj->maps[i].priv);
@@ -1266,6 +1306,13 @@ int bpf_map__get_def(struct bpf_map *map, struct bpf_map_def *pdef)
 	return 0;
 }
 
+const char *bpf_map__get_name(struct bpf_map *map)
+{
+	if (!map)
+		return NULL;
+	return map->name;
+}
+
 int bpf_map__set_private(struct bpf_map *map, void *priv,
 			 bpf_map_clear_priv_t clear_priv)
 {
@@ -1318,3 +1365,15 @@ bpf_map__next(struct bpf_map *prev, struct bpf_object *obj)
 		return NULL;
 	return &obj->maps[idx];
 }
+
+struct bpf_map *
+bpf_object__get_map_by_name(struct bpf_object *obj, const char *name)
+{
+	struct bpf_map *pos;
+
+	bpf_map__for_each(pos, obj) {
+		if (strcmp(pos->name, name) == 0)
+			return pos;
+	}
+	return NULL;
+}
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index ef63125..a51594c 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -170,6 +170,8 @@ struct bpf_map_def {
  * it is not a uapi header so no need to consider name clash.
  */
 struct bpf_map;
+struct bpf_map *
+bpf_object__get_map_by_name(struct bpf_object *obj, const char *name);
 
 struct bpf_map *
 bpf_map__next(struct bpf_map *map, struct bpf_object *obj);
@@ -180,6 +182,7 @@ bpf_map__next(struct bpf_map *map, struct bpf_object *obj);
 
 int bpf_map__get_fd(struct bpf_map *map);
 int bpf_map__get_def(struct bpf_map *map, struct bpf_map_def *pdef);
+const char *bpf_map__get_name(struct bpf_map *map);
 
 typedef void (*bpf_map_clear_priv_t)(struct bpf_map *, void *);
 int bpf_map__set_private(struct bpf_map *map, void *priv,
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1279370 — Re: [PATCH v2 02/13] bpf tools: Extract and collect map names from BPF object file

FromNamhyung Kim <namhyung@kernel.org>
Date2015-11-29 17:20 +0100
SubjectRe: [PATCH v2 02/13] bpf tools: Extract and collect map names from BPF object file
Message-ID<qAcRH-8lW-13@gated-at.bofh.it>
In reply to#1278628
Hi Wang,

On Fri, Nov 27, 2015 at 08:47:36AM +0000, Wang Nan wrote:
> This patch collects name of maps in BPF object files and saves them into
> 'maps' field in 'struct bpf_object'. 'bpf_object__get_map_by_name' is
> introduced to retrive fd and definitions of a map through its name.
> 
> Signed-off-by: Wang Nan <wangnan0@huawei.com>
> Signed-off-by: He Kuang <hekuang@huawei.com>
> Cc: Alexei Starovoitov <ast@kernel.org>
> Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
> Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
> Cc: Namhyung Kim <namhyung@kernel.org>
> Cc: Zefan Li <lizefan@huawei.com>
> Cc: pi3orama@163.com
> ---
>  tools/lib/bpf/libbpf.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++---
>  tools/lib/bpf/libbpf.h |  3 +++
>  2 files changed, 65 insertions(+), 3 deletions(-)
> 
> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> index f509825..a298614 100644
> --- a/tools/lib/bpf/libbpf.c
> +++ b/tools/lib/bpf/libbpf.c
> @@ -165,6 +165,7 @@ struct bpf_program {
>  
>  struct bpf_map {
>  	int fd;
> +	char *name;
>  	struct bpf_map_def def;
>  	void *priv;
>  	bpf_map_clear_priv_t clear_priv;
> @@ -526,12 +527,46 @@ bpf_object__init_maps(struct bpf_object *obj, void *data,
>  	return 0;
>  }
>  
> +static void
> +bpf_object__init_maps_name(struct bpf_object *obj, int maps_shndx)
> +{
> +	int i;
> +	Elf_Data *symbols = obj->efile.symbols;
> +
> +	if (!symbols || maps_shndx < 0)
> +		return;
> +
> +	for (i = 0; i < symbols->d_size / sizeof(GElf_Sym); i++) {
> +		GElf_Sym sym;
> +		size_t map_idx;
> +		const char *map_name;
> +
> +		if (!gelf_getsym(symbols, i, &sym))
> +			continue;
> +		if (sym.st_shndx != maps_shndx)
> +			continue;
> +
> +		map_name = elf_strptr(obj->efile.elf,
> +				      obj->efile.ehdr.e_shstrndx,
> +				      sym.st_name);

It means that each map name is saved in section header string table?


> +		map_idx = sym.st_value / sizeof(struct bpf_map_def);
> +		if (map_idx >= obj->nr_maps) {
> +			pr_warning("index of map \"%s\" is buggy: %zu > %zu\n",
> +				   map_name, map_idx, obj->nr_maps);
> +			continue;
> +		}
> +		obj->maps[map_idx].name = strdup(map_name);

You need to check the return value.

thanks,
Namhyung


> +		pr_debug("map %zu is \"%s\"\n", map_idx,
> +			 obj->maps[map_idx].name);
> +	}
> +}
> +
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1279563 — Re: [PATCH v2 02/13] bpf tools: Extract and collect map names from BPF object file

From"Wangnan (F)" <wangnan0@huawei.com>
Date2015-11-30 06:10 +0100
SubjectRe: [PATCH v2 02/13] bpf tools: Extract and collect map names from BPF object file
Message-ID<qAoSR-7Gx-5@gated-at.bofh.it>
In reply to#1279370

On 2015/11/30 0:14, Namhyung Kim wrote:
> Hi Wang,
>
> On Fri, Nov 27, 2015 at 08:47:36AM +0000, Wang Nan wrote:
>> This patch collects name of maps in BPF object files and saves them into
>> 'maps' field in 'struct bpf_object'. 'bpf_object__get_map_by_name' is
>> introduced to retrive fd and definitions of a map through its name.
>>
>> Signed-off-by: Wang Nan <wangnan0@huawei.com>
>> Signed-off-by: He Kuang <hekuang@huawei.com>
>> Cc: Alexei Starovoitov <ast@kernel.org>
>> Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
>> Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
>> Cc: Namhyung Kim <namhyung@kernel.org>
>> Cc: Zefan Li <lizefan@huawei.com>
>> Cc: pi3orama@163.com
>> ---
>>   tools/lib/bpf/libbpf.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++---
>>   tools/lib/bpf/libbpf.h |  3 +++
>>   2 files changed, 65 insertions(+), 3 deletions(-)
>>
>> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
>> index f509825..a298614 100644
>> --- a/tools/lib/bpf/libbpf.c
>> +++ b/tools/lib/bpf/libbpf.c
>> @@ -165,6 +165,7 @@ struct bpf_program {
>>   
>>   struct bpf_map {
>>   	int fd;
>> +	char *name;
>>   	struct bpf_map_def def;
>>   	void *priv;
>>   	bpf_map_clear_priv_t clear_priv;
>> @@ -526,12 +527,46 @@ bpf_object__init_maps(struct bpf_object *obj, void *data,
>>   	return 0;
>>   }
>>   
>> +static void
>> +bpf_object__init_maps_name(struct bpf_object *obj, int maps_shndx)
>> +{
>> +	int i;
>> +	Elf_Data *symbols = obj->efile.symbols;
>> +
>> +	if (!symbols || maps_shndx < 0)
>> +		return;
>> +
>> +	for (i = 0; i < symbols->d_size / sizeof(GElf_Sym); i++) {
>> +		GElf_Sym sym;
>> +		size_t map_idx;
>> +		const char *map_name;
>> +
>> +		if (!gelf_getsym(symbols, i, &sym))
>> +			continue;
>> +		if (sym.st_shndx != maps_shndx)
>> +			continue;
>> +
>> +		map_name = elf_strptr(obj->efile.elf,
>> +				      obj->efile.ehdr.e_shstrndx,
>> +				      sym.st_name);
> It means that each map name is saved in section header string table?

According to elf format specification:

For an symbol table entry, the st_name field "holds an index
into the object file’s symbol string table, which holds the
character representations of the symbol names. If the value
is non-zero, it represents a string table index that gives
the symbol name. Otherwise, the symbol table entry has no
name."

And so called "object file’s symbol string table" is a
section in the object file which index is stored into
ehdr and be loaded during gelf_getehdr(), and its index
would be set to ehdr->e_shstrndx. So I think for each map
its name should be saved in that string table.

>
>> +		map_idx = sym.st_value / sizeof(struct bpf_map_def);
>> +		if (map_idx >= obj->nr_maps) {
>> +			pr_warning("index of map \"%s\" is buggy: %zu > %zu\n",
>> +				   map_name, map_idx, obj->nr_maps);
>> +			continue;
>> +		}
>> +		obj->maps[map_idx].name = strdup(map_name);
> You need to check the return value.

Will send a patch for it.

Thank you.

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1279700 — Re: [PATCH v2 02/13] bpf tools: Extract and collect map names from BPF object file

FromNamhyung Kim <namhyung@kernel.org>
Date2015-11-30 10:00 +0100
SubjectRe: [PATCH v2 02/13] bpf tools: Extract and collect map names from BPF object file
Message-ID<qAstt-1kv-9@gated-at.bofh.it>
In reply to#1279563
On Mon, Nov 30, 2015 at 01:00:46PM +0800, Wangnan (F) wrote:
> 
> 
> On 2015/11/30 0:14, Namhyung Kim wrote:
> >Hi Wang,
> >
> >On Fri, Nov 27, 2015 at 08:47:36AM +0000, Wang Nan wrote:
> >>This patch collects name of maps in BPF object files and saves them into
> >>'maps' field in 'struct bpf_object'. 'bpf_object__get_map_by_name' is
> >>introduced to retrive fd and definitions of a map through its name.
> >>
> >>Signed-off-by: Wang Nan <wangnan0@huawei.com>
> >>Signed-off-by: He Kuang <hekuang@huawei.com>
> >>Cc: Alexei Starovoitov <ast@kernel.org>
> >>Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
> >>Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
> >>Cc: Namhyung Kim <namhyung@kernel.org>
> >>Cc: Zefan Li <lizefan@huawei.com>
> >>Cc: pi3orama@163.com
> >>---
> >>  tools/lib/bpf/libbpf.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++---
> >>  tools/lib/bpf/libbpf.h |  3 +++
> >>  2 files changed, 65 insertions(+), 3 deletions(-)
> >>
> >>diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> >>index f509825..a298614 100644
> >>--- a/tools/lib/bpf/libbpf.c
> >>+++ b/tools/lib/bpf/libbpf.c
> >>@@ -165,6 +165,7 @@ struct bpf_program {
> >>  struct bpf_map {
> >>  	int fd;
> >>+	char *name;
> >>  	struct bpf_map_def def;
> >>  	void *priv;
> >>  	bpf_map_clear_priv_t clear_priv;
> >>@@ -526,12 +527,46 @@ bpf_object__init_maps(struct bpf_object *obj, void *data,
> >>  	return 0;
> >>  }
> >>+static void
> >>+bpf_object__init_maps_name(struct bpf_object *obj, int maps_shndx)
> >>+{
> >>+	int i;
> >>+	Elf_Data *symbols = obj->efile.symbols;
> >>+
> >>+	if (!symbols || maps_shndx < 0)
> >>+		return;
> >>+
> >>+	for (i = 0; i < symbols->d_size / sizeof(GElf_Sym); i++) {
> >>+		GElf_Sym sym;
> >>+		size_t map_idx;
> >>+		const char *map_name;
> >>+
> >>+		if (!gelf_getsym(symbols, i, &sym))
> >>+			continue;
> >>+		if (sym.st_shndx != maps_shndx)
> >>+			continue;
> >>+
> >>+		map_name = elf_strptr(obj->efile.elf,
> >>+				      obj->efile.ehdr.e_shstrndx,
> >>+				      sym.st_name);
> >It means that each map name is saved in section header string table?
> 
> According to elf format specification:
> 
> For an symbol table entry, the st_name field "holds an index
> into the object file’s symbol string table, which holds the
> character representations of the symbol names. If the value
> is non-zero, it represents a string table index that gives
> the symbol name. Otherwise, the symbol table entry has no
> name."
> 
> And so called "object file’s symbol string table" is a
> section in the object file which index is stored into
> ehdr and be loaded during gelf_getehdr(), and its index
> would be set to ehdr->e_shstrndx. So I think for each map
> its name should be saved in that string table.

AFAIK there're two symbol string tables in a ELF file.  One for
section headers (.shstrtab) and another for normal symbols (.strtab).
And ehdr->e_shstrndx is the index of section header string table so
your code assumes map names are saved in the section header string
table, right?

Thanks,
Namhyung


> 
> >
> >>+		map_idx = sym.st_value / sizeof(struct bpf_map_def);
> >>+		if (map_idx >= obj->nr_maps) {
> >>+			pr_warning("index of map \"%s\" is buggy: %zu > %zu\n",
> >>+				   map_name, map_idx, obj->nr_maps);
> >>+			continue;
> >>+		}
> >>+		obj->maps[map_idx].name = strdup(map_name);
> >You need to check the return value.
> 
> Will send a patch for it.
> 
> Thank you.
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1279725 — Re: [PATCH v2 02/13] bpf tools: Extract and collect map names from BPF object file

From"Wangnan (F)" <wangnan0@huawei.com>
Date2015-11-30 10:30 +0100
SubjectRe: [PATCH v2 02/13] bpf tools: Extract and collect map names from BPF object file
Message-ID<qAsWt-1JR-17@gated-at.bofh.it>
In reply to#1279700

On 2015/11/30 16:51, Namhyung Kim wrote:
> On Mon, Nov 30, 2015 at 01:00:46PM +0800, Wangnan (F) wrote:
>>
>> On 2015/11/30 0:14, Namhyung Kim wrote:
>>> Hi Wang,
>>>
>>> On Fri, Nov 27, 2015 at 08:47:36AM +0000, Wang Nan wrote:
>>>> This patch collects name of maps in BPF object files and saves them into
>>>> 'maps' field in 'struct bpf_object'. 'bpf_object__get_map_by_name' is
>>>> introduced to retrive fd and definitions of a map through its name.
>>>>
>>>> Signed-off-by: Wang Nan <wangnan0@huawei.com>
>>>> Signed-off-by: He Kuang <hekuang@huawei.com>
>>>> Cc: Alexei Starovoitov <ast@kernel.org>
>>>> Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
>>>> Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
>>>> Cc: Namhyung Kim <namhyung@kernel.org>
>>>> Cc: Zefan Li <lizefan@huawei.com>
>>>> Cc: pi3orama@163.com
>>>> ---
>>>>   tools/lib/bpf/libbpf.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++---
>>>>   tools/lib/bpf/libbpf.h |  3 +++
>>>>   2 files changed, 65 insertions(+), 3 deletions(-)
>>>>
>>>> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
>>>> index f509825..a298614 100644
>>>> --- a/tools/lib/bpf/libbpf.c
>>>> +++ b/tools/lib/bpf/libbpf.c
>>>> @@ -165,6 +165,7 @@ struct bpf_program {
>>>>   struct bpf_map {
>>>>   	int fd;
>>>> +	char *name;
>>>>   	struct bpf_map_def def;
>>>>   	void *priv;
>>>>   	bpf_map_clear_priv_t clear_priv;
>>>> @@ -526,12 +527,46 @@ bpf_object__init_maps(struct bpf_object *obj, void *data,
>>>>   	return 0;
>>>>   }
>>>> +static void
>>>> +bpf_object__init_maps_name(struct bpf_object *obj, int maps_shndx)
>>>> +{
>>>> +	int i;
>>>> +	Elf_Data *symbols = obj->efile.symbols;
>>>> +
>>>> +	if (!symbols || maps_shndx < 0)
>>>> +		return;
>>>> +
>>>> +	for (i = 0; i < symbols->d_size / sizeof(GElf_Sym); i++) {
>>>> +		GElf_Sym sym;
>>>> +		size_t map_idx;
>>>> +		const char *map_name;
>>>> +
>>>> +		if (!gelf_getsym(symbols, i, &sym))
>>>> +			continue;
>>>> +		if (sym.st_shndx != maps_shndx)
>>>> +			continue;
>>>> +
>>>> +		map_name = elf_strptr(obj->efile.elf,
>>>> +				      obj->efile.ehdr.e_shstrndx,
>>>> +				      sym.st_name);
>>> It means that each map name is saved in section header string table?
>> According to elf format specification:
>>
>> For an symbol table entry, the st_name field "holds an index
>> into the object file’s symbol string table, which holds the
>> character representations of the symbol names. If the value
>> is non-zero, it represents a string table index that gives
>> the symbol name. Otherwise, the symbol table entry has no
>> name."
>>
>> And so called "object file’s symbol string table" is a
>> section in the object file which index is stored into
>> ehdr and be loaded during gelf_getehdr(), and its index
>> would be set to ehdr->e_shstrndx. So I think for each map
>> its name should be saved in that string table.
> AFAIK there're two symbol string tables in a ELF file.  One for
> section headers (.shstrtab) and another for normal symbols (.strtab).
> And ehdr->e_shstrndx is the index of section header string table so
> your code assumes map names are saved in the section header string
> table, right?
>
> Thanks,
> Namhyung

In case of gcc:

$ echo 'int func() {return 0;}' | gcc -x c -c -o ./temp.o -
$ readelf -h ./temp.o
ELF Header:
   Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
   Class:                             ELF64
   Data:                              2's complement, little endian
   Version:                           1 (current)
   OS/ABI:                            UNIX - System V
   ABI Version:                       0
   Type:                              REL (Relocatable file)
   Machine:                           Advanced Micro Devices X86-64
   Version:                           0x1
   Entry point address:               0x0
   Start of program headers:          0 (bytes into file)
   Start of section headers:          240 (bytes into file)
   Flags:                             0x0
   Size of this header:               64 (bytes)
   Size of program headers:           0 (bytes)
   Number of program headers:         0
   Size of section headers:           64 (bytes)
   Number of section headers:         11
   Section header string table index: 8

Let's see what is section 8:

$ readelf -S ./temp.o
   ...
   [ 8] .shstrtab         STRTAB           0000000000000000  00000098
        0000000000000054  0000000000000000           0     0     1
   ...

Yes, in this case it is .shstrtab.

However, this is what I found when using llvm:

$ echo 'int func() {return 0;}' | x86_64-oe-linux-clang -x c -c -o 
./temp.o -
ELF Header:
   Magic:   7f 45 4c 46 02 01 01 03 00 00 00 00 00 00 00 00
   Class:                             ELF64
   Data:                              2's complement, little endian
   Version:                           1 (current)
   OS/ABI:                            UNIX - GNU
   ABI Version:                       0
   Type:                              REL (Relocatable file)
   Machine:                           Advanced Micro Devices X86-64
   Version:                           0x1
   Entry point address:               0x0
   Start of program headers:          0 (bytes into file)
   Start of section headers:          648 (bytes into file)
   Flags:                             0x0
   Size of this header:               64 (bytes)
   Size of program headers:           0 (bytes)
   Number of program headers:         0
   Size of section headers:           64 (bytes)
   Number of section headers:         10
   Section header string table index: 1

$ readelf -S ./temp.o
There are 10 section headers, starting at offset 0x288:

Section Headers:
   [Nr] Name              Type             Address           Offset
        Size              EntSize          Flags  Link  Info  Align
   [ 0]                   NULL             0000000000000000  00000000
        0000000000000000  0000000000000000           0     0     0
   [ 1] .strtab           STRTAB           0000000000000000  00000230
        0000000000000051  0000000000000000           0     0     1

This time it is strtab.

And here is the content of strtab:

$ readelf -p .strtab ./temp.o

String dump of section '.strtab':
   [     1]  .text
   [     7]  .comment
   [    10]  .bss
   [    15]  .note.GNU-stack
   [    25]  .rela.eh_frame
   [    34]  func
   [    39]  .strtab
   [    41]  .symtab
   [    49]  .data
   [    4f]  -


Note that I don't use BPF backend. This is a normal x86 compiling.

So seems it is the default behavior of LLVM.

Thank you.


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1279734

FromNamhyung Kim <namhyung@gmail.com>
Date2015-11-30 10:50 +0100
Message-ID<qAtfP-1R8-1@gated-at.bofh.it>
In reply to#1279725
On November 30, 2015 6:27:57 PM GMT+09:00, "Wangnan (F)" <wangnan0@huawei.com> wrote:
>
>
>On 2015/11/30 16:51, Namhyung Kim wrote:
>> On Mon, Nov 30, 2015 at 01:00:46PM +0800, Wangnan (F) wrote:
>>>
>>> On 2015/11/30 0:14, Namhyung Kim wrote:
>>>> Hi Wang,
>>>>
>>>> On Fri, Nov 27, 2015 at 08:47:36AM +0000, Wang Nan wrote:
>>>>> This patch collects name of maps in BPF object files and saves
>them into
>>>>> 'maps' field in 'struct bpf_object'. 'bpf_object__get_map_by_name'
>is
>>>>> introduced to retrive fd and definitions of a map through its
>name.
>>>>>
>>>>> Signed-off-by: Wang Nan <wangnan0@huawei.com>
>>>>> Signed-off-by: He Kuang <hekuang@huawei.com>
>>>>> Cc: Alexei Starovoitov <ast@kernel.org>
>>>>> Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
>>>>> Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
>>>>> Cc: Namhyung Kim <namhyung@kernel.org>
>>>>> Cc: Zefan Li <lizefan@huawei.com>
>>>>> Cc: pi3orama@163.com
>>>>> ---
>>>>>   tools/lib/bpf/libbpf.c | 65
>+++++++++++++++++++++++++++++++++++++++++++++++---
>>>>>   tools/lib/bpf/libbpf.h |  3 +++
>>>>>   2 files changed, 65 insertions(+), 3 deletions(-)
>>>>>
>>>>> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
>>>>> index f509825..a298614 100644
>>>>> --- a/tools/lib/bpf/libbpf.c
>>>>> +++ b/tools/lib/bpf/libbpf.c
>>>>> @@ -165,6 +165,7 @@ struct bpf_program {
>>>>>   struct bpf_map {
>>>>>   	int fd;
>>>>> +	char *name;
>>>>>   	struct bpf_map_def def;
>>>>>   	void *priv;
>>>>>   	bpf_map_clear_priv_t clear_priv;
>>>>> @@ -526,12 +527,46 @@ bpf_object__init_maps(struct bpf_object
>*obj, void *data,
>>>>>   	return 0;
>>>>>   }
>>>>> +static void
>>>>> +bpf_object__init_maps_name(struct bpf_object *obj, int
>maps_shndx)
>>>>> +{
>>>>> +	int i;
>>>>> +	Elf_Data *symbols = obj->efile.symbols;
>>>>> +
>>>>> +	if (!symbols || maps_shndx < 0)
>>>>> +		return;
>>>>> +
>>>>> +	for (i = 0; i < symbols->d_size / sizeof(GElf_Sym); i++) {
>>>>> +		GElf_Sym sym;
>>>>> +		size_t map_idx;
>>>>> +		const char *map_name;
>>>>> +
>>>>> +		if (!gelf_getsym(symbols, i, &sym))
>>>>> +			continue;
>>>>> +		if (sym.st_shndx != maps_shndx)
>>>>> +			continue;
>>>>> +
>>>>> +		map_name = elf_strptr(obj->efile.elf,
>>>>> +				      obj->efile.ehdr.e_shstrndx,
>>>>> +				      sym.st_name);
>>>> It means that each map name is saved in section header string
>table?
>>> According to elf format specification:
>>>
>>> For an symbol table entry, the st_name field "holds an index
>>> into the object file’s symbol string table, which holds the
>>> character representations of the symbol names. If the value
>>> is non-zero, it represents a string table index that gives
>>> the symbol name. Otherwise, the symbol table entry has no
>>> name."
>>>
>>> And so called "object file’s symbol string table" is a
>>> section in the object file which index is stored into
>>> ehdr and be loaded during gelf_getehdr(), and its index
>>> would be set to ehdr->e_shstrndx. So I think for each map
>>> its name should be saved in that string table.
>> AFAIK there're two symbol string tables in a ELF file.  One for
>> section headers (.shstrtab) and another for normal symbols (.strtab).
>> And ehdr->e_shstrndx is the index of section header string table so
>> your code assumes map names are saved in the section header string
>> table, right?
>>
>> Thanks,
>> Namhyung
>
>In case of gcc:
>
>$ echo 'int func() {return 0;}' | gcc -x c -c -o ./temp.o -
>$ readelf -h ./temp.o
>ELF Header:
>   Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
>   Class:                             ELF64
>   Data:                              2's complement, little endian
>   Version:                           1 (current)
>   OS/ABI:                            UNIX - System V
>   ABI Version:                       0
>   Type:                              REL (Relocatable file)
>   Machine:                           Advanced Micro Devices X86-64
>   Version:                           0x1
>   Entry point address:               0x0
>   Start of program headers:          0 (bytes into file)
>   Start of section headers:          240 (bytes into file)
>   Flags:                             0x0
>   Size of this header:               64 (bytes)
>   Size of program headers:           0 (bytes)
>   Number of program headers:         0
>   Size of section headers:           64 (bytes)
>   Number of section headers:         11
>   Section header string table index: 8
>
>Let's see what is section 8:
>
>$ readelf -S ./temp.o
>   ...
>   [ 8] .shstrtab         STRTAB           0000000000000000  00000098
>        0000000000000054  0000000000000000           0     0     1
>   ...
>
>Yes, in this case it is .shstrtab.
>
>However, this is what I found when using llvm:
>
>$ echo 'int func() {return 0;}' | x86_64-oe-linux-clang -x c -c -o 
>./temp.o -
>ELF Header:
>   Magic:   7f 45 4c 46 02 01 01 03 00 00 00 00 00 00 00 00
>   Class:                             ELF64
>   Data:                              2's complement, little endian
>   Version:                           1 (current)
>   OS/ABI:                            UNIX - GNU
>   ABI Version:                       0
>   Type:                              REL (Relocatable file)
>   Machine:                           Advanced Micro Devices X86-64
>   Version:                           0x1
>   Entry point address:               0x0
>   Start of program headers:          0 (bytes into file)
>   Start of section headers:          648 (bytes into file)
>   Flags:                             0x0
>   Size of this header:               64 (bytes)
>   Size of program headers:           0 (bytes)
>   Number of program headers:         0
>   Size of section headers:           64 (bytes)
>   Number of section headers:         10
>   Section header string table index: 1
>
>$ readelf -S ./temp.o
>There are 10 section headers, starting at offset 0x288:
>
>Section Headers:
>   [Nr] Name              Type             Address           Offset
>        Size              EntSize          Flags  Link  Info  Align
>   [ 0]                   NULL             0000000000000000  00000000
>        0000000000000000  0000000000000000           0     0     0
>   [ 1] .strtab           STRTAB           0000000000000000  00000230
>        0000000000000051  0000000000000000           0     0     1
>
>This time it is strtab.
>
>And here is the content of strtab:
>
>$ readelf -p .strtab ./temp.o
>
>String dump of section '.strtab':
>   [     1]  .text
>   [     7]  .comment
>   [    10]  .bss
>   [    15]  .note.GNU-stack
>   [    25]  .rela.eh_frame
>   [    34]  func
>   [    39]  .strtab
>   [    41]  .symtab
>   [    49]  .data
>   [    4f]  -
>
>
>Note that I don't use BPF backend. This is a normal x86 compiling.
>
>So seems it is the default behavior of LLVM.

Ah, didn't know that. So strtab has section header strings as well as normal symbol strings when compiled with LLVM, right?  It'd be great if you add comment about it.

Thanks,
Namhyung

-- 
Sent from my Android device with K-9 Mail. Please excuse my brevity.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1279735 — Re: [PATCH v2 02/13] bpf tools: Extract and collect map names from BPF object file

From"Wangnan (F)" <wangnan0@huawei.com>
Date2015-11-30 10:50 +0100
SubjectRe: [PATCH v2 02/13] bpf tools: Extract and collect map names from BPF object file
Message-ID<qAtfP-1R8-3@gated-at.bofh.it>
In reply to#1279734

On 2015/11/30 17:43, Namhyung Kim wrote:
> On November 30, 2015 6:27:57 PM GMT+09:00, "Wangnan (F)" <wangnan0@huawei.com> wrote:
>>
>> On 2015/11/30 16:51, Namhyung Kim wrote:
>>> On Mon, Nov 30, 2015 at 01:00:46PM +0800, Wangnan (F) wrote:
>>>> On 2015/11/30 0:14, Namhyung Kim wrote:
>>>>> Hi Wang,
>>>>>
>>>>> On Fri, Nov 27, 2015 at 08:47:36AM +0000, Wang Nan wrote:
>>>>>> This patch collects name of maps in BPF object files and saves
>> them into
>>>>>> 'maps' field in 'struct bpf_object'. 'bpf_object__get_map_by_name'
>> is
>>>>>> introduced to retrive fd and definitions of a map through its
>> name.
>>>>>> Signed-off-by: Wang Nan <wangnan0@huawei.com>
>>>>>> Signed-off-by: He Kuang <hekuang@huawei.com>
>>>>>> Cc: Alexei Starovoitov <ast@kernel.org>
>>>>>> Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
>>>>>> Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
>>>>>> Cc: Namhyung Kim <namhyung@kernel.org>
>>>>>> Cc: Zefan Li <lizefan@huawei.com>
>>>>>> Cc: pi3orama@163.com
>>>>>> ---
>>>>>>    tools/lib/bpf/libbpf.c | 65
>> +++++++++++++++++++++++++++++++++++++++++++++++---
>>>>>>    tools/lib/bpf/libbpf.h |  3 +++
>>>>>>    2 files changed, 65 insertions(+), 3 deletions(-)
>>>>>>
>>>>>> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
>>>>>> index f509825..a298614 100644
>>>>>> --- a/tools/lib/bpf/libbpf.c
>>>>>> +++ b/tools/lib/bpf/libbpf.c
>>>>>> @@ -165,6 +165,7 @@ struct bpf_program {
>>>>>>    struct bpf_map {
>>>>>>    	int fd;
>>>>>> +	char *name;
>>>>>>    	struct bpf_map_def def;
>>>>>>    	void *priv;
>>>>>>    	bpf_map_clear_priv_t clear_priv;
>>>>>> @@ -526,12 +527,46 @@ bpf_object__init_maps(struct bpf_object
>> *obj, void *data,
>>>>>>    	return 0;
>>>>>>    }
>>>>>> +static void
>>>>>> +bpf_object__init_maps_name(struct bpf_object *obj, int
>> maps_shndx)
>>>>>> +{
>>>>>> +	int i;
>>>>>> +	Elf_Data *symbols = obj->efile.symbols;
>>>>>> +
>>>>>> +	if (!symbols || maps_shndx < 0)
>>>>>> +		return;
>>>>>> +
>>>>>> +	for (i = 0; i < symbols->d_size / sizeof(GElf_Sym); i++) {
>>>>>> +		GElf_Sym sym;
>>>>>> +		size_t map_idx;
>>>>>> +		const char *map_name;
>>>>>> +
>>>>>> +		if (!gelf_getsym(symbols, i, &sym))
>>>>>> +			continue;
>>>>>> +		if (sym.st_shndx != maps_shndx)
>>>>>> +			continue;
>>>>>> +
>>>>>> +		map_name = elf_strptr(obj->efile.elf,
>>>>>> +				      obj->efile.ehdr.e_shstrndx,
>>>>>> +				      sym.st_name);
>>>>> It means that each map name is saved in section header string
>> table?
>>>> According to elf format specification:
>>>>
>>>> For an symbol table entry, the st_name field "holds an index
>>>> into the object file’s symbol string table, which holds the
>>>> character representations of the symbol names. If the value
>>>> is non-zero, it represents a string table index that gives
>>>> the symbol name. Otherwise, the symbol table entry has no
>>>> name."
>>>>
>>>> And so called "object file’s symbol string table" is a
>>>> section in the object file which index is stored into
>>>> ehdr and be loaded during gelf_getehdr(), and its index
>>>> would be set to ehdr->e_shstrndx. So I think for each map
>>>> its name should be saved in that string table.
>>> AFAIK there're two symbol string tables in a ELF file.  One for
>>> section headers (.shstrtab) and another for normal symbols (.strtab).
>>> And ehdr->e_shstrndx is the index of section header string table so
>>> your code assumes map names are saved in the section header string
>>> table, right?
>>>
>>> Thanks,
>>> Namhyung
>> In case of gcc:
>>
>> $ echo 'int func() {return 0;}' | gcc -x c -c -o ./temp.o -
>> $ readelf -h ./temp.o
>> ELF Header:
>>    Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
>>    Class:                             ELF64
>>    Data:                              2's complement, little endian
>>    Version:                           1 (current)
>>    OS/ABI:                            UNIX - System V
>>    ABI Version:                       0
>>    Type:                              REL (Relocatable file)
>>    Machine:                           Advanced Micro Devices X86-64
>>    Version:                           0x1
>>    Entry point address:               0x0
>>    Start of program headers:          0 (bytes into file)
>>    Start of section headers:          240 (bytes into file)
>>    Flags:                             0x0
>>    Size of this header:               64 (bytes)
>>    Size of program headers:           0 (bytes)
>>    Number of program headers:         0
>>    Size of section headers:           64 (bytes)
>>    Number of section headers:         11
>>    Section header string table index: 8
>>
>> Let's see what is section 8:
>>
>> $ readelf -S ./temp.o
>>    ...
>>    [ 8] .shstrtab         STRTAB           0000000000000000  00000098
>>         0000000000000054  0000000000000000           0     0     1
>>    ...
>>
>> Yes, in this case it is .shstrtab.
>>
>> However, this is what I found when using llvm:
>>
>> $ echo 'int func() {return 0;}' | x86_64-oe-linux-clang -x c -c -o
>> ./temp.o -
>> ELF Header:
>>    Magic:   7f 45 4c 46 02 01 01 03 00 00 00 00 00 00 00 00
>>    Class:                             ELF64
>>    Data:                              2's complement, little endian
>>    Version:                           1 (current)
>>    OS/ABI:                            UNIX - GNU
>>    ABI Version:                       0
>>    Type:                              REL (Relocatable file)
>>    Machine:                           Advanced Micro Devices X86-64
>>    Version:                           0x1
>>    Entry point address:               0x0
>>    Start of program headers:          0 (bytes into file)
>>    Start of section headers:          648 (bytes into file)
>>    Flags:                             0x0
>>    Size of this header:               64 (bytes)
>>    Size of program headers:           0 (bytes)
>>    Number of program headers:         0
>>    Size of section headers:           64 (bytes)
>>    Number of section headers:         10
>>    Section header string table index: 1
>>
>> $ readelf -S ./temp.o
>> There are 10 section headers, starting at offset 0x288:
>>
>> Section Headers:
>>    [Nr] Name              Type             Address           Offset
>>         Size              EntSize          Flags  Link  Info  Align
>>    [ 0]                   NULL             0000000000000000  00000000
>>         0000000000000000  0000000000000000           0     0     0
>>    [ 1] .strtab           STRTAB           0000000000000000  00000230
>>         0000000000000051  0000000000000000           0     0     1
>>
>> This time it is strtab.
>>
>> And here is the content of strtab:
>>
>> $ readelf -p .strtab ./temp.o
>>
>> String dump of section '.strtab':
>>    [     1]  .text
>>    [     7]  .comment
>>    [    10]  .bss
>>    [    15]  .note.GNU-stack
>>    [    25]  .rela.eh_frame
>>    [    34]  func
>>    [    39]  .strtab
>>    [    41]  .symtab
>>    [    49]  .data
>>    [    4f]  -
>>
>>
>> Note that I don't use BPF backend. This is a normal x86 compiling.
>>
>> So seems it is the default behavior of LLVM.
> Ah, didn't know that. So strtab has section header strings as well as normal symbol strings when compiled with LLVM, right?  It'd be great if you add comment about it.

I think technically speaking you are right, because I haven't see any 
documentation
about it, so I don't know the reason why LLVM behave like this, and 
don't know
whether it would change it in future. And it is also possible that we 
will have
other compiler to compile BPF source file. Now I'm reading readelf's 
code and try to
find a canonical way for it.

Thank you for your review.

> Thanks,
> Namhyung
>


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1279758 — [PATCH] tools lib bpf: Fetch map names from correct strtab

FromWang Nan <wangnan0@huawei.com>
Date2015-11-30 11:40 +0100
Subject[PATCH] tools lib bpf: Fetch map names from correct strtab
Message-ID<qAu2e-2mA-7@gated-at.bofh.it>
In reply to#1279734
Namhyung Kim pointed out a potential problem in original code that it
fetches names of maps from section header string table, which is used
to store section names.

Original code doesn't cause error because of a LLVM behavior that, it
combines shstrtab into strtab. For example:

 $ echo 'int func() {return 0;}' | x86_64-oe-linux-clang -x c -o temp.o -c -
 $ readelf -h ./temp.o
 ELF Header:
   Magic:   7f 45 4c 46 02 01 01 03 00 00 00 00 00 00 00 00
   ...
   Section header string table index: 1
 $ readelf -S ./temp.o
 There are 10 section headers, starting at offset 0x288:

 Section Headers:
   [Nr] Name              Type             Address           Offset
        Size              EntSize          Flags  Link  Info  Align
   [ 0]                   NULL             0000000000000000  00000000
        0000000000000000  0000000000000000           0     0     0
   [ 1] .strtab           STRTAB           0000000000000000  00000230
        0000000000000051  0000000000000000           0     0     1
        ...
 $ readelf -p .strtab ./temp.o

 String dump of section '.strtab':
   [     1]  .text
   [     7]  .comment
   [    10]  .bss
   [    15]  .note.GNU-stack
   [    25]  .rela.eh_frame
   [    34]  func
   [    39]  .strtab
   [    41]  .symtab
   [    49]  .data
   [    4f]  -

 $ readelf -p .shstrtab ./temp.o
 readelf: Warning: Section '.shstrtab' was not dumped because it does not exist!

Where, 'section header string table index' points to '.strtab', and
symbol names are also stored there.

However, in case of gcc:

 $ echo 'int func() {return 0;}' | gcc -x c -o temp.o -c -
 $ readelf -p .shstrtab ./temp.o

 String dump of section '.shstrtab':
   [     1]  .symtab
   [     9]  .strtab
   [    11]  .shstrtab
   [    1b]  .text
   [    21]  .data
   [    27]  .bss
   [    2c]  .comment
   [    35]  .note.GNU-stack
   [    45]  .rela.eh_frame
 $ readelf -p .strtab ./temp.o

 String dump of section '.strtab':
   [     1]  func

They are separated sections.

Although original code doesn't cause error, we'd better use canonical
method for fetching symbol names to avoid potential behavior changing.
This patch learns from readelf's code, fetches string from sh_link
of .symbol section.

Reported-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/lib/bpf/libbpf.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 16485ab..8334a5a 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -195,6 +195,7 @@ struct bpf_object {
 		Elf *elf;
 		GElf_Ehdr ehdr;
 		Elf_Data *symbols;
+		size_t strtabidx;
 		struct {
 			GElf_Shdr shdr;
 			Elf_Data *data;
@@ -547,7 +548,7 @@ bpf_object__init_maps_name(struct bpf_object *obj, int maps_shndx)
 			continue;
 
 		map_name = elf_strptr(obj->efile.elf,
-				      obj->efile.ehdr.e_shstrndx,
+				      obj->efile.strtabidx,
 				      sym.st_name);
 		map_idx = sym.st_value / sizeof(struct bpf_map_def);
 		if (map_idx >= obj->nr_maps) {
@@ -630,8 +631,10 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
 				pr_warning("bpf: multiple SYMTAB in %s\n",
 					   obj->path);
 				err = -LIBBPF_ERRNO__FORMAT;
-			} else
+			} else {
 				obj->efile.symbols = data;
+				obj->efile.strtabidx = sh.sh_link;
+			}
 		} else if ((sh.sh_type == SHT_PROGBITS) &&
 			   (sh.sh_flags & SHF_EXECINSTR) &&
 			   (data->d_size > 0)) {
@@ -667,6 +670,10 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
 			goto out;
 	}
 
+	if (!obj->efile.strtabidx || obj->efile.strtabidx >= idx) {
+		pr_warning("Corrupted ELF file: index of strtab invalid\n");
+		return LIBBPF_ERRNO__FORMAT;
+	}
 	if (maps_shndx >= 0)
 		err = bpf_object__init_maps_name(obj, maps_shndx);
 out:
-- 
1.8.3.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1279780 — Re: [PATCH] tools lib bpf: Fetch map names from correct strtab

FromNamhyung Kim <namhyung@kernel.org>
Date2015-11-30 12:30 +0100
SubjectRe: [PATCH] tools lib bpf: Fetch map names from correct strtab
Message-ID<qAuOB-2S8-13@gated-at.bofh.it>
In reply to#1279758
On Mon, Nov 30, 2015 at 10:39:10AM +0000, Wang Nan wrote:
> Namhyung Kim pointed out a potential problem in original code that it
> fetches names of maps from section header string table, which is used
> to store section names.
> 
> Original code doesn't cause error because of a LLVM behavior that, it
> combines shstrtab into strtab. For example:
> 
>  $ echo 'int func() {return 0;}' | x86_64-oe-linux-clang -x c -o temp.o -c -
>  $ readelf -h ./temp.o
>  ELF Header:
>    Magic:   7f 45 4c 46 02 01 01 03 00 00 00 00 00 00 00 00
>    ...
>    Section header string table index: 1
>  $ readelf -S ./temp.o
>  There are 10 section headers, starting at offset 0x288:
> 
>  Section Headers:
>    [Nr] Name              Type             Address           Offset
>         Size              EntSize          Flags  Link  Info  Align
>    [ 0]                   NULL             0000000000000000  00000000
>         0000000000000000  0000000000000000           0     0     0
>    [ 1] .strtab           STRTAB           0000000000000000  00000230
>         0000000000000051  0000000000000000           0     0     1
>         ...
>  $ readelf -p .strtab ./temp.o
> 
>  String dump of section '.strtab':
>    [     1]  .text
>    [     7]  .comment
>    [    10]  .bss
>    [    15]  .note.GNU-stack
>    [    25]  .rela.eh_frame
>    [    34]  func
>    [    39]  .strtab
>    [    41]  .symtab
>    [    49]  .data
>    [    4f]  -
> 
>  $ readelf -p .shstrtab ./temp.o
>  readelf: Warning: Section '.shstrtab' was not dumped because it does not exist!
> 
> Where, 'section header string table index' points to '.strtab', and
> symbol names are also stored there.
> 
> However, in case of gcc:
> 
>  $ echo 'int func() {return 0;}' | gcc -x c -o temp.o -c -
>  $ readelf -p .shstrtab ./temp.o
> 
>  String dump of section '.shstrtab':
>    [     1]  .symtab
>    [     9]  .strtab
>    [    11]  .shstrtab
>    [    1b]  .text
>    [    21]  .data
>    [    27]  .bss
>    [    2c]  .comment
>    [    35]  .note.GNU-stack
>    [    45]  .rela.eh_frame
>  $ readelf -p .strtab ./temp.o
> 
>  String dump of section '.strtab':
>    [     1]  func
> 
> They are separated sections.
> 
> Although original code doesn't cause error, we'd better use canonical
> method for fetching symbol names to avoid potential behavior changing.
> This patch learns from readelf's code, fetches string from sh_link
> of .symbol section.
> 
> Reported-by: Namhyung Kim <namhyung@kernel.org>
> Signed-off-by: Wang Nan <wangnan0@huawei.com>
> Cc: Arnaldo Carvalho de Melo <acme@redhat.com>

Acked-by: Namhyung Kim <namhyung@kernel.org>

Thanks,
Namhyung


> ---
>  tools/lib/bpf/libbpf.c | 11 +++++++++--
>  1 file changed, 9 insertions(+), 2 deletions(-)
> 
> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> index 16485ab..8334a5a 100644
> --- a/tools/lib/bpf/libbpf.c
> +++ b/tools/lib/bpf/libbpf.c
> @@ -195,6 +195,7 @@ struct bpf_object {
>  		Elf *elf;
>  		GElf_Ehdr ehdr;
>  		Elf_Data *symbols;
> +		size_t strtabidx;
>  		struct {
>  			GElf_Shdr shdr;
>  			Elf_Data *data;
> @@ -547,7 +548,7 @@ bpf_object__init_maps_name(struct bpf_object *obj, int maps_shndx)
>  			continue;
>  
>  		map_name = elf_strptr(obj->efile.elf,
> -				      obj->efile.ehdr.e_shstrndx,
> +				      obj->efile.strtabidx,
>  				      sym.st_name);
>  		map_idx = sym.st_value / sizeof(struct bpf_map_def);
>  		if (map_idx >= obj->nr_maps) {
> @@ -630,8 +631,10 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
>  				pr_warning("bpf: multiple SYMTAB in %s\n",
>  					   obj->path);
>  				err = -LIBBPF_ERRNO__FORMAT;
> -			} else
> +			} else {
>  				obj->efile.symbols = data;
> +				obj->efile.strtabidx = sh.sh_link;
> +			}
>  		} else if ((sh.sh_type == SHT_PROGBITS) &&
>  			   (sh.sh_flags & SHF_EXECINSTR) &&
>  			   (data->d_size > 0)) {
> @@ -667,6 +670,10 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
>  			goto out;
>  	}
>  
> +	if (!obj->efile.strtabidx || obj->efile.strtabidx >= idx) {
> +		pr_warning("Corrupted ELF file: index of strtab invalid\n");
> +		return LIBBPF_ERRNO__FORMAT;
> +	}
>  	if (maps_shndx >= 0)
>  		err = bpf_object__init_maps_name(obj, maps_shndx);
>  out:
> -- 
> 1.8.3.4
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web