From: Ihor Solodrai <ihor.solodrai@pm.me>
To: dwarves@vger.kernel.org
Cc: bpf@vger.kernel.org, acme@kernel.org, alan.maguire@oracle.com,
eddyz87@gmail.com, andrii@kernel.org, mykolal@fb.com,
olsajiri@gmail.com
Subject: [PATCH dwarves v4 05/10] btf_encoder: introduce elf_functions_list
Date: Tue, 07 Jan 2025 19:09:27 +0000 [thread overview]
Message-ID: <20250107190855.2312210-6-ihor.solodrai@pm.me> (raw)
In-Reply-To: <20250107190855.2312210-1-ihor.solodrai@pm.me>
In case of processing of multiple DWARF modules, multiple ELFs are
read. This requires maintaining and elf_functions table per ELF.
Replace btf_encoder.functions with btf_encoder.elf_functions_list,
that contains all necessary elf_functions tables.
The list is initialized when btf_encoder is created. When a new CU is
assigned to the encoder in btf_encoder__encode_cu, an elf_functions
table will be created if the CU is coming from an unknown Elf.
This patch is a variant of [1], following a discussion at [2].
[1] https://lore.kernel.org/bpf/20241213223641.564002-7-ihor.solodrai@pm.me/
[2] https://lore.kernel.org/bpf/C82bYTvJaV4bfT15o25EsBiUvFsj5eTlm17933Hvva76CXjIcu3gvpaOCWPgeZ8g3cZ-RMa8Vp0y1o_QMR2LhPB-LEUYfZCGuCfR_HvkIP8=@pm.me/
Signed-off-by: Ihor Solodrai <ihor.solodrai@pm.me>
---
btf_encoder.c | 138 +++++++++++++++++++++++++++++++++++++++++---------
1 file changed, 115 insertions(+), 23 deletions(-)
diff --git a/btf_encoder.c b/btf_encoder.c
index 0df9296..7b4523b 100644
--- a/btf_encoder.c
+++ b/btf_encoder.c
@@ -102,6 +102,8 @@ struct elf_secinfo {
};
struct elf_functions {
+ struct list_head node; /* for elf_functions_list */
+ Elf *elf; /* source ELF */
struct elf_symtab *symtab;
struct elf_function *entries;
int cnt;
@@ -134,7 +136,11 @@ struct btf_encoder {
size_t seccnt;
int encode_vars;
struct list_head func_states;
- struct elf_functions functions;
+ /* This is a list of elf_functions tables, one per ELF.
+ * Multiple ELF modules can be processed in one pahole run,
+ * so we have to store elf_functions tables per ELF.
+ */
+ struct list_head elf_functions_list;
};
struct btf_func {
@@ -148,6 +154,72 @@ struct btf_kfunc_set_range {
uint64_t end;
};
+static inline void elf_functions__delete(struct elf_functions *funcs)
+{
+ for (int i = 0; i < funcs->cnt; i++)
+ free(funcs->entries[i].alias);
+ free(funcs->entries);
+ elf_symtab__delete(funcs->symtab);
+ list_del(&funcs->node);
+ free(funcs);
+}
+
+static int elf_functions__collect(struct elf_functions *functions);
+
+struct elf_functions *elf_functions__new(Elf *elf)
+{
+ struct elf_functions *funcs;
+ int err;
+
+ funcs = calloc(1, sizeof(*funcs));
+ if (!funcs) {
+ err = -ENOMEM;
+ goto out_delete;
+ }
+
+ funcs->symtab = elf_symtab__new(NULL, elf);
+ if (!funcs->symtab) {
+ err = -1;
+ goto out_delete;
+ }
+
+ funcs->elf = elf;
+ err = elf_functions__collect(funcs);
+ if (err < 0)
+ goto out_delete;
+
+ return funcs;
+
+out_delete:
+ elf_functions__delete(funcs);
+ return NULL;
+}
+
+static inline void elf_functions_list__clear(struct list_head *elf_functions_list)
+{
+ struct elf_functions *funcs;
+ struct list_head *pos, *tmp;
+
+ list_for_each_safe(pos, tmp, elf_functions_list) {
+ funcs = list_entry(pos, struct elf_functions, node);
+ elf_functions__delete(funcs);
+ }
+}
+
+static struct elf_functions *elf_functions__find(const Elf *elf, const struct list_head *elf_functions_list)
+{
+ struct elf_functions *funcs;
+ struct list_head *pos;
+
+ list_for_each(pos, elf_functions_list) {
+ funcs = list_entry(pos, struct elf_functions, node);
+ if (funcs->elf == elf)
+ return funcs;
+ }
+ return NULL;
+}
+
+
static LIST_HEAD(encoders);
static pthread_mutex_t encoders__lock = PTHREAD_MUTEX_INITIALIZER;
@@ -1253,9 +1325,6 @@ static void btf_encoder__delete_saved_funcs(struct btf_encoder *encoder)
free(pos->annots);
free(pos);
}
-
- for (int i = 0; i < encoder->functions.cnt; i++)
- free(encoder->functions.entries[i].alias);
}
int btf_encoder__add_saved_funcs(struct btf_encoder *encoder)
@@ -1348,12 +1417,30 @@ static void elf_functions__collect_function(struct elf_functions *functions, GEl
functions->cnt++;
}
+static struct elf_functions *btf_encoder__elf_functions(struct btf_encoder *encoder)
+{
+ struct elf_functions *funcs = NULL;
+
+ if (!encoder->cu || !encoder->cu->elf)
+ return NULL;
+
+ funcs = elf_functions__find(encoder->cu->elf, &encoder->elf_functions_list);
+ if (!funcs) {
+ funcs = elf_functions__new(encoder->cu->elf);
+ if (funcs)
+ list_add(&funcs->node, &encoder->elf_functions_list);
+ }
+
+ return funcs;
+}
+
static struct elf_function *btf_encoder__find_function(const struct btf_encoder *encoder,
const char *name, size_t prefixlen)
{
+ struct elf_functions *funcs = elf_functions__find(encoder->cu->elf, &encoder->elf_functions_list);
struct elf_function key = { .name = name, .prefixlen = prefixlen };
- return bsearch(&key, encoder->functions.entries, encoder->functions.cnt, sizeof(key), functions_cmp);
+ return bsearch(&key, funcs->entries, funcs->cnt, sizeof(key), functions_cmp);
}
static bool btf_name_char_ok(char c, bool first)
@@ -2114,6 +2201,8 @@ int btf_encoder__encode(struct btf_encoder *encoder)
#endif
err = btf_encoder__write_elf(encoder, encoder->btf, BTF_ELF_SEC);
}
+
+ elf_functions_list__clear(&encoder->elf_functions_list);
return err;
}
@@ -2369,8 +2458,10 @@ out:
struct btf_encoder *btf_encoder__new(struct cu *cu, const char *detached_filename, struct btf *base_btf, bool verbose, struct conf_load *conf_load)
{
struct btf_encoder *encoder = zalloc(sizeof(*encoder));
+ struct elf_functions *funcs = NULL;
if (encoder) {
+ encoder->cu = cu;
encoder->raw_output = detached_filename != NULL;
encoder->source_filename = strdup(cu->filename);
encoder->filename = strdup(encoder->raw_output ? detached_filename : cu->filename);
@@ -2398,6 +2489,13 @@ struct btf_encoder *btf_encoder__new(struct cu *cu, const char *detached_filenam
if (conf_load->encode_btf_global_vars)
encoder->encode_vars |= BTF_VAR_GLOBAL;
+ INIT_LIST_HEAD(&encoder->elf_functions_list);
+ funcs = btf_encoder__elf_functions(encoder);
+ if (!funcs)
+ goto out_delete;
+
+ encoder->symtab = funcs->symtab;
+
GElf_Ehdr ehdr;
if (gelf_getehdr(cu->elf, &ehdr) == NULL) {
@@ -2418,14 +2516,6 @@ struct btf_encoder *btf_encoder__new(struct cu *cu, const char *detached_filenam
goto out_delete;
}
- encoder->symtab = elf_symtab__new(NULL, cu->elf);
- if (!encoder->symtab) {
- if (encoder->verbose)
- printf("%s: '%s' doesn't have symtab.\n", __func__, cu->filename);
- goto out;
- }
- encoder->functions.symtab = encoder->symtab;
-
/* index the ELF sections for later lookup */
GElf_Shdr shdr;
@@ -2463,14 +2553,11 @@ struct btf_encoder *btf_encoder__new(struct cu *cu, const char *detached_filenam
if (!found_percpu && encoder->verbose)
printf("%s: '%s' doesn't have '%s' section\n", __func__, cu->filename, PERCPU_SECTION);
- if (elf_functions__collect(&encoder->functions))
- goto out_delete;
-
if (encoder->verbose)
printf("File %s:\n", cu->filename);
btf_encoders__add(encoder);
}
-out:
+
return encoder;
out_delete:
@@ -2493,11 +2580,8 @@ void btf_encoder__delete(struct btf_encoder *encoder)
zfree(&encoder->source_filename);
btf__free(encoder->btf);
encoder->btf = NULL;
- elf_symtab__delete(encoder->symtab);
- encoder->functions.cnt = 0;
- free(encoder->functions.entries);
- encoder->functions.entries = NULL;
+ elf_functions_list__clear(&encoder->elf_functions_list);
btf_encoder__delete_saved_funcs(encoder);
@@ -2508,12 +2592,20 @@ int btf_encoder__encode_cu(struct btf_encoder *encoder, struct cu *cu, struct co
{
struct llvm_annotation *annot;
int btf_type_id, tag_type_id, skipped_types = 0;
+ struct elf_functions *funcs;
uint32_t core_id;
struct function *fn;
struct tag *pos;
int err = 0;
encoder->cu = cu;
+ funcs = btf_encoder__elf_functions(encoder);
+ if (!funcs) {
+ err = -1;
+ goto out;
+ }
+ encoder->symtab = funcs->symtab;
+
encoder->type_id_off = btf__type_cnt(encoder->btf) - 1;
if (!encoder->has_index_type) {
@@ -2597,7 +2689,7 @@ int btf_encoder__encode_cu(struct btf_encoder *encoder, struct cu *cu, struct co
continue;
if (!ftype__has_arg_names(&fn->proto))
continue;
- if (encoder->functions.cnt) {
+ if (funcs->cnt) {
const char *name;
name = function__name(fn);
@@ -2606,7 +2698,7 @@ int btf_encoder__encode_cu(struct btf_encoder *encoder, struct cu *cu, struct co
/* prefer exact function name match... */
func = btf_encoder__find_function(encoder, name, 0);
- if (!func && encoder->functions.suffix_cnt &&
+ if (!func && funcs->suffix_cnt &&
conf_load->btf_gen_optimized) {
/* falling back to name.isra.0 match if no exact
* match is found; only bother if we found any
--
2.47.1
next prev parent reply other threads:[~2025-01-07 19:09 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-01-07 19:08 [PATCH dwarves v4 00/10] pahole: faster reproducible BTF encoding Ihor Solodrai
2025-01-07 19:09 ` [PATCH dwarves v4 01/10] btf_encoder: simplify function encoding Ihor Solodrai
2025-01-07 19:09 ` [PATCH dwarves v4 02/10] btf_encoder: free encoder->secinfo in btf_encoder__delete Ihor Solodrai
2025-01-09 16:54 ` Alan Maguire
2025-01-09 21:36 ` Arnaldo Carvalho de Melo
2025-01-07 19:09 ` [PATCH dwarves v4 03/10] btf_encoder: separate elf function, saved function representations Ihor Solodrai
2025-01-07 19:09 ` [PATCH dwarves v4 04/10] btf_encoder: introduce elf_functions struct type Ihor Solodrai
2025-01-07 19:09 ` Ihor Solodrai [this message]
2025-01-07 19:09 ` [PATCH dwarves v4 06/10] btf_encoder: remove skip_encoding_inconsistent_proto Ihor Solodrai
2025-01-07 19:09 ` [PATCH dwarves v4 07/10] dwarf_loader: introduce cu->id Ihor Solodrai
2025-01-07 19:09 ` [PATCH dwarves v4] dwarf_loader: multithreading with a job/worker model Ihor Solodrai
2025-01-07 19:09 ` [PATCH dwarves v4 09/10] btf_encoder: clean up global encoders list Ihor Solodrai
2025-01-07 19:09 ` [PATCH dwarves v4] btf_encoder: switch func_states from a list to an array Ihor Solodrai
2025-01-07 20:35 ` [PATCH dwarves v4 00/10] pahole: faster reproducible BTF encoding Ihor Solodrai
2025-01-09 18:32 ` Arnaldo Carvalho de Melo
2025-01-09 18:38 ` Ihor Solodrai
2025-01-09 21:21 ` Arnaldo Carvalho de Melo
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=20250107190855.2312210-6-ihor.solodrai@pm.me \
--to=ihor.solodrai@pm.me \
--cc=acme@kernel.org \
--cc=alan.maguire@oracle.com \
--cc=andrii@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=dwarves@vger.kernel.org \
--cc=eddyz87@gmail.com \
--cc=mykolal@fb.com \
--cc=olsajiri@gmail.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