From patchwork Tue Jan 24 13:45:27 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Maguire X-Patchwork-Id: 13114164 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 51C17C38142 for ; Tue, 24 Jan 2023 13:49:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233890AbjAXNtf (ORCPT ); Tue, 24 Jan 2023 08:49:35 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44400 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234520AbjAXNtW (ORCPT ); Tue, 24 Jan 2023 08:49:22 -0500 Received: from mx0b-00069f02.pphosted.com (mx0b-00069f02.pphosted.com [205.220.177.32]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 306404A1EC for ; Tue, 24 Jan 2023 05:47:11 -0800 (PST) Received: from pps.filterd (m0246631.ppops.net [127.0.0.1]) by mx0b-00069f02.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 30ODI0vn020819; Tue, 24 Jan 2023 13:45:41 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oracle.com; h=from : to : cc : subject : date : message-id : in-reply-to : references; s=corp-2022-7-12; bh=6YmgzfREeWWPe+FbqSOX6JR1RgoKQWvYthiYsgCt1EQ=; b=kwkUeKV7AzqvNJgXJeBGty4+AygjdOtwx3WbOM5qXFgSvsD8+Mubo60OUY9LBoKEht3m YOfrCp8qYfvPNX2YZOJSYE4+YVZF1KMXW6Ey2++7zW9DPAWVsK2jyEVqMFmUzhE+Y9QR 2J9XFJ7selEREyACBIytfhzF9TqUSJ59zLKU2zYTuvWVDGd4qkVIrhTOlApwshoCyqN6 jSQYoj++Xt2jFgVNZ6eDx4HbNV20s6O9+vE3N+KTwmqscQ9HKbHecbMvolf841GlGLZ8 rZaK0i5Sx9E22AviqFMsbplsqquUS+ovCrVa1PqVWLGrELJ+3hB3bpq9HLCTyWYwzheQ Pg== Received: from iadpaimrmta02.imrmtpd1.prodappiadaev1.oraclevcn.com (iadpaimrmta02.appoci.oracle.com [147.154.18.20]) by mx0b-00069f02.pphosted.com (PPS) with ESMTPS id 3n86u2wc5k-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 24 Jan 2023 13:45:40 +0000 Received: from pps.filterd (iadpaimrmta02.imrmtpd1.prodappiadaev1.oraclevcn.com [127.0.0.1]) by iadpaimrmta02.imrmtpd1.prodappiadaev1.oraclevcn.com (8.17.1.5/8.17.1.5) with ESMTP id 30OBmnFx021016; Tue, 24 Jan 2023 13:45:40 GMT Received: from pps.reinject (localhost [127.0.0.1]) by iadpaimrmta02.imrmtpd1.prodappiadaev1.oraclevcn.com (PPS) with ESMTPS id 3n86gbr5jx-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 24 Jan 2023 13:45:40 +0000 Received: from iadpaimrmta02.imrmtpd1.prodappiadaev1.oraclevcn.com (iadpaimrmta02.imrmtpd1.prodappiadaev1.oraclevcn.com [127.0.0.1]) by pps.reinject (8.17.1.5/8.17.1.5) with ESMTP id 30ODjZ3r037951; Tue, 24 Jan 2023 13:45:39 GMT Received: from myrouter.uk.oracle.com (dhcp-10-175-161-98.vpn.oracle.com [10.175.161.98]) by iadpaimrmta02.imrmtpd1.prodappiadaev1.oraclevcn.com (PPS) with ESMTP id 3n86gbr5fj-2; Tue, 24 Jan 2023 13:45:39 +0000 From: Alan Maguire To: acme@kernel.org, yhs@fb.com, ast@kernel.org, olsajiri@gmail.com, timo@incline.eu Cc: daniel@iogearbox.net, andrii@kernel.org, songliubraving@fb.com, john.fastabend@gmail.com, kpsingh@chromium.org, sdf@google.com, haoluo@google.com, martin.lau@kernel.org, bpf@vger.kernel.org, Alan Maguire Subject: [PATCH dwarves 1/5] dwarves: help dwarf loader spot functions with optimized-out parameters Date: Tue, 24 Jan 2023 13:45:27 +0000 Message-Id: <1674567931-26458-2-git-send-email-alan.maguire@oracle.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1674567931-26458-1-git-send-email-alan.maguire@oracle.com> References: <1674567931-26458-1-git-send-email-alan.maguire@oracle.com> X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.219,Aquarius:18.0.930,Hydra:6.0.562,FMLib:17.11.122.1 definitions=2023-01-23_12,2023-01-24_01,2022-06-22_01 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 phishscore=0 mlxscore=0 spamscore=0 bulkscore=0 mlxlogscore=999 malwarescore=0 adultscore=0 suspectscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2212070000 definitions=main-2301240125 X-Proofpoint-GUID: unTRRNDAhYmCDQsvtnDJmMdWnNIcf-Nd X-Proofpoint-ORIG-GUID: unTRRNDAhYmCDQsvtnDJmMdWnNIcf-Nd Precedence: bulk List-ID: X-Mailing-List: bpf@vger.kernel.org Compilation generates DWARF at several stages, and often the later DWARF representations more accurately represent optimizations that have occurred during compilation. In particular, parameter representations can be spotted by their abstract origin references to the original parameter, but they often have more accurate location information. In most cases, the parameter locations will match calling conventions, and be registers for the first 6 parameters on x86_64, first 8 on ARM64 etc. If the parameter is not a register when it should be however, it is likely passed via the stack or the compiler has used a constant representation instead. This change adds a field to parameters and their associated ftype to note if a parameter has been optimized out. Having this information allows us to skip such functions, as their presence in CUs makes BTF encoding impossible. Signed-off-by: Alan Maguire --- dwarf_loader.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- dwarves.h | 4 +++- 2 files changed, 77 insertions(+), 3 deletions(-) diff --git a/dwarf_loader.c b/dwarf_loader.c index 5a74035..0220f1d 100644 --- a/dwarf_loader.c +++ b/dwarf_loader.c @@ -992,13 +992,67 @@ static struct class_member *class_member__new(Dwarf_Die *die, struct cu *cu, return member; } -static struct parameter *parameter__new(Dwarf_Die *die, struct cu *cu, struct conf_load *conf) +/* How many function parameters are passed via registers? Used below in + * determining if an argument has been optimized out or if it is simply + * an argument > NR_REGISTER_PARAMS. Setting NR_REGISTER_PARAMS to 0 + * allows unsupported architectures to skip tagging optimized-out + * values. + */ +#if defined(__x86_64__) +#define NR_REGISTER_PARAMS 6 +#elif defined(__s390__) +#define NR_REGISTER_PARAMS 5 +#elif defined(__aarch64__) +#define NR_REGISTER_PARAMS 8 +#elif defined(__mips__) +#define NR_REGISTER_PARAMS 8 +#elif defined(__powerpc__) +#define NR_REGISTER_PARAMS 8 +#elif defined(__sparc__) +#define NR_REGISTER_PARAMS 6 +#elif defined(__riscv) && __riscv_xlen == 64 +#define NR_REGISTER_PARAMS 8 +#elif defined(__arc__) +#define NR_REGISTER_PARAMS 8 +#else +#define NR_REGISTER_PARAMS 0 +#endif + +static struct parameter *parameter__new(Dwarf_Die *die, struct cu *cu, + struct conf_load *conf, int param_idx) { struct parameter *parm = tag__alloc(cu, sizeof(*parm)); if (parm != NULL) { + struct location loc; + tag__init(&parm->tag, cu, die); parm->name = attr_string(die, DW_AT_name, conf); + + /* Parameters which use DW_AT_abstract_origin to point at + * the original parameter definition (with no name in the DIE) + * are the result of later DWARF generation during compilation + * so often better take into account if arguments were + * optimized out. + * + * By checking that locations for parameters that are expected + * to be passed as registers are actually passed as registers, + * we can spot optimized-out parameters. + */ + if (param_idx < NR_REGISTER_PARAMS && !parm->name && + attr_location(die, &loc.expr, &loc.exprlen) == 0 && + loc.exprlen != 0) { + Dwarf_Op *expr = loc.expr; + + switch (expr->atom) { + case DW_OP_reg1 ... DW_OP_reg31: + case DW_OP_breg0 ... DW_OP_breg31: + break; + default: + parm->optimized = true; + break; + } + } } return parm; @@ -1450,7 +1504,7 @@ static struct tag *die__create_new_parameter(Dwarf_Die *die, struct cu *cu, struct conf_load *conf, int param_idx) { - struct parameter *parm = parameter__new(die, cu, conf); + struct parameter *parm = parameter__new(die, cu, conf, param_idx); if (parm == NULL) return NULL; @@ -2209,6 +2263,10 @@ static void ftype__recode_dwarf_types(struct tag *tag, struct cu *cu) } pos->name = tag__parameter(dtype->tag)->name; pos->tag.type = dtype->tag->type; + if (pos->optimized) { + tag__parameter(dtype->tag)->optimized = pos->optimized; + type->optimized_parms = 1; + } continue; } @@ -2219,6 +2277,20 @@ static void ftype__recode_dwarf_types(struct tag *tag, struct cu *cu) } pos->tag.type = dtype->small_id; } + /* if parameters were optimized out, set flag for the ftype this + * function tag referred to via abstract origin. + */ + if (type->optimized_parms) { + struct dwarf_tag *dtype = type->tag.priv; + struct dwarf_tag *dftype; + + dftype = dwarf_cu__find_tag_by_ref(dcu, &dtype->abstract_origin); + if (dftype && dftype->tag) { + struct ftype *ftype = tag__ftype(dftype->tag); + + ftype->optimized_parms = 1; + } + } } static void lexblock__recode_dwarf_types(struct lexblock *tag, struct cu *cu) diff --git a/dwarves.h b/dwarves.h index 589588e..1ad1b3b 100644 --- a/dwarves.h +++ b/dwarves.h @@ -808,6 +808,7 @@ size_t lexblock__fprintf(const struct lexblock *lexblock, const struct cu *cu, struct parameter { struct tag tag; const char *name; + bool optimized; }; static inline struct parameter *tag__parameter(const struct tag *tag) @@ -827,7 +828,8 @@ struct ftype { struct tag tag; struct list_head parms; uint16_t nr_parms; - uint8_t unspec_parms; /* just one bit is needed */ + uint8_t unspec_parms:1; /* just one bit is needed */ + uint8_t optimized_parms:1; }; static inline struct ftype *tag__ftype(const struct tag *tag) From patchwork Tue Jan 24 13:45:28 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Maguire X-Patchwork-Id: 13114292 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 12C12C25B4E for ; Tue, 24 Jan 2023 14:57:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235169AbjAXO5m (ORCPT ); Tue, 24 Jan 2023 09:57:42 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43972 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234450AbjAXO5m (ORCPT ); Tue, 24 Jan 2023 09:57:42 -0500 Received: from mx0b-00069f02.pphosted.com (mx0b-00069f02.pphosted.com [205.220.177.32]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E00C0279B2 for ; Tue, 24 Jan 2023 06:57:40 -0800 (PST) Received: from pps.filterd (m0333520.ppops.net [127.0.0.1]) by mx0b-00069f02.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 30ODHiTD002552; Tue, 24 Jan 2023 13:45:44 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oracle.com; h=from : to : cc : subject : date : message-id : in-reply-to : references; s=corp-2022-7-12; bh=CWJASffG0y5aFpyOpRF5/WXa8b3KKWQIjTEmf4Z/em8=; b=UlkAvsWClp06ui0cBR42x1UKoRudTGKVInuknZzhkvc4K6Ch3LkC1fWiYsJMBRrDolRm r0fW0ADHi5SgE677DpEDtCnrZO4zp2u3ZUmDsqUd9RB/Yp9cg9xXbWgkI7Al5WMJcSNE Y9/wWxxDRqpVn/PhR6ug0bD2vHOFo6cufGnIoxkXX0Dt7Jp7FaOdIWkGwwN6bV4/eHh1 06mhZVFbi0UGi1BIo9jydChooY/r7HUMpFAC2MK8U4JCN4Aa/l4O74Ntp8BeNlWfdEcW hwn6Z8lBF+AHh0kGQo7hZEkvzI5iN2Eyoci/gpnKf8ZGjWQdDktqN83imAy6chTUzE+k zg== Received: from iadpaimrmta02.imrmtpd1.prodappiadaev1.oraclevcn.com (iadpaimrmta02.appoci.oracle.com [147.154.18.20]) by mx0b-00069f02.pphosted.com (PPS) with ESMTPS id 3n883c5buj-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 24 Jan 2023 13:45:44 +0000 Received: from pps.filterd (iadpaimrmta02.imrmtpd1.prodappiadaev1.oraclevcn.com [127.0.0.1]) by iadpaimrmta02.imrmtpd1.prodappiadaev1.oraclevcn.com (8.17.1.5/8.17.1.5) with ESMTP id 30OBmnIn021076; Tue, 24 Jan 2023 13:45:44 GMT Received: from pps.reinject (localhost [127.0.0.1]) by iadpaimrmta02.imrmtpd1.prodappiadaev1.oraclevcn.com (PPS) with ESMTPS id 3n86gbr5mp-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 24 Jan 2023 13:45:43 +0000 Received: from iadpaimrmta02.imrmtpd1.prodappiadaev1.oraclevcn.com (iadpaimrmta02.imrmtpd1.prodappiadaev1.oraclevcn.com [127.0.0.1]) by pps.reinject (8.17.1.5/8.17.1.5) with ESMTP id 30ODjZ3t037951; Tue, 24 Jan 2023 13:45:43 GMT Received: from myrouter.uk.oracle.com (dhcp-10-175-161-98.vpn.oracle.com [10.175.161.98]) by iadpaimrmta02.imrmtpd1.prodappiadaev1.oraclevcn.com (PPS) with ESMTP id 3n86gbr5fj-3; Tue, 24 Jan 2023 13:45:43 +0000 From: Alan Maguire To: acme@kernel.org, yhs@fb.com, ast@kernel.org, olsajiri@gmail.com, timo@incline.eu Cc: daniel@iogearbox.net, andrii@kernel.org, songliubraving@fb.com, john.fastabend@gmail.com, kpsingh@chromium.org, sdf@google.com, haoluo@google.com, martin.lau@kernel.org, bpf@vger.kernel.org, Alan Maguire Subject: [PATCH dwarves 2/5] btf_encoder: refactor function addition into dedicated btf_encoder__add_func Date: Tue, 24 Jan 2023 13:45:28 +0000 Message-Id: <1674567931-26458-3-git-send-email-alan.maguire@oracle.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1674567931-26458-1-git-send-email-alan.maguire@oracle.com> References: <1674567931-26458-1-git-send-email-alan.maguire@oracle.com> X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.219,Aquarius:18.0.930,Hydra:6.0.562,FMLib:17.11.122.1 definitions=2023-01-23_12,2023-01-24_01,2022-06-22_01 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 phishscore=0 mlxscore=0 spamscore=0 bulkscore=0 mlxlogscore=999 malwarescore=0 adultscore=0 suspectscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2212070000 definitions=main-2301240125 X-Proofpoint-ORIG-GUID: spVaUXkOBs6UY0Kjyma6JVD40KmMABil X-Proofpoint-GUID: spVaUXkOBs6UY0Kjyma6JVD40KmMABil Precedence: bulk List-ID: X-Mailing-List: bpf@vger.kernel.org This will be useful for postponing local function addition later on. As part of this, store the type id offset and unspecified type in the encoder, as this will simplify late addition of local functions. Signed-off-by: Alan Maguire --- btf_encoder.c | 99 +++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 55 insertions(+), 44 deletions(-) diff --git a/btf_encoder.c b/btf_encoder.c index a5fa04a..15a042c 100644 --- a/btf_encoder.c +++ b/btf_encoder.c @@ -54,6 +54,8 @@ struct btf_encoder { struct gobuffer percpu_secinfo; const char *filename; struct elf_symtab *symtab; + uint32_t type_id_off; + uint32_t unspecified_type; bool has_index_type, need_index_type, skip_encoding_vars, @@ -593,20 +595,20 @@ static int32_t btf_encoder__add_func_param(struct btf_encoder *encoder, const ch } } -static int32_t btf_encoder__tag_type(struct btf_encoder *encoder, uint32_t type_id_off, uint32_t tag_type) +static int32_t btf_encoder__tag_type(struct btf_encoder *encoder, uint32_t tag_type) { if (tag_type == 0) return 0; - if (encoder->cu->unspecified_type.tag && tag_type == encoder->cu->unspecified_type.type) { + if (tag_type == encoder->unspecified_type) { // No provision for encoding this, turn it into void. return 0; } - return type_id_off + tag_type; + return encoder->type_id_off + tag_type; } -static int32_t btf_encoder__add_func_proto(struct btf_encoder *encoder, struct ftype *ftype, uint32_t type_id_off) +static int32_t btf_encoder__add_func_proto(struct btf_encoder *encoder, struct ftype *ftype) { struct btf *btf = encoder->btf; const struct btf_type *t; @@ -616,7 +618,7 @@ static int32_t btf_encoder__add_func_proto(struct btf_encoder *encoder, struct f /* add btf_type for func_proto */ nr_params = ftype->nr_parms + (ftype->unspec_parms ? 1 : 0); - type_id = btf_encoder__tag_type(encoder, type_id_off, ftype->tag.type); + type_id = btf_encoder__tag_type(encoder, ftype->tag.type); id = btf__add_func_proto(btf, type_id); if (id > 0) { @@ -634,7 +636,7 @@ static int32_t btf_encoder__add_func_proto(struct btf_encoder *encoder, struct f ftype__for_each_parameter(ftype, param) { const char *name = parameter__name(param); - type_id = param->tag.type == 0 ? 0 : type_id_off + param->tag.type; + type_id = param->tag.type == 0 ? 0 : encoder->type_id_off + param->tag.type; ++param_idx; if (btf_encoder__add_func_param(encoder, name, type_id, param_idx == nr_params)) return -1; @@ -762,6 +764,30 @@ static int32_t btf_encoder__add_decl_tag(struct btf_encoder *encoder, const char return id; } +static int32_t btf_encoder__add_func(struct btf_encoder *encoder, struct function *fn) +{ + int btf_fnproto_id, btf_fn_id, tag_type_id; + struct llvm_annotation *annot; + const char *name; + + btf_fnproto_id = btf_encoder__add_func_proto(encoder, &fn->proto); + name = function__name(fn); + btf_fn_id = btf_encoder__add_ref_type(encoder, BTF_KIND_FUNC, btf_fnproto_id, name, false); + if (btf_fnproto_id < 0 || btf_fn_id < 0) { + printf("error: failed to encode function '%s'\n", function__name(fn)); + return -1; + } + list_for_each_entry(annot, &fn->annots, node) { + tag_type_id = btf_encoder__add_decl_tag(encoder, annot->value, btf_fn_id, annot->component_idx); + if (tag_type_id < 0) { + fprintf(stderr, "error: failed to encode tag '%s' to func %s with component_idx %d\n", + annot->value, name, annot->component_idx); + return -1; + } + } + return 0; +} + /* * This corresponds to the same macro defined in * include/linux/kallsyms.h @@ -859,22 +885,21 @@ static void dump_invalid_symbol(const char *msg, const char *sym, fprintf(stderr, "PAHOLE: Error: Use '--btf_encode_force' to ignore such symbols and force emit the btf.\n"); } -static int tag__check_id_drift(const struct tag *tag, - uint32_t core_id, uint32_t btf_type_id, - uint32_t type_id_off) +static int tag__check_id_drift(struct btf_encoder *encoder, const struct tag *tag, + uint32_t core_id, uint32_t btf_type_id) { - if (btf_type_id != (core_id + type_id_off)) { + if (btf_type_id != (core_id + encoder->type_id_off)) { fprintf(stderr, "%s: %s id drift, core_id: %u, btf_type_id: %u, type_id_off: %u\n", __func__, dwarf_tag_name(tag->tag), - core_id, btf_type_id, type_id_off); + core_id, btf_type_id, encoder->type_id_off); return -1; } return 0; } -static int32_t btf_encoder__add_struct_type(struct btf_encoder *encoder, struct tag *tag, uint32_t type_id_off) +static int32_t btf_encoder__add_struct_type(struct btf_encoder *encoder, struct tag *tag) { struct type *type = tag__type(tag); struct class_member *pos; @@ -896,7 +921,7 @@ static int32_t btf_encoder__add_struct_type(struct btf_encoder *encoder, struct * is required. */ name = class_member__name(pos); - if (btf_encoder__add_field(encoder, name, type_id_off + pos->tag.type, pos->bitfield_size, pos->bit_offset)) + if (btf_encoder__add_field(encoder, name, encoder->type_id_off + pos->tag.type, pos->bitfield_size, pos->bit_offset)) return -1; } @@ -936,11 +961,11 @@ static int32_t btf_encoder__add_enum_type(struct btf_encoder *encoder, struct ta return type_id; } -static int btf_encoder__encode_tag(struct btf_encoder *encoder, struct tag *tag, uint32_t type_id_off, +static int btf_encoder__encode_tag(struct btf_encoder *encoder, struct tag *tag, struct conf_load *conf_load) { /* single out type 0 as it represents special type "void" */ - uint32_t ref_type_id = tag->type == 0 ? 0 : type_id_off + tag->type; + uint32_t ref_type_id = tag->type == 0 ? 0 : encoder->type_id_off + tag->type; struct base_type *bt; const char *name; @@ -970,7 +995,7 @@ static int btf_encoder__encode_tag(struct btf_encoder *encoder, struct tag *tag, if (tag__type(tag)->declaration) return btf_encoder__add_ref_type(encoder, BTF_KIND_FWD, 0, name, tag->tag == DW_TAG_union_type); else - return btf_encoder__add_struct_type(encoder, tag, type_id_off); + return btf_encoder__add_struct_type(encoder, tag); case DW_TAG_array_type: /* TODO: Encode one dimension at a time. */ encoder->need_index_type = true; @@ -978,7 +1003,7 @@ static int btf_encoder__encode_tag(struct btf_encoder *encoder, struct tag *tag, case DW_TAG_enumeration_type: return btf_encoder__add_enum_type(encoder, tag, conf_load); case DW_TAG_subroutine_type: - return btf_encoder__add_func_proto(encoder, tag__ftype(tag), type_id_off); + return btf_encoder__add_func_proto(encoder, tag__ftype(tag)); case DW_TAG_unspecified_type: /* Just don't encode this for now, converting anything with this type to void (0) instead. * @@ -1281,7 +1306,7 @@ static bool ftype__has_arg_names(const struct ftype *ftype) return true; } -static int btf_encoder__encode_cu_variables(struct btf_encoder *encoder, uint32_t type_id_off) +static int btf_encoder__encode_cu_variables(struct btf_encoder *encoder) { struct cu *cu = encoder->cu; uint32_t core_id; @@ -1366,7 +1391,7 @@ static int btf_encoder__encode_cu_variables(struct btf_encoder *encoder, uint32_ continue; } - type = var->ip.tag.type + type_id_off; + type = var->ip.tag.type + encoder->type_id_off; linkage = var->external ? BTF_VAR_GLOBAL_ALLOCATED : BTF_VAR_STATIC; if (encoder->verbose) { @@ -1507,7 +1532,6 @@ void btf_encoder__delete(struct btf_encoder *encoder) int btf_encoder__encode_cu(struct btf_encoder *encoder, struct cu *cu, struct conf_load *conf_load) { - uint32_t type_id_off = btf__type_cnt(encoder->btf) - 1; struct llvm_annotation *annot; int btf_type_id, tag_type_id, skipped_types = 0; uint32_t core_id; @@ -1516,21 +1540,24 @@ int btf_encoder__encode_cu(struct btf_encoder *encoder, struct cu *cu, struct co int err = 0; encoder->cu = cu; + encoder->type_id_off = btf__type_cnt(encoder->btf) - 1; + if (encoder->cu->unspecified_type.tag) + encoder->unspecified_type = encoder->cu->unspecified_type.type; if (!encoder->has_index_type) { /* cu__find_base_type_by_name() takes "type_id_t *id" */ type_id_t id; if (cu__find_base_type_by_name(cu, "int", &id)) { encoder->has_index_type = true; - encoder->array_index_id = type_id_off + id; + encoder->array_index_id = encoder->type_id_off + id; } else { encoder->has_index_type = false; - encoder->array_index_id = type_id_off + cu->types_table.nr_entries; + encoder->array_index_id = encoder->type_id_off + cu->types_table.nr_entries; } } cu__for_each_type(cu, core_id, pos) { - btf_type_id = btf_encoder__encode_tag(encoder, pos, type_id_off, conf_load); + btf_type_id = btf_encoder__encode_tag(encoder, pos, conf_load); if (btf_type_id == 0) { ++skipped_types; @@ -1538,7 +1565,7 @@ int btf_encoder__encode_cu(struct btf_encoder *encoder, struct cu *cu, struct co } if (btf_type_id < 0 || - tag__check_id_drift(pos, core_id, btf_type_id + skipped_types, type_id_off)) { + tag__check_id_drift(encoder, pos, core_id, btf_type_id + skipped_types)) { err = -1; goto out; } @@ -1572,7 +1599,7 @@ int btf_encoder__encode_cu(struct btf_encoder *encoder, struct cu *cu, struct co continue; } - btf_type_id = type_id_off + core_id; + btf_type_id = encoder->type_id_off + core_id; ns = tag__namespace(pos); list_for_each_entry(annot, &ns->annots, node) { tag_type_id = btf_encoder__add_decl_tag(encoder, annot->value, btf_type_id, annot->component_idx); @@ -1585,8 +1612,6 @@ int btf_encoder__encode_cu(struct btf_encoder *encoder, struct cu *cu, struct co } cu__for_each_function(cu, core_id, fn) { - int btf_fnproto_id, btf_fn_id; - const char *name; /* * Skip functions that: @@ -1616,27 +1641,13 @@ int btf_encoder__encode_cu(struct btf_encoder *encoder, struct cu *cu, struct co continue; } - btf_fnproto_id = btf_encoder__add_func_proto(encoder, &fn->proto, type_id_off); - name = function__name(fn); - btf_fn_id = btf_encoder__add_ref_type(encoder, BTF_KIND_FUNC, btf_fnproto_id, name, false); - if (btf_fnproto_id < 0 || btf_fn_id < 0) { - err = -1; - printf("error: failed to encode function '%s'\n", function__name(fn)); + err = btf_encoder__add_func(encoder, fn); + if (err) goto out; - } - - list_for_each_entry(annot, &fn->annots, node) { - tag_type_id = btf_encoder__add_decl_tag(encoder, annot->value, btf_fn_id, annot->component_idx); - if (tag_type_id < 0) { - fprintf(stderr, "error: failed to encode tag '%s' to func %s with component_idx %d\n", - annot->value, name, annot->component_idx); - goto out; - } - } } if (!encoder->skip_encoding_vars) - err = btf_encoder__encode_cu_variables(encoder, type_id_off); + err = btf_encoder__encode_cu_variables(encoder); out: encoder->cu = NULL; return err; From patchwork Tue Jan 24 13:45:29 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Maguire X-Patchwork-Id: 13114165 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 257B2C25B4E for ; Tue, 24 Jan 2023 13:49:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234756AbjAXNth (ORCPT ); Tue, 24 Jan 2023 08:49:37 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43654 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234598AbjAXNtX (ORCPT ); Tue, 24 Jan 2023 08:49:23 -0500 Received: from mx0b-00069f02.pphosted.com (mx0b-00069f02.pphosted.com [205.220.177.32]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E75C546700 for ; Tue, 24 Jan 2023 05:47:13 -0800 (PST) Received: from pps.filterd (m0333520.ppops.net [127.0.0.1]) by mx0b-00069f02.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 30ODHhk1002539; Tue, 24 Jan 2023 13:45:48 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oracle.com; h=from : to : cc : subject : date : message-id : in-reply-to : references; s=corp-2022-7-12; bh=G+I7KnrQ/H/31Cfswrotey4N0yvpKVUFFC/LA3Hr4mc=; b=IunItGn+locyyCbSuMAck5lhsUmlv3YNAqsAt6St2rSlMEtJawiPSkmvN8IBHzlMIa2Z jzvpPMxFyW3I8TZlYPaFj4vubo8pQ4qhctv4jb5lxpeS05VOTq9g2Z2KRjYfnMoEZH0y kHUxYZhxapP0j4qEb0LYILPbbxgf/caDBNazZwv5swL1ju2NdCG4rpgDfKaAmWuGfoYv 0wf50Dpry6GJyWkcACRwFXt7HNWbtKRq5XcD0+3IM0IhuloAWm6EIM2W9lT4pGCbjBrw V0MlwFASibM56k1pr16yW9v7nySs93QxQt6nKICKC7e1KHDULjXps4HzmUIEqUxRgzbV Og== Received: from iadpaimrmta02.imrmtpd1.prodappiadaev1.oraclevcn.com (iadpaimrmta02.appoci.oracle.com [147.154.18.20]) by mx0b-00069f02.pphosted.com (PPS) with ESMTPS id 3n883c5bun-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 24 Jan 2023 13:45:48 +0000 Received: from pps.filterd (iadpaimrmta02.imrmtpd1.prodappiadaev1.oraclevcn.com [127.0.0.1]) by iadpaimrmta02.imrmtpd1.prodappiadaev1.oraclevcn.com (8.17.1.5/8.17.1.5) with ESMTP id 30OBmnvW021048; Tue, 24 Jan 2023 13:45:48 GMT Received: from pps.reinject (localhost [127.0.0.1]) by iadpaimrmta02.imrmtpd1.prodappiadaev1.oraclevcn.com (PPS) with ESMTPS id 3n86gbr5pj-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 24 Jan 2023 13:45:47 +0000 Received: from iadpaimrmta02.imrmtpd1.prodappiadaev1.oraclevcn.com (iadpaimrmta02.imrmtpd1.prodappiadaev1.oraclevcn.com [127.0.0.1]) by pps.reinject (8.17.1.5/8.17.1.5) with ESMTP id 30ODjZ3v037951; Tue, 24 Jan 2023 13:45:47 GMT Received: from myrouter.uk.oracle.com (dhcp-10-175-161-98.vpn.oracle.com [10.175.161.98]) by iadpaimrmta02.imrmtpd1.prodappiadaev1.oraclevcn.com (PPS) with ESMTP id 3n86gbr5fj-4; Tue, 24 Jan 2023 13:45:46 +0000 From: Alan Maguire To: acme@kernel.org, yhs@fb.com, ast@kernel.org, olsajiri@gmail.com, timo@incline.eu Cc: daniel@iogearbox.net, andrii@kernel.org, songliubraving@fb.com, john.fastabend@gmail.com, kpsingh@chromium.org, sdf@google.com, haoluo@google.com, martin.lau@kernel.org, bpf@vger.kernel.org, Alan Maguire Subject: [PATCH dwarves 3/5] btf_encoder: child encoders should have a reference to parent encoder Date: Tue, 24 Jan 2023 13:45:29 +0000 Message-Id: <1674567931-26458-4-git-send-email-alan.maguire@oracle.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1674567931-26458-1-git-send-email-alan.maguire@oracle.com> References: <1674567931-26458-1-git-send-email-alan.maguire@oracle.com> X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.219,Aquarius:18.0.930,Hydra:6.0.562,FMLib:17.11.122.1 definitions=2023-01-23_12,2023-01-24_01,2022-06-22_01 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 phishscore=0 mlxscore=0 spamscore=0 bulkscore=0 mlxlogscore=999 malwarescore=0 adultscore=0 suspectscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2212070000 definitions=main-2301240125 X-Proofpoint-ORIG-GUID: 4DH8C4S4Gpyb5r29sHL4BRSi-Y2aDKA5 X-Proofpoint-GUID: 4DH8C4S4Gpyb5r29sHL4BRSi-Y2aDKA5 Precedence: bulk List-ID: X-Mailing-List: bpf@vger.kernel.org The parent encoder will be used to share details of local functions such that we can mark those which have optimized parameters in any CU. Signed-off-by: Alan Maguire --- btf_encoder.c | 4 +++- btf_encoder.h | 2 +- pahole.c | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/btf_encoder.c b/btf_encoder.c index 15a042c..449439f 100644 --- a/btf_encoder.c +++ b/btf_encoder.c @@ -49,6 +49,7 @@ struct var_info { */ struct btf_encoder { struct list_head node; + struct btf_encoder *parent; struct btf *btf; struct cu *cu; struct gobuffer percpu_secinfo; @@ -1433,11 +1434,12 @@ out: return err; } -struct btf_encoder *btf_encoder__new(struct cu *cu, const char *detached_filename, struct btf *base_btf, bool skip_encoding_vars, bool force, bool gen_floats, bool verbose) +struct btf_encoder *btf_encoder__new(struct cu *cu, const char *detached_filename, struct btf *base_btf, bool skip_encoding_vars, bool force, bool gen_floats, struct btf_encoder *parent, bool verbose) { struct btf_encoder *encoder = zalloc(sizeof(*encoder)); if (encoder) { + encoder->parent = parent; encoder->raw_output = detached_filename != NULL; encoder->filename = strdup(encoder->raw_output ? detached_filename : cu->filename); if (encoder->filename == NULL) diff --git a/btf_encoder.h b/btf_encoder.h index a65120c..fd5a97f 100644 --- a/btf_encoder.h +++ b/btf_encoder.h @@ -16,7 +16,7 @@ struct btf; struct cu; struct list_head; -struct btf_encoder *btf_encoder__new(struct cu *cu, const char *detached_filename, struct btf *base_btf, bool skip_encoding_vars, bool force, bool gen_floats, bool verbose); +struct btf_encoder *btf_encoder__new(struct cu *cu, const char *detached_filename, struct btf *base_btf, bool skip_encoding_vars, bool force, bool gen_floats, struct btf_encoder *parent, bool verbose); void btf_encoder__delete(struct btf_encoder *encoder); int btf_encoder__encode(struct btf_encoder *encoder); diff --git a/pahole.c b/pahole.c index 6f4f87c..844d502 100644 --- a/pahole.c +++ b/pahole.c @@ -3037,7 +3037,7 @@ static enum load_steal_kind pahole_stealer(struct cu *cu, * create it. */ btf_encoder = btf_encoder__new(cu, detached_btf_filename, conf_load->base_btf, skip_encoding_btf_vars, - btf_encode_force, btf_gen_floats, global_verbose); + btf_encode_force, btf_gen_floats, NULL, global_verbose); if (btf_encoder && thr_data) { struct thread_data *thread = thr_data; @@ -3069,6 +3069,7 @@ static enum load_steal_kind pahole_stealer(struct cu *cu, skip_encoding_btf_vars, btf_encode_force, btf_gen_floats, + btf_encoder, global_verbose); thread->btf = btf_encoder__btf(thread->encoder); } From patchwork Tue Jan 24 13:45:30 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Maguire X-Patchwork-Id: 13114191 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 47B53C25B4E for ; Tue, 24 Jan 2023 14:15:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233828AbjAXOP2 (ORCPT ); Tue, 24 Jan 2023 09:15:28 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54230 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233370AbjAXOP0 (ORCPT ); Tue, 24 Jan 2023 09:15:26 -0500 Received: from mx0b-00069f02.pphosted.com (mx0b-00069f02.pphosted.com [205.220.177.32]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EB85313DE9 for ; Tue, 24 Jan 2023 06:15:09 -0800 (PST) Received: from pps.filterd (m0246630.ppops.net [127.0.0.1]) by mx0b-00069f02.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 30ODI9Hd004727; Tue, 24 Jan 2023 13:45:53 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oracle.com; h=from : to : cc : subject : date : message-id : in-reply-to : references; s=corp-2022-7-12; bh=pMVf2tP5Fw49a4oKAbfRtxdvm3bsSHLaXhAm1lkbaHI=; b=SyWih7bXIR+8hszMdqQRsOTtq03nfBEsmJBS8sS7KtPC5VrZtB//YlLK9ThE8d3UvJSt M9wpxmY0QgLoIGG3gRk+SmL65CYd69L6JH/5D5nHTvFSLnDbk48dhDRKRBr+LSZU45x2 kcitdcdB6nkGvPQtsO0dt0BcPawOG/qV3zQ8piXHZ4vRgSwFo1Qd8c2ofdXE8Qi8n//W P0gpAMS9QvX+1XVPxqiNW2d9wU0R7uIXu2rV90DGFy4BGki6yoVBt9udI8zMrHZRFUiq Pb9BC2pDUBV991Egzg9Pp56qoXns8B9DM0THTi/r4S0g4KhGH9u4wRVH9wD4D4nWniT/ zA== Received: from iadpaimrmta02.imrmtpd1.prodappiadaev1.oraclevcn.com (iadpaimrmta02.appoci.oracle.com [147.154.18.20]) by mx0b-00069f02.pphosted.com (PPS) with ESMTPS id 3n86fcdd3a-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 24 Jan 2023 13:45:52 +0000 Received: from pps.filterd (iadpaimrmta02.imrmtpd1.prodappiadaev1.oraclevcn.com [127.0.0.1]) by iadpaimrmta02.imrmtpd1.prodappiadaev1.oraclevcn.com (8.17.1.5/8.17.1.5) with ESMTP id 30OBmnFu021150; Tue, 24 Jan 2023 13:45:52 GMT Received: from pps.reinject (localhost [127.0.0.1]) by iadpaimrmta02.imrmtpd1.prodappiadaev1.oraclevcn.com (PPS) with ESMTPS id 3n86gbr5rp-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 24 Jan 2023 13:45:52 +0000 Received: from iadpaimrmta02.imrmtpd1.prodappiadaev1.oraclevcn.com (iadpaimrmta02.imrmtpd1.prodappiadaev1.oraclevcn.com [127.0.0.1]) by pps.reinject (8.17.1.5/8.17.1.5) with ESMTP id 30ODjZ3x037951; Tue, 24 Jan 2023 13:45:51 GMT Received: from myrouter.uk.oracle.com (dhcp-10-175-161-98.vpn.oracle.com [10.175.161.98]) by iadpaimrmta02.imrmtpd1.prodappiadaev1.oraclevcn.com (PPS) with ESMTP id 3n86gbr5fj-5; Tue, 24 Jan 2023 13:45:50 +0000 From: Alan Maguire To: acme@kernel.org, yhs@fb.com, ast@kernel.org, olsajiri@gmail.com, timo@incline.eu Cc: daniel@iogearbox.net, andrii@kernel.org, songliubraving@fb.com, john.fastabend@gmail.com, kpsingh@chromium.org, sdf@google.com, haoluo@google.com, martin.lau@kernel.org, bpf@vger.kernel.org, Alan Maguire Subject: [PATCH dwarves 4/5] btf_encoder: represent "."-suffixed optimized functions (".isra.0") in BTF Date: Tue, 24 Jan 2023 13:45:30 +0000 Message-Id: <1674567931-26458-5-git-send-email-alan.maguire@oracle.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1674567931-26458-1-git-send-email-alan.maguire@oracle.com> References: <1674567931-26458-1-git-send-email-alan.maguire@oracle.com> X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.219,Aquarius:18.0.930,Hydra:6.0.562,FMLib:17.11.122.1 definitions=2023-01-23_12,2023-01-24_01,2022-06-22_01 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 phishscore=0 mlxscore=0 spamscore=0 bulkscore=0 mlxlogscore=999 malwarescore=0 adultscore=0 suspectscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2212070000 definitions=main-2301240125 X-Proofpoint-GUID: gW763peLxbNowvdakkkhePAJ66zOK_GW X-Proofpoint-ORIG-GUID: gW763peLxbNowvdakkkhePAJ66zOK_GW Precedence: bulk List-ID: X-Mailing-List: bpf@vger.kernel.org At gcc optimization level O2 or higher, many function optimizations occur such as - constant propagation (.constprop.0); - interprocedural scalar replacement of aggregates, removal of unused parameters and replacement of parameters passed by reference by parameters passed by value (.isra.0) See [1] for details. Currently BTF encoding does not handle such optimized functions that get renamed with a "." suffix such as ".isra.0", ".constprop.0". This is safer because such suffixes can often indicate parameters have been optimized out. Since we can now spot this, support matching to a "." suffix and represent the function in BTF if it does not have optimized-out parameters. First an attempt to match by exact name is made; if that fails we fall back to checking for a "."-suffixed name. The BTF representation will use the original function name "foo" not "foo.isra.0" for consistency with DWARF representation. There is a complication however, and this arises because we process each CU separately and merge BTF when complete. Different CUs may optimize differently, so in one CU, a function may have optimized-out parameters - and thus be ineligible for BTF - while in another it does not have optimized-out parameters - making it eligible for BTF. The NF_HOOK function is an example of this. The only workable solution I could find without disrupting BTF generation parallelism is to create a shared representation of such "."-suffixed functions in the main BTF encoder. A binary tree is used to store function representations. Instead of directly adding a static function with a "." suffix, we postpone their addition until we have processed all CUs. At that point - since we have merged any observations of optimized-out parameters for each function - we know if the candidate function is safe for BTF addition or not. [1] https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html Signed-off-by: Alan Maguire --- btf_encoder.c | 195 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- pahole.c | 4 +- 2 files changed, 191 insertions(+), 8 deletions(-) diff --git a/btf_encoder.c b/btf_encoder.c index 449439f..a86b099 100644 --- a/btf_encoder.c +++ b/btf_encoder.c @@ -21,6 +21,8 @@ #include /* for qsort() and bsearch() */ #include #include +#include /* for tsearch(), tfind() and tdstroy() */ +#include #include #include @@ -34,6 +36,7 @@ struct elf_function { const char *name; bool generated; + size_t prefixlen; }; #define MAX_PERCPU_VAR_CNT 4096 @@ -57,6 +60,9 @@ struct btf_encoder { struct elf_symtab *symtab; uint32_t type_id_off; uint32_t unspecified_type; + void *saved_func_tree; + int saved_func_cnt; + pthread_mutex_t saved_func_lock; bool has_index_type, need_index_type, skip_encoding_vars, @@ -77,9 +83,12 @@ struct btf_encoder { struct elf_function *entries; int allocated; int cnt; + int suffix_cnt; /* number of .isra, .part etc */ } functions; }; +static void btf_encoder__add_saved_funcs(struct btf_encoder *encoder); + void btf_encoders__add(struct list_head *encoders, struct btf_encoder *encoder) { list_add_tail(&encoder->node, encoders); @@ -698,6 +707,11 @@ int32_t btf_encoder__add_encoder(struct btf_encoder *encoder, struct btf_encoder return id; } + /* for multi-threaded case, saved functions are added to each encoder's + * BTF, prior to it being merged with the parent encoder. + */ + btf_encoder__add_saved_funcs(encoder); + return btf__add_btf(encoder->btf, other->btf); } @@ -765,6 +779,76 @@ static int32_t btf_encoder__add_decl_tag(struct btf_encoder *encoder, const char return id; } +static int function__compare(const void *a, const void *b) +{ + struct function *fa = (struct function *)a, *fb = (struct function *)b; + + return strcmp(function__name(fa), function__name(fb)); +} + +struct btf_encoder_state { + struct btf_encoder *encoder; + uint32_t type_id_off; +}; + +/* + * static functions with suffixes are not added yet - we need to + * observe across all CUs to see if the static function has + * optimized parameters in any CU, since in such a case it should + * not be included in the final BTF. NF_HOOK.constprop.0() is + * a case in point - it has optimized-out parameters in some CUs + * but not others. In order to have consistency (since we do not + * know which instance the BTF-specified function signature will + * apply to), we simply skip adding functions which have optimized + * out parameters anywhere. + */ +static int32_t btf_encoder__save_func(struct btf_encoder *encoder, struct function *fn) +{ + struct btf_encoder *parent = encoder->parent ? encoder->parent : encoder; + const char *name = function__name(fn); + struct function **nodep; + int ret = 0; + + pthread_mutex_lock(&parent->saved_func_lock); + nodep = tsearch(fn, &parent->saved_func_tree, function__compare); + if (nodep == NULL) { + fprintf(stderr, "error: out of memory adding local function '%s'\n", + name); + ret = -1; + goto out; + } + /* If we find an existing entry, we want to merge observations + * across both functions, checking that the "seen optimized-out + * parameters" status is reflected in our tree entry. + * If the entry is new, record encoder state required + * to add the local function later (encoder + type_id_off) + * such that we can add the function later. + */ + if (*nodep != fn) { + (*nodep)->proto.optimized_parms |= fn->proto.optimized_parms; + } else { + struct btf_encoder_state *state = zalloc(sizeof(*state)); + + if (state == NULL) { + fprintf(stderr, "error: out of memory adding local function '%s'\n", + name); + ret = -1; + goto out; + } + state->encoder = encoder; + state->type_id_off = encoder->type_id_off; + fn->priv = state; + encoder->saved_func_cnt++; + if (encoder->verbose) + printf("added local function '%s'%s\n", name, + fn->proto.optimized_parms ? + ", optimized-out params" : ""); + } +out: + pthread_mutex_unlock(&parent->saved_func_lock); + return ret; +} + static int32_t btf_encoder__add_func(struct btf_encoder *encoder, struct function *fn) { int btf_fnproto_id, btf_fn_id, tag_type_id; @@ -789,6 +873,55 @@ static int32_t btf_encoder__add_func(struct btf_encoder *encoder, struct functio return 0; } +/* visit each node once, adding associated function */ +static void btf_encoder__add_saved_func(const void *nodep, const VISIT which, + const int depth __maybe_unused) +{ + struct btf_encoder_state *state; + struct btf_encoder *encoder; + struct function *fn = NULL; + + switch (which) { + case preorder: + case endorder: + break; + case postorder: + case leaf: + fn = *((struct function **)nodep); + break; + } + if (!fn || !fn->priv) + return; + state = (struct btf_encoder_state *)fn->priv; + encoder = state->encoder; + encoder->type_id_off = state->type_id_off; + /* we can safely free encoder state since we visit each node once */ + free(fn->priv); + fn->priv = NULL; + if (fn->proto.optimized_parms) { + if (encoder->verbose) + printf("skipping addition of '%s' due to optimized-out parameters\n", + function__name(fn)); + } else { + btf_encoder__add_func(encoder, fn); + } +} + +void saved_func__free(void *nodep __maybe_unused) +{ + /* nothing to do, functions are freed when the cu is. */ +} + +static void btf_encoder__add_saved_funcs(struct btf_encoder *encoder) +{ + if (!encoder->parent && encoder->saved_func_tree) { + encoder->type_id_off = 0; + twalk(encoder->saved_func_tree, btf_encoder__add_saved_func); + tdestroy(encoder->saved_func_tree, saved_func__free); + encoder->saved_func_tree = NULL; + } +} + /* * This corresponds to the same macro defined in * include/linux/kallsyms.h @@ -800,6 +933,12 @@ static int functions_cmp(const void *_a, const void *_b) const struct elf_function *a = _a; const struct elf_function *b = _b; + /* if search key allows prefix match, verify target has matching + * prefix len and prefix matches. + */ + if (a->prefixlen && a->prefixlen == b->prefixlen) + return strncmp(a->name, b->name, b->prefixlen); + return strcmp(a->name, b->name); } @@ -832,14 +971,21 @@ static int btf_encoder__collect_function(struct btf_encoder *encoder, GElf_Sym * } encoder->functions.entries[encoder->functions.cnt].name = name; + if (strchr(name, '.')) { + const char *suffix = strchr(name, '.'); + + encoder->functions.suffix_cnt++; + encoder->functions.entries[encoder->functions.cnt].prefixlen = suffix - name; + } encoder->functions.entries[encoder->functions.cnt].generated = false; encoder->functions.cnt++; return 0; } -static struct elf_function *btf_encoder__find_function(const struct btf_encoder *encoder, const char *name) +static struct elf_function *btf_encoder__find_function(const struct btf_encoder *encoder, const char *name, + size_t prefixlen) { - struct elf_function key = { .name = name }; + struct elf_function key = { .name = name, .prefixlen = prefixlen }; return bsearch(&key, encoder->functions.entries, encoder->functions.cnt, sizeof(key), functions_cmp); } @@ -1171,6 +1317,9 @@ int btf_encoder__encode(struct btf_encoder *encoder) if (gobuffer__size(&encoder->percpu_secinfo) != 0) btf_encoder__add_datasec(encoder, PERCPU_SECTION); + /* for single-threaded case, saved functions are added here */ + btf_encoder__add_saved_funcs(encoder); + /* Empty file, nothing to do, so... done! */ if (btf__type_cnt(encoder->btf) == 1) return 0; @@ -1456,6 +1605,7 @@ struct btf_encoder *btf_encoder__new(struct cu *cu, const char *detached_filenam encoder->has_index_type = false; encoder->need_index_type = false; encoder->array_index_id = 0; + pthread_mutex_init(&encoder->saved_func_lock, NULL); GElf_Ehdr ehdr; @@ -1614,6 +1764,7 @@ int btf_encoder__encode_cu(struct btf_encoder *encoder, struct cu *cu, struct co } cu__for_each_function(cu, core_id, fn) { + bool save = false; /* * Skip functions that: @@ -1634,22 +1785,54 @@ int btf_encoder__encode_cu(struct btf_encoder *encoder, struct cu *cu, struct co if (!name) continue; - func = btf_encoder__find_function(encoder, name); - if (!func || func->generated) + /* prefer exact name function match... */ + func = btf_encoder__find_function(encoder, name, 0); + if (func) { + if (func->generated) + continue; + func->generated = true; + } else if (encoder->functions.suffix_cnt) { + /* falling back to name.isra.0 match if no exact + * match is found; only bother if we found any + * .suffix function names. The function + * will be saved and added once we ensure + * it does not have optimized-out parameters + * in any cu. + */ + func = btf_encoder__find_function(encoder, name, + strlen(name)); + if (func) { + save = true; + if (encoder->verbose) + printf("matched function '%s' with '%s'%s\n", + name, func->name, + fn->proto.optimized_parms ? + ", has optimized-out parameters" : ""); + } + } + if (!func) continue; - func->generated = true; } else { if (!fn->external) continue; } - err = btf_encoder__add_func(encoder, fn); + if (save) + err = btf_encoder__save_func(encoder, fn); + else + err = btf_encoder__add_func(encoder, fn); if (err) goto out; } if (!encoder->skip_encoding_vars) err = btf_encoder__encode_cu_variables(encoder); + + /* It is only safe to delete this CU if we have not stashed any local + * functions for later addition. + */ + if (!err) + err = encoder->saved_func_cnt > 0 ? LSK__KEEPIT : LSK__DELETE; out: encoder->cu = NULL; return err; diff --git a/pahole.c b/pahole.c index 844d502..62d54ec 100644 --- a/pahole.c +++ b/pahole.c @@ -3078,11 +3078,11 @@ static enum load_steal_kind pahole_stealer(struct cu *cu, encoder = btf_encoder; } - if (btf_encoder__encode_cu(encoder, cu, conf_load)) { + ret = btf_encoder__encode_cu(encoder, cu, conf_load); + if (ret < 0) { fprintf(stderr, "Encountered error while encoding BTF.\n"); exit(1); } - ret = LSK__DELETE; out_btf: return ret; } From patchwork Tue Jan 24 13:45:31 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Maguire X-Patchwork-Id: 13114240 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 51E79C38142 for ; Tue, 24 Jan 2023 14:23:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234797AbjAXOXz (ORCPT ); Tue, 24 Jan 2023 09:23:55 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36236 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234831AbjAXOXy (ORCPT ); Tue, 24 Jan 2023 09:23:54 -0500 Received: from mx0a-00069f02.pphosted.com (mx0a-00069f02.pphosted.com [205.220.165.32]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9EC4C37F13 for ; Tue, 24 Jan 2023 06:23:51 -0800 (PST) Received: from pps.filterd (m0246627.ppops.net [127.0.0.1]) by mx0b-00069f02.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 30ODI2tq026732; Tue, 24 Jan 2023 13:45:57 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oracle.com; h=from : to : cc : subject : date : message-id : in-reply-to : references; s=corp-2022-7-12; bh=kiXRasoYTr/qWeDfho2jTnTv9ttAwukbNpppe2PGAls=; b=YEWEnyYr6UI/9y99G2MdY6cXAK1Ft/xzMVToCkCq3kQ3U5kkXaZr6ZSDRRGayGBw7b8y lts3QdVYvzbkj9Q52hjV/7CudkDxjj0sMQWEuLapCdoa9htLQCwrs68XblJtx7YHW291 qWdylogp3ku/kwGbMVc3DuZ43WTOqgUB65sm8Cq6GnNaxu95ygw2Db6fAaJTShKIClaK W3ahnpbDKIUpkX/Nl4XO0h8phU0t5m3IlcJNELvl+qwqaOHcEFwELEjrRDY8b+kLPqj9 7B0BYE0vbKT9aiOSObZMlSUUfKItl0ZQ0ESSdcPDxIv1Vr5rAfcAW/fb/Rsy1Wj8ihzx Tg== Received: from iadpaimrmta02.imrmtpd1.prodappiadaev1.oraclevcn.com (iadpaimrmta02.appoci.oracle.com [147.154.18.20]) by mx0b-00069f02.pphosted.com (PPS) with ESMTPS id 3n86n0wbtx-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 24 Jan 2023 13:45:57 +0000 Received: from pps.filterd (iadpaimrmta02.imrmtpd1.prodappiadaev1.oraclevcn.com [127.0.0.1]) by iadpaimrmta02.imrmtpd1.prodappiadaev1.oraclevcn.com (8.17.1.5/8.17.1.5) with ESMTP id 30OBmpLN021339; Tue, 24 Jan 2023 13:45:56 GMT Received: from pps.reinject (localhost [127.0.0.1]) by iadpaimrmta02.imrmtpd1.prodappiadaev1.oraclevcn.com (PPS) with ESMTPS id 3n86gbr5t5-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 24 Jan 2023 13:45:56 +0000 Received: from iadpaimrmta02.imrmtpd1.prodappiadaev1.oraclevcn.com (iadpaimrmta02.imrmtpd1.prodappiadaev1.oraclevcn.com [127.0.0.1]) by pps.reinject (8.17.1.5/8.17.1.5) with ESMTP id 30ODjZ41037951; Tue, 24 Jan 2023 13:45:55 GMT Received: from myrouter.uk.oracle.com (dhcp-10-175-161-98.vpn.oracle.com [10.175.161.98]) by iadpaimrmta02.imrmtpd1.prodappiadaev1.oraclevcn.com (PPS) with ESMTP id 3n86gbr5fj-6; Tue, 24 Jan 2023 13:45:55 +0000 From: Alan Maguire To: acme@kernel.org, yhs@fb.com, ast@kernel.org, olsajiri@gmail.com, timo@incline.eu Cc: daniel@iogearbox.net, andrii@kernel.org, songliubraving@fb.com, john.fastabend@gmail.com, kpsingh@chromium.org, sdf@google.com, haoluo@google.com, martin.lau@kernel.org, bpf@vger.kernel.org, Alan Maguire Subject: [PATCH dwarves 5/5] btf_encoder: skip BTF encoding of static functions with inconsistent prototypes Date: Tue, 24 Jan 2023 13:45:31 +0000 Message-Id: <1674567931-26458-6-git-send-email-alan.maguire@oracle.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1674567931-26458-1-git-send-email-alan.maguire@oracle.com> References: <1674567931-26458-1-git-send-email-alan.maguire@oracle.com> X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.219,Aquarius:18.0.930,Hydra:6.0.562,FMLib:17.11.122.1 definitions=2023-01-23_12,2023-01-24_01,2022-06-22_01 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 phishscore=0 mlxscore=0 spamscore=0 bulkscore=0 mlxlogscore=999 malwarescore=0 adultscore=0 suspectscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2212070000 definitions=main-2301240125 X-Proofpoint-GUID: uuol-4J1kywZ8jPqPHYC8FPTvcuo6y2t X-Proofpoint-ORIG-GUID: uuol-4J1kywZ8jPqPHYC8FPTvcuo6y2t Precedence: bulk List-ID: X-Mailing-List: bpf@vger.kernel.org Two static functions in different CUs can share the same name but have different function prototypes. In such a case BTF has no way currently to map which function description matches which function site, so it is safer to eliminate such duplicates by using the same global matching procedure used to identify functions with optimized-out parameters. Protoype checking is done by comparing parameter numbers and then names. Signed-off-by: Alan Maguire --- btf_encoder.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++++---------- dwarves.h | 1 + 2 files changed, 78 insertions(+), 16 deletions(-) diff --git a/btf_encoder.c b/btf_encoder.c index a86b099..e0acd29 100644 --- a/btf_encoder.c +++ b/btf_encoder.c @@ -786,21 +786,39 @@ static int function__compare(const void *a, const void *b) return strcmp(function__name(fa), function__name(fb)); } +#define BTF_ENCODER_MAX_PARAMETERS 10 + struct btf_encoder_state { struct btf_encoder *encoder; uint32_t type_id_off; + bool got_parameter_names; + const char *parameter_names[BTF_ENCODER_MAX_PARAMETERS]; }; +void parameter_names__get(struct ftype *ftype, size_t nr_parameters, const char **parameter_names) +{ + struct parameter *parameter; + int i = 0; + + ftype__for_each_parameter(ftype, parameter) { + if (i >= nr_parameters) + break; + parameter_names[i++] = parameter__name(parameter); + } +} + /* - * static functions with suffixes are not added yet - we need to - * observe across all CUs to see if the static function has - * optimized parameters in any CU, since in such a case it should - * not be included in the final BTF. NF_HOOK.constprop.0() is - * a case in point - it has optimized-out parameters in some CUs - * but not others. In order to have consistency (since we do not - * know which instance the BTF-specified function signature will - * apply to), we simply skip adding functions which have optimized - * out parameters anywhere. + * static functions are not added yet - we need to observe across + * all CUs to see if the static function has optimized-out parameters + * in any CU, or inconsistent function prototypes; in either case, + * it should not be included in the final BTF. For the optimized-out + * case, NF_HOOK.constprop.0() is a case in point - it has optimized-out + * parameters in some CUs but not others. Similarly, a static function + * like enable_store() has inconsistent function prototypes in different + * CUs so should not be present. In order to have consistency (since + * we do not know which instance the BTF-specified function signature + * will apply to), we simply skip adding functions which have + * optimized-out parameters/inconsistent function prototypes anywhere. */ static int32_t btf_encoder__save_func(struct btf_encoder *encoder, struct function *fn) { @@ -819,13 +837,51 @@ static int32_t btf_encoder__save_func(struct btf_encoder *encoder, struct functi } /* If we find an existing entry, we want to merge observations * across both functions, checking that the "seen optimized-out - * parameters" status is reflected in our tree entry. + * parameters"/inconsistent proto status is reflected in tree entry. * If the entry is new, record encoder state required * to add the local function later (encoder + type_id_off) - * such that we can add the function later. + * such that we can add the function later. Parameter names are + * also stored in state to speed up multiple static function + * comparisons. */ if (*nodep != fn) { - (*nodep)->proto.optimized_parms |= fn->proto.optimized_parms; + struct function *ofn = *nodep; + + ofn->proto.optimized_parms |= fn->proto.optimized_parms; + /* compare parameters to see if signatures match */ + + if (ofn->proto.inconsistent_proto) + goto out; + + if (ofn->proto.nr_parms != fn->proto.nr_parms) { + ofn->proto.inconsistent_proto = 1; + goto out; + } + if (ofn->proto.nr_parms > 0) { + struct btf_encoder_state *state = ofn->priv; + const char *parameter_names[BTF_ENCODER_MAX_PARAMETERS]; + int i; + + if (!state->got_parameter_names) { + parameter_names__get(&ofn->proto, BTF_ENCODER_MAX_PARAMETERS, + state->parameter_names); + state->got_parameter_names = true; + } + parameter_names__get(&fn->proto, BTF_ENCODER_MAX_PARAMETERS, + parameter_names); + for (i = 0; i < ofn->proto.nr_parms; i++) { + if (!state->parameter_names[i]) { + if (!parameter_names[i]) + continue; + } else if (parameter_names[i]) { + if (strcmp(state->parameter_names[i], + parameter_names[i]) == 0) + continue; + } + ofn->proto.inconsistent_proto = 1; + goto out; + } + } } else { struct btf_encoder_state *state = zalloc(sizeof(*state)); @@ -898,10 +954,12 @@ static void btf_encoder__add_saved_func(const void *nodep, const VISIT which, /* we can safely free encoder state since we visit each node once */ free(fn->priv); fn->priv = NULL; - if (fn->proto.optimized_parms) { + if (fn->proto.optimized_parms || fn->proto.inconsistent_proto) { if (encoder->verbose) - printf("skipping addition of '%s' due to optimized-out parameters\n", - function__name(fn)); + printf("skipping addition of '%s' due to %s\n", + function__name(fn), + fn->proto.optimized_parms ? "optimized-out parameters" : + "multiple inconsistent function prototypes"); } else { btf_encoder__add_func(encoder, fn); } @@ -1775,6 +1833,8 @@ int btf_encoder__encode_cu(struct btf_encoder *encoder, struct cu *cu, struct co */ if (fn->declaration) continue; + if (!fn->external) + save = true; if (!ftype__has_arg_names(&fn->proto)) continue; if (encoder->functions.cnt) { @@ -1790,7 +1850,8 @@ int btf_encoder__encode_cu(struct btf_encoder *encoder, struct cu *cu, struct co if (func) { if (func->generated) continue; - func->generated = true; + if (!save) + func->generated = true; } else if (encoder->functions.suffix_cnt) { /* falling back to name.isra.0 match if no exact * match is found; only bother if we found any diff --git a/dwarves.h b/dwarves.h index 1ad1b3b..9b80262 100644 --- a/dwarves.h +++ b/dwarves.h @@ -830,6 +830,7 @@ struct ftype { uint16_t nr_parms; uint8_t unspec_parms:1; /* just one bit is needed */ uint8_t optimized_parms:1; + uint8_t inconsistent_proto:1; }; static inline struct ftype *tag__ftype(const struct tag *tag)