From patchwork Sat Dec 21 01:23:17 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ihor Solodrai X-Patchwork-Id: 13917576 Received: from mail-40133.protonmail.ch (mail-40133.protonmail.ch [185.70.40.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5BE7017588 for ; Sat, 21 Dec 2024 01:23:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.70.40.133 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1734744212; cv=none; b=q+HnPf4XnyizcIbfZw6aQ0b5Bovpvp0RIHFh12tPe4cdL8+pM9hzYkb0gCE4SYGQKiY0ZaKrEfmQvauIzulghwDKyoBCwm72e83hK3svPY1ZMXexz+mTefTqlgj86eBuihOFPG6n/hDobGI77RI1ild58LHMQBriEXHL+f0p1Ok= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1734744212; c=relaxed/simple; bh=6cVgHfhfZdxpLvYOK0R8n/C+xGHjC4kgqF2iyCdnEgQ=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=m0XZjxs9yKfpOFBKCgpj1WSkr7MQS8txlQ1QDCtDq7gg2fT/lIdTDE2f6+y2maYsthamc4KsDQ/e0e09lQCiOZyusXKjzIO+SerW7JO95NlZYOHG0Bv0vPOFybhGxq6onriEp9002a8zyIXeMTtfVDt5SV9LWivw38DORjkX928= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=pm.me; spf=pass smtp.mailfrom=pm.me; dkim=pass (2048-bit key) header.d=pm.me header.i=@pm.me header.b=XsZpu8Xo; arc=none smtp.client-ip=185.70.40.133 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=pm.me Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=pm.me Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=pm.me header.i=@pm.me header.b="XsZpu8Xo" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pm.me; s=protonmail3; t=1734744203; x=1735003403; bh=tVIggqt/vu4CUOFrjaawdDXhmMFLrK7i643N2uoykNQ=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: Feedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID: Message-ID:BIMI-Selector:List-Unsubscribe:List-Unsubscribe-Post; b=XsZpu8XoCamVO6xzVlHgAwZpHgrbKNaXsDBefrwb0yLZsRGXI31tFd4e6E9mD3lCm Gi/4S1rWyjLgrq5fXxt5dV5NS5knd6vqBoogSkf5IU/i4lFGk5wDqDfss1L7TIHjeZ RQBnkxQ0n7iGgG9P3+vNWC/nGvap7+GMmS6UrdnxESlZZUD6PbZU4cHW3yX7ARhTx2 2c0Npv9arb0t/i55tp+h9MBS69se5fTeFmyfh7tm5o92uDNsKRInsuXAEA0iCh6Ngm lKnjLK44FUWEBzxMsZFLrkFsKj7QDpqLBmiEqLpf2oh1xXkLnEEgC4vAkrGTst6GHM 3KyDmsK5/4dxg== Date: Sat, 21 Dec 2024 01:23:17 +0000 To: dwarves@vger.kernel.org From: Ihor Solodrai Cc: acme@kernel.org, alan.maguire@oracle.com, eddyz87@gmail.com, andrii@kernel.org, mykolal@fb.com, bpf@vger.kernel.org Subject: [PATCH dwarves v3 4/8] btf_encoder: introduce elf_functions_list Message-ID: <20241221012245.243845-5-ihor.solodrai@pm.me> In-Reply-To: <20241221012245.243845-1-ihor.solodrai@pm.me> References: <20241221012245.243845-1-ihor.solodrai@pm.me> Feedback-ID: 27520582:user:proton X-Pm-Message-ID: 1b6b20a28e09e628bb7bcbf029f6b9c773bde894 Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 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 --- btf_encoder.c | 138 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 115 insertions(+), 23 deletions(-) diff --git a/btf_encoder.c b/btf_encoder.c index 1467e09..566ecfe 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) @@ -1341,12 +1410,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) @@ -2100,6 +2187,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; } @@ -2358,8 +2447,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); @@ -2387,6 +2478,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) { @@ -2407,14 +2505,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; @@ -2452,14 +2542,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: @@ -2482,11 +2569,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); @@ -2497,12 +2581,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) { @@ -2586,7 +2678,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); @@ -2595,7 +2687,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