From nobody Mon Dec 1 23:33:39 2025 Received: from out-174.mta0.migadu.com (out-174.mta0.migadu.com [91.218.175.174]) (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 7DE9F2F5A18 for ; Wed, 26 Nov 2025 01:29:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.174 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764120575; cv=none; b=G9cYBxTsHKYrejqkgfqoB9XdtyuVREcPwNPCKtVZqJx3wxG7KLfq3xefhqVPpHn9T7JBrIVTa0LmkMFzpvX90l1pm2crbJFz9Zf4qQlmlc+4SGK+U85Oj13GSQxeOVVyCpPm0gwFCzQBTF6H/dOJJeS0mJ3K9vChHYTaxl03tfM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764120575; c=relaxed/simple; bh=0vPBXFkWZ/MzGH4tjLWdF3Fl9qTxFcaK/Jzqj1oLtgA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=RZMYVCKdABdEp/BMymMH/ydDOZtp1C2zuHZH/aH0dqxHaK9u+UxplMzu3edPUKGUfFbFpdi6jJLrXDaM50NJDkeUuv863HxaFPea1asoijIEhO5brfcbWCQupdQbdPy1NE2ivvAmndD+C0TKow6MRMhr5q8OKSaKYYKmefXtzFA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=MCaqU0Cu; arc=none smtp.client-ip=91.218.175.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="MCaqU0Cu" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1764120570; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=4xzNaBNG8jGgwOPkttRYQPmkjzfbEIAH53D/pi2LZps=; b=MCaqU0Cup+kk5iU+XTEsWgK2C5cR4gPaOFtdx7Tp6e4LOtTwFJH/CidUDGTYNCdhUukKqj TATIZPGq9cGcvF0aIY7FVyBVbv7obvfE5ITssPGkG6V4gEzrjQL+j3lNlnbA/FBEcggnUI T63SBlPCsmMUKB+NnyIg8gRmXyTy7ms= From: Ihor Solodrai To: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Nathan Chancellor , Nicolas Schier , Nick Desaulniers , Bill Wendling , Justin Stitt Cc: bpf@vger.kernel.org, dwarves@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kbuild@vger.kernel.org, Alan Maguire , Donglin Peng Subject: [PATCH bpf-next v1 1/4] resolve_btfids: rename object btf field to btf_path Date: Tue, 25 Nov 2025 17:26:53 -0800 Message-ID: <20251126012656.3546071-2-ihor.solodrai@linux.dev> In-Reply-To: <20251126012656.3546071-1-ihor.solodrai@linux.dev> References: <20251126012656.3546071-1-ihor.solodrai@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" Rename the member of `struct object` holding the path to BTF data if provided via --btf arg. `btf_path` is less ambiguous. Signed-off-by: Ihor Solodrai --- tools/bpf/resolve_btfids/main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/bpf/resolve_btfids/main.c b/tools/bpf/resolve_btfids/mai= n.c index d47191c6e55e..d2762487ce5f 100644 --- a/tools/bpf/resolve_btfids/main.c +++ b/tools/bpf/resolve_btfids/main.c @@ -113,7 +113,7 @@ struct btf_id { =20 struct object { const char *path; - const char *btf; + const char *btf_path; const char *base_btf_path; =20 struct { @@ -550,11 +550,11 @@ static int symbols_resolve(struct object *obj) } } =20 - btf =3D btf__parse_split(obj->btf ?: obj->path, base_btf); + btf =3D btf__parse_split(obj->btf_path ?: obj->path, base_btf); err =3D libbpf_get_error(btf); if (err) { pr_err("FAILED: load BTF from %s: %s\n", - obj->btf ?: obj->path, strerror(-err)); + obj->btf_path ?: obj->path, strerror(-err)); goto out; } =20 @@ -790,7 +790,7 @@ int main(int argc, const char **argv) struct option btfid_options[] =3D { OPT_INCR('v', "verbose", &verbose, "be more verbose (show errors, etc)"), - OPT_STRING(0, "btf", &obj.btf, "BTF data", + OPT_STRING(0, "btf", &obj.btf_path, "BTF data", "BTF data"), OPT_STRING('b', "btf_base", &obj.base_btf_path, "file", "path of file providing base BTF"), --=20 2.52.0 From nobody Mon Dec 1 23:33:39 2025 Received: from out-181.mta0.migadu.com (out-181.mta0.migadu.com [91.218.175.181]) (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 F2D662F7443 for ; Wed, 26 Nov 2025 01:29:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.181 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764120580; cv=none; b=BY3gkVFaFWJZxMrpZwbMQHgwfaJjo+wpxGcD/91YED1humrKl1eHwCsh/yDtEDPYP2ul44PLl6wUSTVkQ1tpRyWyXxmak664dEiB4NEB8GofwQ4QenexVMuYL2l4vrtwqhiAMxiYMKnFsSZlw8URlMn+efTe0QhSpU/uwn2UMf4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764120580; c=relaxed/simple; bh=aXv/pih24yggz6hes7FfJ4CF5Nhjv1blxuz2JItVklU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=OJyYEnsGtjenLE+aGdu7MBVkjLEMNHIbbUIPkXauM66cD2cNqazjP3wGDTImjGSCT9O2GFy9cDpfCDuBToEanidChwkJgBwx6SfCp+mNNFUbuFzgpanDz4US3+aMI5771zkwHgGosDwQ6mh3LklQYCbs4IbObC38HSMHJJsLiUA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=SrTIFUVB; arc=none smtp.client-ip=91.218.175.181 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="SrTIFUVB" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1764120577; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ncfgnkJo0FOQMsiCWv0mDQ10nQdwXB48HeO+ohRsxaQ=; b=SrTIFUVBrpFAmd98XMWC17KblJ3e7muWCuc+Or/BXUEkR6JHurnYCxGgznBKd6k1Y1goFG eSINmtcq8EG3lfVrbQ9T6efABDn33zVhzp/7cKiKHRKQfULWuLxvoPCZPk6/qQ2mimxhDw cA7fnESy8kLMq7BHs5cmoEeU2T3095k= From: Ihor Solodrai To: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Nathan Chancellor , Nicolas Schier , Nick Desaulniers , Bill Wendling , Justin Stitt Cc: bpf@vger.kernel.org, dwarves@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kbuild@vger.kernel.org, Alan Maguire , Donglin Peng Subject: [PATCH bpf-next v1 2/4] resolve_btfids: factor out load_btf() Date: Tue, 25 Nov 2025 17:26:54 -0800 Message-ID: <20251126012656.3546071-3-ihor.solodrai@linux.dev> In-Reply-To: <20251126012656.3546071-1-ihor.solodrai@linux.dev> References: <20251126012656.3546071-1-ihor.solodrai@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" Increase the lifetime of parsed BTF in resolve_btfids by factoring load_btf() routine out of symbols_resolve() and storing the base_btf and btf pointers in the struct object. Signed-off-by: Ihor Solodrai --- tools/bpf/resolve_btfids/main.c | 47 ++++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/tools/bpf/resolve_btfids/main.c b/tools/bpf/resolve_btfids/mai= n.c index d2762487ce5f..b7b44e72e765 100644 --- a/tools/bpf/resolve_btfids/main.c +++ b/tools/bpf/resolve_btfids/main.c @@ -116,6 +116,9 @@ struct object { const char *btf_path; const char *base_btf_path; =20 + struct btf *btf; + struct btf *base_btf; + struct { int fd; Elf *elf; @@ -529,16 +532,10 @@ static int symbols_collect(struct object *obj) return 0; } =20 -static int symbols_resolve(struct object *obj) +static int load_btf(struct object *obj) { - int nr_typedefs =3D obj->nr_typedefs; - int nr_structs =3D obj->nr_structs; - int nr_unions =3D obj->nr_unions; - int nr_funcs =3D obj->nr_funcs; - struct btf *base_btf =3D NULL; - int err, type_id; - struct btf *btf; - __u32 nr_types; + struct btf *base_btf =3D NULL, *btf =3D NULL; + int err; =20 if (obj->base_btf_path) { base_btf =3D btf__parse(obj->base_btf_path, NULL); @@ -546,7 +543,7 @@ static int symbols_resolve(struct object *obj) if (err) { pr_err("FAILED: load base BTF from %s: %s\n", obj->base_btf_path, strerror(-err)); - return -1; + goto out_err; } } =20 @@ -555,9 +552,30 @@ static int symbols_resolve(struct object *obj) if (err) { pr_err("FAILED: load BTF from %s: %s\n", obj->btf_path ?: obj->path, strerror(-err)); - goto out; + goto out_err; } =20 + obj->base_btf =3D base_btf; + obj->btf =3D btf; + + return 0; + +out_err: + btf__free(base_btf); + btf__free(btf); + return err; +} + +static int symbols_resolve(struct object *obj) +{ + int nr_typedefs =3D obj->nr_typedefs; + int nr_structs =3D obj->nr_structs; + int nr_unions =3D obj->nr_unions; + int nr_funcs =3D obj->nr_funcs; + struct btf *btf =3D obj->btf; + int err, type_id; + __u32 nr_types; + err =3D -1; nr_types =3D btf__type_cnt(btf); =20 @@ -615,8 +633,6 @@ static int symbols_resolve(struct object *obj) =20 err =3D 0; out: - btf__free(base_btf); - btf__free(btf); return err; } =20 @@ -824,6 +840,9 @@ int main(int argc, const char **argv) if (symbols_collect(&obj)) goto out; =20 + if (load_btf(&obj)) + goto out; + if (symbols_resolve(&obj)) goto out; =20 @@ -833,6 +852,8 @@ int main(int argc, const char **argv) if (!(fatal_warnings && warnings)) err =3D 0; out: + btf__free(obj.base_btf); + btf__free(obj.btf); if (obj.efile.elf) { elf_end(obj.efile.elf); close(obj.efile.fd); --=20 2.52.0 From nobody Mon Dec 1 23:33:39 2025 Received: from out-170.mta0.migadu.com (out-170.mta0.migadu.com [91.218.175.170]) (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 544CF2FB602 for ; Wed, 26 Nov 2025 01:29:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.170 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764120587; cv=none; b=iAdNq1q28MkY67vdr0sdDrDQHnXzNyAmdyRqdqGEEC4wZbtWn2BBH5JJg4yos8j8VPwndX0KPLfo5WulEHUzUAp9nR8xV+y5dsb7ahpqXiIU/Xs7Hjhq/mCqGWFXKdItw9EEBPaEskm84nz31mbSbF3mMI2CKphUx2azU3+DESE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764120587; c=relaxed/simple; bh=xCvFs1xbcVN6h+Vy2tQsGp0ZQAuYsMF+spiFOaf/Irg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=U/A/G+e/uRv7f2hTOr+AfhKZQorm/ryw/cCoTLsCQ1zyCp6PTYF5Fpl1yaxXOLE+UWsfFHLhI4HRQDBdX/svT1ifewzNojodDDlJdU/x+yB5ymIhAddqjM10ivo+zzmhXRY9ArQ8Z2BOBN4X/GwVnx4Kj6yhwGeNRCMBqKt3khM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=ozOqoMmw; arc=none smtp.client-ip=91.218.175.170 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="ozOqoMmw" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1764120583; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=8OxpVlu97uQOGmIsABXF9JpduqMEidWW+QhnLTm9npg=; b=ozOqoMmwYEy7W1BpWVntj+K2UBfM18cylAmrgcVy5bN2TCF+A6jmJZ/GfdoJ7MSxh5s7QG Mh3Ssvs5JU9yzDE+uTsJj1SHogTx+3YHwb39wkmPpJTn0cSEzn0+VpTZT91ip94Lo6GgMl ipeh+NywOo7JuYy7x6MWBJIYgxG2etE= From: Ihor Solodrai To: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Nathan Chancellor , Nicolas Schier , Nick Desaulniers , Bill Wendling , Justin Stitt Cc: bpf@vger.kernel.org, dwarves@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kbuild@vger.kernel.org, Alan Maguire , Donglin Peng Subject: [PATCH bpf-next v1 3/4] resolve_btfids: introduce enum btf_id_kind Date: Tue, 25 Nov 2025 17:26:55 -0800 Message-ID: <20251126012656.3546071-4-ihor.solodrai@linux.dev> In-Reply-To: <20251126012656.3546071-1-ihor.solodrai@linux.dev> References: <20251126012656.3546071-1-ihor.solodrai@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" Instead of using multiple flags, make struct btf_id tagged with an enum value indicating its kind in the context of resolve_btfids. Signed-off-by: Ihor Solodrai --- tools/bpf/resolve_btfids/main.c | 61 ++++++++++++++++++++++----------- 1 file changed, 41 insertions(+), 20 deletions(-) diff --git a/tools/bpf/resolve_btfids/main.c b/tools/bpf/resolve_btfids/mai= n.c index b7b44e72e765..7f5a9f7dde7f 100644 --- a/tools/bpf/resolve_btfids/main.c +++ b/tools/bpf/resolve_btfids/main.c @@ -98,6 +98,13 @@ # error "Unknown machine endianness!" #endif =20 +enum btf_id_kind { + BTF_ID_KIND_NONE, + BTF_ID_KIND_SYM, + BTF_ID_KIND_SET, + BTF_ID_KIND_SET8 +}; + struct btf_id { struct rb_node rb_node; char *name; @@ -105,9 +112,8 @@ struct btf_id { int id; int cnt; }; - int addr_cnt; - bool is_set; - bool is_set8; + enum btf_id_kind kind:8; + int addr_cnt:8; Elf64_Addr addr[ADDR_CNT]; }; =20 @@ -260,26 +266,33 @@ static char *get_id(const char *prefix_end) return id; } =20 -static struct btf_id *add_set(struct object *obj, char *name, bool is_set8) +static struct btf_id *add_set(struct object *obj, char *name, enum btf_id_= kind kind) { /* * __BTF_ID__set__name * name =3D ^ * id =3D ^ */ - char *id =3D name + (is_set8 ? sizeof(BTF_SET8 "__") : sizeof(BTF_SET "__= ")) - 1; + int prefixlen =3D kind =3D=3D BTF_ID_KIND_SET8 ? sizeof(BTF_SET8 "__") : = sizeof(BTF_SET "__"); + char *id =3D name + prefixlen - 1; int len =3D strlen(name); + struct btf_id *btf_id; =20 if (id >=3D name + len) { pr_err("FAILED to parse set name: %s\n", name); return NULL; } =20 - return btf_id__add(&obj->sets, id, true); + btf_id =3D btf_id__add(&obj->sets, id, true); + if (btf_id) + btf_id->kind =3D kind; + + return btf_id; } =20 static struct btf_id *add_symbol(struct rb_root *root, char *name, size_t = size) { + struct btf_id *btf_id; char *id; =20 id =3D get_id(name + size); @@ -288,7 +301,10 @@ static struct btf_id *add_symbol(struct rb_root *root,= char *name, size_t size) return NULL; } =20 - return btf_id__add(root, id, false); + btf_id =3D btf_id__add(root, id, false); + btf_id->kind =3D BTF_ID_KIND_SYM; + + return btf_id; } =20 /* Older libelf.h and glibc elf.h might not yet define the ELF compression= types. */ @@ -491,28 +507,24 @@ static int symbols_collect(struct object *obj) id =3D add_symbol(&obj->funcs, prefix, sizeof(BTF_FUNC) - 1); /* set8 */ } else if (!strncmp(prefix, BTF_SET8, sizeof(BTF_SET8) - 1)) { - id =3D add_set(obj, prefix, true); + id =3D add_set(obj, prefix, BTF_ID_KIND_SET8); /* * SET8 objects store list's count, which is encoded * in symbol's size, together with 'cnt' field hence * that - 1. */ - if (id) { + if (id) id->cnt =3D sym.st_size / sizeof(uint64_t) - 1; - id->is_set8 =3D true; - } /* set */ } else if (!strncmp(prefix, BTF_SET, sizeof(BTF_SET) - 1)) { - id =3D add_set(obj, prefix, false); + id =3D add_set(obj, prefix, BTF_ID_KIND_SET); /* * SET objects store list's count, which is encoded * in symbol's size, together with 'cnt' field hence * that - 1. */ - if (id) { + if (id) id->cnt =3D sym.st_size / sizeof(int) - 1; - id->is_set =3D true; - } } else { pr_err("FAILED unsupported prefix %s\n", prefix); return -1; @@ -643,7 +655,7 @@ static int id_patch(struct object *obj, struct btf_id *= id) int i; =20 /* For set, set8, id->id may be 0 */ - if (!id->id && !id->is_set && !id->is_set8) { + if (!id->id && id->kind =3D=3D BTF_ID_KIND_SYM) { pr_err("WARN: resolve_btfids: unresolved symbol %s\n", id->name); warnings++; } @@ -696,6 +708,7 @@ static int sets_patch(struct object *obj) { Elf_Data *data =3D obj->efile.idlist; struct rb_node *next; + int cnt; =20 next =3D rb_first(&obj->sets); while (next) { @@ -715,11 +728,15 @@ static int sets_patch(struct object *obj) return -1; } =20 - if (id->is_set) { + switch (id->kind) { + case BTF_ID_KIND_SET: set =3D data->d_buf + off; + cnt =3D set->cnt; qsort(set->ids, set->cnt, sizeof(set->ids[0]), cmp_id); - } else { + break; + case BTF_ID_KIND_SET8: set8 =3D data->d_buf + off; + cnt =3D set8->cnt; /* * Make sure id is at the beginning of the pairs * struct, otherwise the below qsort would not work. @@ -744,10 +761,14 @@ static int sets_patch(struct object *obj) bswap_32(set8->pairs[i].flags); } } + break; + case BTF_ID_KIND_SYM: + default: + pr_err("Unexpected btf_id_kind %d for set '%s'\n", id->kind, id->name); + return -1; } =20 - pr_debug("sorting addr %5lu: cnt %6d [%s]\n", - off, id->is_set ? set->cnt : set8->cnt, id->name); + pr_debug("sorting addr %5lu: cnt %6d [%s]\n", off, cnt, id->name); =20 next =3D rb_next(next); } --=20 2.52.0 From nobody Mon Dec 1 23:33:39 2025 Received: from out-179.mta0.migadu.com (out-179.mta0.migadu.com [91.218.175.179]) (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 0089C2F83AC; Wed, 26 Nov 2025 01:29:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.179 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764120594; cv=none; b=CQYe5s+/k60Rr03Y3CDv2gXEwRsfFc+H9nxgvTpQw9ENgXoCU+M2GYt8ujBCYS3JG9RhKLB572wloAZ2TJv9X1id2p7Bi6E5+8UBkU7wu5rTZvf2V5Uui7y07GCZ0lyxs0/KQxr5fILA3HryK7VgWptLfyUSh6/rRRsyuIsKt90= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764120594; c=relaxed/simple; bh=YwgShm4j2Q5W1IYLLkNrx9t+LBeGXChj+nW6RyJ2dsI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ZTVQnLYD2/mRH5K8d3qz4UOwKPcq8zJKTGci8Kj7PIfdPJCNBM4juRXf+wrG5g2ZuW6drfXraJoZUvIIubhksM1IfJQVMlDjMLsEElAhe+pUKczRaEF8Gy8DhdAcIFYpnP/S7pg0+g5UiCZraBKuo9HUOPiJLPRdx6VTqu7fmGY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=dDTpMGSq; arc=none smtp.client-ip=91.218.175.179 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="dDTpMGSq" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1764120589; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=McMjrjL60SjDk8vrsOfgt5kcZdJJBubZnhh/BKmREoY=; b=dDTpMGSqh4cRfHLt2DzNnb6TMVzcoEzUr48cUyGDQFXH0BEyZ1CDN4/X4fII08QX4MyxLa j74m30W2b8RF6chq728f8xBuFowRS6oD3skoOc00UdObpTdzTaUck3EK3s0E2UboyxW77Q 55vbN/KKAMfMjFG+BqwR1E9//C/wsuk= From: Ihor Solodrai To: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Nathan Chancellor , Nicolas Schier , Nick Desaulniers , Bill Wendling , Justin Stitt Cc: bpf@vger.kernel.org, dwarves@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kbuild@vger.kernel.org, Alan Maguire , Donglin Peng Subject: [PATCH bpf-next v1 4/4] resolve_btfids: change in-place update with raw binary output Date: Tue, 25 Nov 2025 17:26:56 -0800 Message-ID: <20251126012656.3546071-5-ihor.solodrai@linux.dev> In-Reply-To: <20251126012656.3546071-1-ihor.solodrai@linux.dev> References: <20251126012656.3546071-1-ihor.solodrai@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" Currently resolve_btfids updates .BTF_ids section of an ELF file in-place, based on the contents of provided BTF, usually within the same input file, and optionally a BTF base. This patch changes resolve_btfids behavior to enable BTF transformations as part of its main operation. To achieve this in-place ELF write in resolve_btfids is replaced with generation of the following binaries: * ${1}.btf with .BTF section data * ${1}.distilled_base.btf with .BTF.base section data (for modules) * ${1}.btf_ids with .BTF_ids section data, if it exists in ${1} The execution of resolve_btfids and consumption of its output is orchestrated by scripts/gen-btf.sh introduced in this patch. The rationale for this approach is that updating ELF in-place with libelf API is complicated and bug-prone, especially in the context of the kernel build. On the other hand applying objcopy to manipulate ELF sections is simpler and more reliable. There are two distinct paths for BTF generation and resolve_btfids application in the kernel build: for vmlinux and for kernel modules. For the vmlinux binary a .BTF section is added in a roundabout way to ensure correct linking (details below). The patch doesn't change this approach, only the implementation is a little different. Before this patch it worked like follows: * pahole consumed .tmp_vmlinux1 [1] and added .BTF section with llvm-objcopy [2] to it * then everything except the .BTF section was stripped from .tmp_vmlinux1 into a .tmp_vmlinux1.bpf.o object [1], later linked into vmlinux * resolve_btfids was executed later on vmlinux.unstripped [3], updating it in-place After this patch gen-btf.sh implements the following: * pahole consumes .tmp_vmlinux1 and produces a **detached** file with raw BTF data * resolve_btfids consumes .tmp_vmlinux1 and detached BTF to produce (potentially modified) .BTF, and .BTF_ids sections data * a .tmp_vmlinux1.bpf.o object is then produced with objcopy copying BTF output of resolve_btfids * .BTF_ids data gets embedded into vmlinux.unstripped in link-vmlinux.sh by objcopy --update-section For the kernel modules creating special .bpf.o file is not necessary, and so embedding of sections data produced by resolve_btfids is straightforward with the objcopy. [1] https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf.git/tree/script= s/link-vmlinux.sh#n115 [2] https://git.kernel.org/pub/scm/devel/pahole/pahole.git/tree/btf_encoder= .c#n1835 [3] https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf.git/tree/script= s/link-vmlinux.sh#n285 Signed-off-by: Ihor Solodrai --- MAINTAINERS | 1 + scripts/Makefile.modfinal | 5 +- scripts/gen-btf.sh | 166 ++++++++++++++++++++++++++++++++ scripts/link-vmlinux.sh | 42 ++------ tools/bpf/resolve_btfids/main.c | 124 ++++++++++++++++++------ 5 files changed, 272 insertions(+), 66 deletions(-) create mode 100755 scripts/gen-btf.sh diff --git a/MAINTAINERS b/MAINTAINERS index 48aabeeed029..5cd34419d952 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4672,6 +4672,7 @@ F: net/sched/act_bpf.c F: net/sched/cls_bpf.c F: samples/bpf/ F: scripts/bpf_doc.py +F: scripts/gen-btf.sh F: scripts/Makefile.btf F: scripts/pahole-version.sh F: tools/bpf/ diff --git a/scripts/Makefile.modfinal b/scripts/Makefile.modfinal index 542ba462ed3e..86f843995556 100644 --- a/scripts/Makefile.modfinal +++ b/scripts/Makefile.modfinal @@ -38,9 +38,8 @@ quiet_cmd_btf_ko =3D BTF [M] $@ cmd_btf_ko =3D \ if [ ! -f $(objtree)/vmlinux ]; then \ printf "Skipping BTF generation for %s due to unavailability of vmlinux\= n" $@ 1>&2; \ - else \ - LLVM_OBJCOPY=3D"$(OBJCOPY)" $(PAHOLE) -J $(PAHOLE_FLAGS) $(MODULE_PAHOLE= _FLAGS) --btf_base $(objtree)/vmlinux $@; \ - $(RESOLVE_BTFIDS) -b $(objtree)/vmlinux $@; \ + else \ + $(objtree)/scripts/gen-btf.sh --btf_base $(objtree)/vmlinux $@; \ fi; =20 # Same as newer-prereqs, but allows to exclude specified extra dependencies diff --git a/scripts/gen-btf.sh b/scripts/gen-btf.sh new file mode 100755 index 000000000000..102f8296ae9e --- /dev/null +++ b/scripts/gen-btf.sh @@ -0,0 +1,166 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (c) 2025 Meta Platforms, Inc. and affiliates. +# +# This script generates BTF data for the provided ELF file. +# +# Kernel BTF generation involves these conceptual steps: +# 1. pahole generates BTF from DWARF data +# 2. resolve_btfids applies kernel-specific btf2btf +# transformations and computes data for .BTF_ids section +# 3. the result gets linked/objcopied into the target binary +# +# How step (3) should be done differs between vmlinux, and +# kernel modules, which is the primary reason for the existence +# of this script. +# +# For modules the script expects vmlinux passed in as --btf_base. +# Generated .BTF, .BTF.base and .BTF_ids sections become embedded +# into the input ELF file with objcopy. +# +# For vmlinux the input file remains unchanged and two files are produced: +# - ${1}.btf.o ready for linking into vmlinux +# - ${1}.btf_ids with .BTF_ids data blob +# This output is consumed by scripts/link-vmlinux.sh + +set -e + +usage() +{ + echo "Usage: $0 [--btf_base ] " + exit 1 +} + +BTF_BASE=3D"" + +while [ $# -gt 0 ]; do + case "$1" in + --btf_base) + BTF_BASE=3D"$2" + shift 2 + ;; + -*) + echo "Unknown option: $1" >&2 + usage + ;; + *) + break + ;; + esac +done + +if [ $# -ne 1 ]; then + usage +fi + +ELF_FILE=3D"$1" +shift + +is_enabled() { + grep -q "^$1=3Dy" ${objtree}/include/config/auto.conf +} + +info() +{ + printf " %-7s %s\n" "${1}" "${2}" +} + +case "${KBUILD_VERBOSE}" in +*1*) + set -x + ;; +esac + +if ! is_enabled CONFIG_DEBUG_INFO_BTF; then + exit 0 +fi + +gen_btf_data() +{ + info BTF "${ELF_FILE}" + btf1=3D"${ELF_FILE}.btf.1" + ${PAHOLE} -J ${PAHOLE_FLAGS} \ + ${BTF_BASE:+--btf_base ${BTF_BASE}} \ + --btf_encode_detached=3D${btf1} \ + "${ELF_FILE}" + + info BTFIDS "${ELF_FILE}" + RESOLVE_BTFIDS_OPTS=3D"" + if is_enabled CONFIG_WERROR; then + RESOLVE_BTFIDS_OPTS+=3D" --fatal_warnings " + fi + if [ -n "${KBUILD_VERBOSE}" ]; then + RESOLVE_BTFIDS_OPTS+=3D" -v " + fi + ${RESOLVE_BTFIDS} ${RESOLVE_BTFIDS_OPTS} \ + ${BTF_BASE:+--btf_base ${BTF_BASE}} \ + --btf ${btf1} "${ELF_FILE}" +} + +gen_btf_o() +{ + local btf_data=3D${ELF_FILE}.btf.o + + # Create ${btf_data} which contains just .BTF section but no symbols. Add + # SHF_ALLOC because .BTF will be part of the vmlinux image. --strip-all + # deletes all symbols including __start_BTF and __stop_BTF, which will + # be redefined in the linker script. + info OBJCOPY "${btf_data}" + echo "" | ${CC} -c -x c -o ${btf_data} - + ${OBJCOPY} --add-section .BTF=3D${ELF_FILE}.btf \ + --set-section-flags .BTF=3Dalloc,readonly ${btf_data} + ${OBJCOPY} --only-section=3D.BTF --strip-all ${btf_data} + + # Change e_type to ET_REL so that it can be used to link final vmlinux. + # GNU ld 2.35+ and lld do not allow an ET_EXEC input. + if is_enabled CONFIG_CPU_BIG_ENDIAN; then + et_rel=3D'\0\1' + else + et_rel=3D'\1\0' + fi + printf "${et_rel}" | dd of=3D"${btf_data}" conv=3Dnotrunc bs=3D1 seek=3D1= 6 status=3Dnone +} + +embed_btf_data() +{ + info OBJCOPY "${ELF_FILE}" + + ${OBJCOPY} \ + --add-section .BTF=3D${ELF_FILE}.btf \ + --add-section .BTF.base=3D${ELF_FILE}.distilled_base.btf \ + ${ELF_FILE} + + # a module might not have a .BTF_ids section + if [ -f "${ELF_FILE}.btf_ids" ]; then + ${OBJCOPY} --update-section .BTF_ids=3D${ELF_FILE}.btf_ids ${ELF_FILE} + fi +} + +cleanup() +{ + rm -f "${ELF_FILE}.btf.1" + rm -f "${ELF_FILE}.btf" + if [ "${BTFGEN_MODE}" =3D=3D "module" ]; then + rm -f "${ELF_FILE}.distilled_base.btf" + rm -f "${ELF_FILE}.btf_ids" + fi +} +trap cleanup EXIT + +BTFGEN_MODE=3D"vmlinux" +if [ -n "${BTF_BASE}" ]; then + BTFGEN_MODE=3D"module" +fi + +gen_btf_data + +case "${BTFGEN_MODE}" in +vmlinux) + gen_btf_o + ;; +module) + embed_btf_data + ;; +esac + +exit 0 diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh index 433849ff7529..728f82af24f6 100755 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh @@ -105,34 +105,6 @@ vmlinux_link() ${kallsymso} ${btf_vmlinux_bin_o} ${arch_vmlinux_o} ${ldlibs} } =20 -# generate .BTF typeinfo from DWARF debuginfo -# ${1} - vmlinux image -gen_btf() -{ - local btf_data=3D${1}.btf.o - - info BTF "${btf_data}" - LLVM_OBJCOPY=3D"${OBJCOPY}" ${PAHOLE} -J ${PAHOLE_FLAGS} ${1} - - # Create ${btf_data} which contains just .BTF section but no symbols. Add - # SHF_ALLOC because .BTF will be part of the vmlinux image. --strip-all - # deletes all symbols including __start_BTF and __stop_BTF, which will - # be redefined in the linker script. Add 2>/dev/null to suppress GNU - # objcopy warnings: "empty loadable segment detected at ..." - ${OBJCOPY} --only-section=3D.BTF --set-section-flags .BTF=3Dalloc,readonl= y \ - --strip-all ${1} "${btf_data}" 2>/dev/null - # Change e_type to ET_REL so that it can be used to link final vmlinux. - # GNU ld 2.35+ and lld do not allow an ET_EXEC input. - if is_enabled CONFIG_CPU_BIG_ENDIAN; then - et_rel=3D'\0\1' - else - et_rel=3D'\1\0' - fi - printf "${et_rel}" | dd of=3D"${btf_data}" conv=3Dnotrunc bs=3D1 seek=3D1= 6 status=3Dnone - - btf_vmlinux_bin_o=3D${btf_data} -} - # Create ${2}.o file with all symbols from the ${1} object file kallsyms() { @@ -204,6 +176,7 @@ if is_enabled CONFIG_ARCH_WANTS_PRE_LINK_VMLINUX; then fi =20 btf_vmlinux_bin_o=3D +btfids_vmlinux=3D kallsymso=3D strip_debug=3D generate_map=3D @@ -224,11 +197,13 @@ if is_enabled CONFIG_KALLSYMS || is_enabled CONFIG_DE= BUG_INFO_BTF; then fi =20 if is_enabled CONFIG_DEBUG_INFO_BTF; then - if ! gen_btf .tmp_vmlinux1; then + if ! scripts/gen-btf.sh .tmp_vmlinux1; then echo >&2 "Failed to generate BTF for vmlinux" echo >&2 "Try to disable CONFIG_DEBUG_INFO_BTF" exit 1 fi + btf_vmlinux_bin_o=3D.tmp_vmlinux1.btf.o + btfids_vmlinux=3D.tmp_vmlinux1.btf_ids fi =20 if is_enabled CONFIG_KALLSYMS; then @@ -281,14 +256,9 @@ fi =20 vmlinux_link "${VMLINUX}" =20 -# fill in BTF IDs if is_enabled CONFIG_DEBUG_INFO_BTF; then - info BTFIDS "${VMLINUX}" - RESOLVE_BTFIDS_ARGS=3D"" - if is_enabled CONFIG_WERROR; then - RESOLVE_BTFIDS_ARGS=3D" --fatal_warnings " - fi - ${RESOLVE_BTFIDS} ${RESOLVE_BTFIDS_ARGS} "${VMLINUX}" + info OBJCOPY ${btfids_vmlinux} + ${OBJCOPY} --update-section .BTF_ids=3D${btfids_vmlinux} ${VMLINUX} fi =20 mksysmap "${VMLINUX}" System.map diff --git a/tools/bpf/resolve_btfids/main.c b/tools/bpf/resolve_btfids/mai= n.c index 7f5a9f7dde7f..4faf16b1ba6b 100644 --- a/tools/bpf/resolve_btfids/main.c +++ b/tools/bpf/resolve_btfids/main.c @@ -71,9 +71,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -429,14 +431,6 @@ static int elf_collect(struct object *obj) obj->efile.idlist =3D data; obj->efile.idlist_shndx =3D idx; obj->efile.idlist_addr =3D sh.sh_addr; - } else if (!strcmp(name, BTF_BASE_ELF_SEC)) { - /* If a .BTF.base section is found, do not resolve - * BTF ids relative to vmlinux; resolve relative - * to the .BTF.base section instead. btf__parse_split() - * will take care of this once the base BTF it is - * passed is NULL. - */ - obj->base_btf_path =3D NULL; } =20 if (compressed_section_fix(elf, scn, &sh)) @@ -570,6 +564,19 @@ static int load_btf(struct object *obj) obj->base_btf =3D base_btf; obj->btf =3D btf; =20 + if (obj->base_btf) { + err =3D btf__distill_base(obj->btf, &base_btf, &btf); + if (err) { + pr_err("FAILED to distill base BTF: %s\n", strerror(errno)); + goto out_err; + } + + btf__free(obj->btf); + btf__free(obj->base_btf); + obj->btf =3D btf; + obj->base_btf =3D base_btf; + } + return 0; =20 out_err: @@ -777,8 +784,6 @@ static int sets_patch(struct object *obj) =20 static int symbols_patch(struct object *obj) { - off_t err; - if (__symbols_patch(obj, &obj->structs) || __symbols_patch(obj, &obj->unions) || __symbols_patch(obj, &obj->typedefs) || @@ -789,20 +794,67 @@ static int symbols_patch(struct object *obj) if (sets_patch(obj)) return -1; =20 - /* Set type to ensure endian translation occurs. */ - obj->efile.idlist->d_type =3D ELF_T_WORD; + return 0; +} =20 - elf_flagdata(obj->efile.idlist, ELF_C_SET, ELF_F_DIRTY); +static int dump_raw_data(const char *out_path, const void *data, u32 size) +{ + int fd, ret; =20 - err =3D elf_update(obj->efile.elf, ELF_C_WRITE); - if (err < 0) { - pr_err("FAILED elf_update(WRITE): %s\n", - elf_errmsg(-1)); + fd =3D open(out_path, O_WRONLY | O_CREAT | O_TRUNC, 0640); + if (fd < 0) { + pr_err("Couldn't open %s for writing\n", out_path); + return fd; + } + + ret =3D write(fd, data, size); + if (ret < 0 || ret !=3D size) { + pr_err("Failed to write data to %s\n", out_path); + close(fd); + unlink(out_path); + return -1; + } + + close(fd); + pr_debug("Dumped %lu bytes of data to %s\n", size, out_path); + + return 0; +} + +static int dump_raw_btf_ids(struct object *obj, const char *out_path) +{ + Elf_Data *data =3D obj->efile.idlist; + int fd, err; + + if (!data || !data->d_buf) { + pr_debug("%s has no BTF_ids data to dump\n", obj->path); + return 0; + } + + err =3D dump_raw_data(out_path, data->d_buf, data->d_size); + if (err) + return -1; + + return 0; +} + +static int dump_raw_btf(struct btf *btf, const char *out_path) +{ + const void *raw_btf_data; + u32 raw_btf_size; + int fd, err; + + raw_btf_data =3D btf__raw_data(btf, &raw_btf_size); + if (raw_btf_data =3D=3D NULL) { + pr_err("btf__raw_data() failed\n"); + return -1; } =20 - pr_debug("update %s for %s\n", - err >=3D 0 ? "ok" : "failed", obj->path); - return err < 0 ? -1 : 0; + err =3D dump_raw_data(out_path, raw_btf_data, raw_btf_size); + if (err) + return -1; + + return 0; } =20 static const char * const resolve_btfids_usage[] =3D { @@ -823,12 +875,13 @@ int main(int argc, const char **argv) .funcs =3D RB_ROOT, .sets =3D RB_ROOT, }; + char out_path[PATH_MAX]; bool fatal_warnings =3D false; struct option btfid_options[] =3D { OPT_INCR('v', "verbose", &verbose, "be more verbose (show errors, etc)"), OPT_STRING(0, "btf", &obj.btf_path, "BTF data", - "BTF data"), + "input BTF data"), OPT_STRING('b', "btf_base", &obj.base_btf_path, "file", "path of file providing base BTF"), OPT_BOOLEAN(0, "fatal_warnings", &fatal_warnings, @@ -844,6 +897,9 @@ int main(int argc, const char **argv) =20 obj.path =3D argv[0]; =20 + if (load_btf(&obj)) + goto out; + if (elf_collect(&obj)) goto out; =20 @@ -853,23 +909,37 @@ int main(int argc, const char **argv) */ if (obj.efile.idlist_shndx =3D=3D -1 || obj.efile.symbols_shndx =3D=3D -1) { - pr_debug("Cannot find .BTF_ids or symbols sections, nothing to do\n"); - err =3D 0; - goto out; + pr_debug("Cannot find .BTF_ids or symbols sections, skip symbols resolut= ion\n"); + goto dump_btf; } =20 if (symbols_collect(&obj)) goto out; =20 - if (load_btf(&obj)) - goto out; - if (symbols_resolve(&obj)) goto out; =20 if (symbols_patch(&obj)) goto out; =20 + strcpy(out_path, obj.path); + strcat(out_path, ".btf_ids"); + if (dump_raw_btf_ids(&obj, out_path)) + goto out; + +dump_btf: + strcpy(out_path, obj.path); + strcat(out_path, ".btf"); + if (dump_raw_btf(obj.btf, out_path)) + goto out; + + if (obj.base_btf) { + strcpy(out_path, obj.path); + strcat(out_path, ".distilled_base.btf"); + if (dump_raw_btf(obj.base_btf, out_path)) + goto out; + } + if (!(fatal_warnings && warnings)) err =3D 0; out: --=20 2.52.0