From: Jiri Olsa <jolsa@kernel.org>
To: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: dwarves@vger.kernel.org, bpf@vger.kernel.org,
Alexei Starovoitov <ast@kernel.org>,
Andrii Nakryiko <andriin@fb.com>, Yonghong Song <yhs@fb.com>,
Hao Luo <haoluo@google.com>, "Frank Ch. Eigler" <fche@redhat.com>,
Mark Wielaard <mjw@redhat.com>
Subject: [PATCH 2/3] btf_encoder: Change functions check due to broken dwarf
Date: Mon, 26 Oct 2020 23:36:16 +0100 [thread overview]
Message-ID: <20201026223617.2868431-3-jolsa@kernel.org> (raw)
In-Reply-To: <20201026223617.2868431-1-jolsa@kernel.org>
We need to generate just single BTF instance for the
function, while DWARF data contains multiple instances
of DW_TAG_subprogram tag.
Unfortunately we can no longer rely on DW_AT_declaration
tag (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97060)
Instead we apply following checks:
- argument names are defined for the function
- there's symbol and address defined for the function
- function is generated only once
They might be slightly superfluous together, but it's
better to be ready for another DWARF mishap.
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
btf_encoder.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++++-
elf_symtab.h | 8 ++++
2 files changed, 109 insertions(+), 1 deletion(-)
diff --git a/btf_encoder.c b/btf_encoder.c
index 2dd26c904039..99b9abe36993 100644
--- a/btf_encoder.c
+++ b/btf_encoder.c
@@ -26,6 +26,62 @@
*/
#define KSYM_NAME_LEN 128
+struct elf_function {
+ const char *name;
+ bool generated;
+};
+
+static struct elf_function *functions;
+static int functions_alloc;
+static int functions_cnt;
+
+static int functions_cmp(const void *_a, const void *_b)
+{
+ const struct elf_function *a = _a;
+ const struct elf_function *b = _b;
+
+ return strcmp(a->name, b->name);
+}
+
+static void delete_functions(void)
+{
+ free(functions);
+ functions_alloc = functions_cnt = 0;
+}
+
+static int config_function(struct btf_elf *btfe, GElf_Sym *sym)
+{
+ if (!elf_sym__is_function(sym))
+ return 0;
+ if (!elf_sym__value(sym))
+ return 0;
+
+ if (functions_cnt == functions_alloc) {
+ functions_alloc += 5000;
+ functions = realloc(functions, functions_alloc * sizeof(*functions));
+ if (!functions)
+ return -1;
+ }
+
+ functions[functions_cnt].name = elf_sym__name(sym, btfe->symtab);
+ functions_cnt++;
+ return 0;
+}
+
+static bool should_generate_func(const struct btf_elf *btfe, const char *name)
+{
+ struct elf_function *p;
+ struct elf_function key = { .name = name };
+
+ p = bsearch(&key, functions, functions_cnt,
+ sizeof(functions[0]), functions_cmp);
+ if (!p || p->generated)
+ return false;
+
+ p->generated = true;
+ return true;
+}
+
static bool btf_name_char_ok(char c, bool first)
{
if (c == '_' || c == '.')
@@ -207,6 +263,7 @@ int btf_encoder__encode()
btf_elf__add_datasec_type(btfe, PERCPU_SECTION, &btfe->percpu_secinfo);
err = btf_elf__encode(btfe, 0);
+ delete_functions();
btf_elf__delete(btfe);
btfe = NULL;
@@ -314,11 +371,16 @@ static int config(struct btf_elf *btfe, bool do_percpu_vars)
/* cache variables' addresses, preparing for searching in symtab. */
percpu_var_cnt = 0;
+ /* functions addresses */
+ functions_cnt = 0;
+ functions_alloc = 0;
/* search within symtab for percpu variables */
elf_symtab__for_each_symbol(btfe->symtab, core_id, sym) {
if (do_percpu_vars && config_percpu_var(btfe, &sym))
return -1;
+ if (config_function(btfe, &sym))
+ return -1;
}
if (do_percpu_vars) {
@@ -329,9 +391,25 @@ static int config(struct btf_elf *btfe, bool do_percpu_vars)
printf("Found %d per-CPU variables!\n", percpu_var_cnt);
}
+ if (functions_cnt)
+ qsort(functions, functions_cnt, sizeof(functions[0]), functions_cmp);
+
return 0;
}
+static bool has_arg_names(struct cu *cu, struct ftype *ftype)
+{
+ struct parameter *param;
+ const char *name;
+
+ ftype__for_each_parameter(ftype, param) {
+ name = dwarves__active_loader->strings__ptr(cu, param->name);
+ if (name == NULL)
+ return false;
+ }
+ return true;
+}
+
int cu__encode_btf(struct cu *cu, int verbose, bool force,
bool skip_encoding_vars)
{
@@ -407,7 +485,28 @@ 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 (!fn->external)
+ continue;
+
+ /*
+ * We need to generate just single BTF instance for the
+ * function, while DWARF data contains multiple instances
+ * of DW_TAG_subprogram tag.
+ *
+ * We can no longer rely on DW_AT_declaration tag.
+ * (see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97060)
+ *
+ * We check following conditions in following calls:
+ * - argument names are defined
+ * - there's symbol and address defined for the function
+ * - function is generated only once
+ *
+ * They might be slightly superfluous together, but it's
+ * better to be ready for another DWARF mishap.
+ */
+ if (!has_arg_names(cu, &fn->proto))
+ continue;
+ if (!should_generate_func(btfe, function__name(fn, cu)))
continue;
btf_fnproto_id = btf_elf__add_func_proto(btfe, cu, &fn->proto, type_id_off);
@@ -491,6 +590,7 @@ int cu__encode_btf(struct cu *cu, int verbose, bool force,
out:
if (err) {
+ delete_functions();
btf_elf__delete(btfe);
btfe = NULL;
}
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 &&
--
2.26.2
next prev parent reply other threads:[~2020-10-26 22:36 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-10-26 22:36 [RFC 0/3] pahole: Workaround dwarf bug for function encoding Jiri Olsa
2020-10-26 22:36 ` [PATCH 1/3] btf_encoder: Move find_all_percpu_vars in generic config function Jiri Olsa
2020-10-27 23:12 ` Andrii Nakryiko
2020-10-27 23:54 ` Hao Luo
2020-10-28 15:51 ` Jiri Olsa
2020-10-26 22:36 ` Jiri Olsa [this message]
2020-10-27 23:20 ` [PATCH 2/3] btf_encoder: Change functions check due to broken dwarf Andrii Nakryiko
2020-10-28 15:50 ` Jiri Olsa
2020-10-26 22:36 ` [PATCH 3/3] btf_encoder: Include static functions to BTF data Jiri Olsa
2020-10-27 23:21 ` Andrii Nakryiko
2020-10-28 15:53 ` Jiri Olsa
2020-10-27 23:13 ` [RFC 0/3] pahole: Workaround dwarf bug for function encoding Andrii Nakryiko
2020-10-28 15:49 ` Jiri Olsa
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=20201026223617.2868431-3-jolsa@kernel.org \
--to=jolsa@kernel.org \
--cc=acme@kernel.org \
--cc=andriin@fb.com \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=dwarves@vger.kernel.org \
--cc=fche@redhat.com \
--cc=haoluo@google.com \
--cc=mjw@redhat.com \
--cc=yhs@fb.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