BPF List
 help / color / mirror / Atom feed
From: Jiri Olsa <jolsa@redhat.com>
To: Andrii Nakryiko <andrii.nakryiko@gmail.com>
Cc: Veronika Kabatova <vkabatov@redhat.com>,
	Andrii Nakryiko <andriin@fb.com>,
	Alexei Starovoitov <ast@kernel.org>,
	Arnaldo Carvalho de Melo <acme@redhat.com>,
	bpf <bpf@vger.kernel.org>, "Frank Ch. Eigler" <fche@redhat.com>,
	Mark Wielaard <mjw@redhat.com>
Subject: Re: Build failures: unresolved symbol vfs_getattr
Date: Fri, 23 Oct 2020 22:17:02 +0200	[thread overview]
Message-ID: <20201023201702.GA2495983@krava> (raw)
In-Reply-To: <CAEf4BzbM=FhKUUjaM9msL1k=t_CSrhoWUNYcubzToZvbAJCJ-A@mail.gmail.com>

On Fri, Oct 23, 2020 at 11:22:05AM -0700, Andrii Nakryiko wrote:
> On Thu, Oct 22, 2020 at 11:58 PM Jiri Olsa <jolsa@redhat.com> wrote:
> >
> > On Fri, Oct 23, 2020 at 07:36:57AM +0200, Jiri Olsa wrote:
> > > On Thu, Oct 22, 2020 at 01:00:19PM -0700, Andrii Nakryiko wrote:
> > >
> > > SNIP
> > >
> > > > >
> > > > > hi,
> > > > > FYI there's still no solution yet, so far the progress is:
> > > > >
> > > > > the proposed workaround was to use the negation -> we don't have
> > > > > DW_AT_declaration tag, so let's find out instead which DW_TAG_subprogram
> > > > > tags have attached code and skip them if they don't have any:
> > > > >   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97060#c10
> > > > >
> > > > > the attached patch is doing that, but the resulting BTF is missing
> > > > > several functions due to another bug in dwarf:
> > > > >   https://bugzilla.redhat.com/show_bug.cgi?id=1890107
> > > >
> > > > It seems fine if there are only few functions (especially if those are
> > > > unlikely to be traced). Do you have an estimate of how many functions
> > > > have this second DWARF bug?
> > >
> > > it wasn't that many, I'll recheck
> >
> > 127 functions missing if the workaround is applied, list attached
> >
> 
> some of those seem pretty useful... I guess the quick workaround in
> pahole would be to just remember function names that were emitted
> already. The problem with that is that we can pick a version without
> parameter names, which is not the end of the world, but certainly
> annoying.

right, we can generate them in bpftrace, but it's a shame


> 
> But otherwise, I don't really have a good feeling what's the perfect
> solution here...

I tried the check of dwarf record against function symbols
with adresses mentioned earlier (attached)

getting more functions of course ;-)

$ bpftool btf dump file ./vmlinux | grep 'FUNC '  | wc -l
46606

compared to 22869 on the same .config with working gcc
and current pahole

and resolve_btfids is happy, because there are no duplications

jirka


---
diff --git a/btf_encoder.c b/btf_encoder.c
index 2a6455be4c52..468781204cd9 100644
--- a/btf_encoder.c
+++ b/btf_encoder.c
@@ -326,6 +326,18 @@ static int find_all_percpu_vars(struct btf_elf *btfe)
 	return 0;
 }
 
+static bool btfe__generate_func(const struct btf_elf *btfe, const char *name)
+{
+	struct symbol *sym;
+
+	sym = btfe__find_symbol(btfe, name);
+	if (!sym || sym->generated || !sym->addr)
+		return false;
+
+	sym->generated = true;
+	return true;
+}
+
 int cu__encode_btf(struct cu *cu, int verbose, bool force,
 		   bool skip_encoding_vars)
 {
@@ -354,6 +366,9 @@ int cu__encode_btf(struct cu *cu, int verbose, bool force,
 		if (!skip_encoding_vars && find_all_percpu_vars(btfe))
 			goto out;
 
+		if (btfe__load_symbols(btfe, cu))
+			goto out;
+
 		has_index_type = false;
 		need_index_type = false;
 		array_index_id = 0;
@@ -401,7 +416,7 @@ int cu__encode_btf(struct cu *cu, int verbose, bool force,
 		int btf_fnproto_id, btf_fn_id;
 		const char *name;
 
-		if (fn->declaration || !fn->external)
+		if (!btfe__generate_func(btfe, function__name(fn, cu)))
 			continue;
 
 		btf_fnproto_id = btf_elf__add_func_proto(btfe, cu, &fn->proto, type_id_off);
diff --git a/elf_symtab.h b/elf_symtab.h
index 359add69c8ab..094ec4683d01 100644
--- a/elf_symtab.h
+++ b/elf_symtab.h
@@ -63,6 +63,14 @@ static inline uint64_t elf_sym__value(const GElf_Sym *sym)
 	return sym->st_value;
 }
 
+static inline int elf_sym__is_function(const GElf_Sym *sym)
+{
+	return (elf_sym__type(sym) == STT_FUNC ||
+		elf_sym__type(sym) == STT_GNU_IFUNC) &&
+		sym->st_name != 0 &&
+		sym->st_shndx != SHN_UNDEF;
+}
+
 static inline bool elf_sym__is_local_function(const GElf_Sym *sym)
 {
 	return elf_sym__type(sym) == STT_FUNC &&
diff --git a/libbtf.c b/libbtf.c
index babf4fe8cd9e..6c4b8a069b85 100644
--- a/libbtf.c
+++ b/libbtf.c
@@ -30,6 +30,91 @@
 uint8_t btf_elf__verbose;
 uint8_t btf_elf__force;
 
+static int btfe__insert_symbol(struct btf_elf *btfe, const char *name,
+			     uint64_t addr)
+{
+	struct rb_node **p = &btfe->symbols.rb_node;
+	struct rb_node *parent = NULL;
+	struct symbol *sym;
+	int err;
+
+	while (*p != NULL) {
+		parent = *p;
+		sym = rb_entry(parent, struct symbol, rb_node);
+
+
+		err = strcmp(sym->name, name);
+		if (err < 0)
+			p = &(*p)->rb_left;
+		else if (err > 0)
+			p = &(*p)->rb_right;
+		else
+			return 0;
+	}
+
+	sym = malloc(sizeof(*sym));
+	if (!sym)
+		return -1;
+	sym->name = name;
+	sym->addr = addr;
+	sym->generated = false;
+
+	rb_link_node(&sym->rb_node, parent, p);
+	rb_insert_color(&sym->rb_node, &btfe->symbols);
+	return 0;
+}
+
+struct symbol *btfe__find_symbol(const struct btf_elf *btfe, const char *name)
+{
+	struct symbol *sym;
+	struct rb_node *n;
+	int err;
+
+	n = btfe->symbols.rb_node;
+
+	while (n) {
+		sym = rb_entry(n, struct symbol, rb_node);
+		err = strcmp(sym->name, name);
+		if (err < 0)
+			n = n->rb_left;
+		else if (err > 0)
+			n = n->rb_right;
+		else
+			return sym;
+	}
+
+	return NULL;
+}
+
+int btfe__load_symbols(struct btf_elf *btfe, struct cu *cu)
+{
+	const char *name;
+	GElf_Sym sym;
+	uint32_t id;
+
+	cu__cache_symtab(cu);
+
+	cu__for_each_cached_symtab_entry(cu, id, sym, name) {
+		if (!elf_sym__is_function(&sym))
+			continue;
+		if (btfe__insert_symbol(btfe, name, elf_sym__value(&sym)))
+			return -1;
+	}
+	return 0;
+}
+
+static void btfe__delete_symbols(struct btf_elf *btfe)
+{
+	struct rb_node *n = rb_first(&btfe->symbols);
+	struct symbol *sym;
+
+	while (n) {
+		sym = rb_entry(n, struct symbol, rb_node);
+		n = rb_next(&sym->rb_node);
+		free(sym);
+	}
+}
+
 static int btf_var_secinfo_cmp(const void *a, const void *b)
 {
 	const struct btf_var_secinfo *av = a;
@@ -72,6 +157,7 @@ struct btf_elf *btf_elf__new(const char *filename, Elf *elf)
 	if (!btfe)
 		return NULL;
 
+	btfe->symbols = RB_ROOT;
 	btfe->in_fd = -1;
 	btfe->filename = strdup(filename);
 	if (btfe->filename == NULL)
@@ -177,6 +263,7 @@ void btf_elf__delete(struct btf_elf *btfe)
 			elf_end(btfe->elf);
 	}
 
+	btfe__delete_symbols(btfe);
 	elf_symtab__delete(btfe->symtab);
 	__gobuffer__delete(&btfe->percpu_secinfo);
 	btf__free(btfe->btf);
diff --git a/libbtf.h b/libbtf.h
index 887b5bc55c8e..f4a58834c390 100644
--- a/libbtf.h
+++ b/libbtf.h
@@ -12,6 +12,14 @@
 #include <stdbool.h>
 #include <stdint.h>
 #include "lib/bpf/src/btf.h"
+#include "rbtree.h"
+
+struct symbol {
+	const char	*name;
+	uint64_t	 addr;
+	bool		 generated;
+	struct rb_node	 rb_node;
+};
 
 struct btf_elf {
 	void		  *priv;
@@ -27,6 +35,7 @@ struct btf_elf {
 	uint32_t	  percpu_shndx;
 	uint64_t	  percpu_base_addr;
 	struct btf	  *btf;
+	struct rb_root	  symbols;
 };
 
 extern uint8_t btf_elf__verbose;
@@ -66,4 +75,7 @@ int  btf_elf__encode(struct btf_elf *btf, uint8_t flags);
 const char *btf_elf__string(struct btf_elf *btf, uint32_t ref);
 int btf_elf__load(struct btf_elf *btf);
 
+struct symbol *btfe__find_symbol(const struct btf_elf *btfe, const char *name);
+int btfe__load_symbols(struct btf_elf *btfe, struct cu *cu);
+
 #endif /* _LIBBTF_H */


  reply	other threads:[~2020-10-23 20:17 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <1723352278.11013122.1600093319730.JavaMail.zimbra@redhat.com>
2020-09-14 14:48 ` Build failures: unresolved symbol vfs_getattr Veronika Kabatova
2020-09-14 18:25   ` Jiri Olsa
2020-09-14 22:26     ` Andrii Nakryiko
2020-09-15  7:30       ` Jiri Olsa
2020-09-15 12:17         ` Jiri Olsa
2020-09-16  9:06           ` Jiri Olsa
2020-10-16 21:38             ` Jiri Olsa
2020-10-21 19:42               ` Jiri Olsa
2020-10-22 20:00                 ` Andrii Nakryiko
2020-10-23  5:36                   ` Jiri Olsa
2020-10-23  6:58                     ` Jiri Olsa
2020-10-23 18:22                       ` Andrii Nakryiko
2020-10-23 20:17                         ` Jiri Olsa [this message]
2020-10-23 20:32                           ` Andrii Nakryiko
2020-10-23 20:45                             ` Jiri Olsa
2020-10-23 22:02                               ` Andrii Nakryiko
2020-10-26 10:14                         ` Jiri Olsa
2020-10-26 22:06                           ` Andrii Nakryiko

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20201023201702.GA2495983@krava \
    --to=jolsa@redhat.com \
    --cc=acme@redhat.com \
    --cc=andrii.nakryiko@gmail.com \
    --cc=andriin@fb.com \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=fche@redhat.com \
    --cc=mjw@redhat.com \
    --cc=vkabatov@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox