bpf.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Alan Maguire <alan.maguire@oracle.com>
To: acme@kernel.org
Cc: andrii.nakryiko@gmail.com, ast@kernel.org, daniel@iogearbox.net,
	jolsa@kernel.org, martin.lau@linux.dev, song@kernel.org,
	yhs@fb.com, john.fastabend@gmail.com, kpsingh@kernel.org,
	sdf@google.com, haoluo@google.com, mykolal@fb.com,
	bpf@vger.kernel.org, Alan Maguire <alan.maguire@oracle.com>
Subject: [RFC dwarves 1/2] dwarves: auto-detect maximum kind supported by vmlinux
Date: Thu, 20 Jul 2023 21:14:42 +0100	[thread overview]
Message-ID: <20230720201443.224040-2-alan.maguire@oracle.com> (raw)
In-Reply-To: <20230720201443.224040-1-alan.maguire@oracle.com>

When a newer pahole is run on an older kernel, it often knows about BTF
kinds that the kernel does not support.  This is a problem because the BTF
generated is then embedded in the kernel image and read, and if unknown
kinds are found, BTF handling fails and core BPF functionality is
unavailable.

The scripts/pahole-flags.sh script enumerates the various pahole options
available associated with various versions of pahole, but the problem is
what matters in the case of an older kernel is the set of kinds the kernel
understands.  Because recent features such as BTF_KIND_ENUM64 are added
by default (and only skipped if --skip_encoding_btf_* is set), BTF will
be created with these newer kinds that the older kernel cannot read.
This can be fixed by stable-backporting --skip options, but this is
cumbersome and would have to be done every time a new BTF kind is
introduced.

Here instead we pre-process the DWARF information associated with the
target for BTF generation; if we find an enum with a BTF_KIND_MAX
value in the DWARF associated with the object, we use that to
determine the maximum BTF kind supported.  Note that the enum
representation of BTF kinds starts for the 5.16 kernel; prior to this
The benefit of auto-detection is that no work is required for older
kernels when new kinds are added, and --skip_encoding options are
less needed.

[1] https://github.com/oracle-samples/bpftune/issues/35

Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
---
 btf_encoder.c  | 12 ++++++++++++
 dwarf_loader.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++
 dwarves.h      |  2 ++
 3 files changed, 66 insertions(+)

diff --git a/btf_encoder.c b/btf_encoder.c
index 65f6e71..98c7529 100644
--- a/btf_encoder.c
+++ b/btf_encoder.c
@@ -1889,3 +1889,15 @@ struct btf *btf_encoder__btf(struct btf_encoder *encoder)
 {
 	return encoder->btf;
 }
+
+void dwarves__set_btf_kind_max(struct conf_load *conf_load, int btf_kind_max)
+{
+	if (btf_kind_max < 0 || btf_kind_max >= BTF_KIND_MAX)
+		return;
+	if (btf_kind_max < BTF_KIND_DECL_TAG)
+		conf_load->skip_encoding_btf_decl_tag = true;
+	if (btf_kind_max < BTF_KIND_TYPE_TAG)
+		conf_load->skip_encoding_btf_type_tag = true;
+	if (btf_kind_max < BTF_KIND_ENUM64)
+		conf_load->skip_encoding_btf_enum64 = true;
+}
diff --git a/dwarf_loader.c b/dwarf_loader.c
index ccf3194..8984043 100644
--- a/dwarf_loader.c
+++ b/dwarf_loader.c
@@ -3358,8 +3358,60 @@ static int __dwarf_cus__process_cus(struct dwarf_cus *dcus)
 	return 0;
 }
 
+/* Find enumeration value for BTF_KIND_MAX; replace conf_load->btf_kind_max with
+ * this value if found since it indicates that the target object does not know
+ * about kinds > its BTF_KIND_MAX value.  This is valuable for kernel/module
+ * BTF where a newer pahole/libbpf operate on an older kernel which cannot
+ * parse some of the newer kinds pahole can generate.
+ */
+static void dwarf__find_btf_kind_max(struct dwarf_cus *dcus)
+{
+	struct conf_load *conf = dcus->conf;
+	uint8_t pointer_size, offset_size;
+	Dwarf_Off off = 0, noff;
+	size_t cuhl;
+
+	while (dwarf_nextcu(dcus->dw, off, &noff, &cuhl, NULL, &pointer_size, &offset_size) == 0) {
+		Dwarf_Die die_mem;
+		Dwarf_Die *cu_die = dwarf_offdie(dcus->dw, off + cuhl, &die_mem);
+		Dwarf_Die child;
+
+		if (cu_die == NULL)
+			break;
+		if (dwarf_child(cu_die, &child) == 0) {
+			Dwarf_Die *die = &child;
+
+			do {
+				Dwarf_Die echild, *edie;
+
+				if (dwarf_tag(die) != DW_TAG_enumeration_type ||
+				    !dwarf_haschildren(die) ||
+				    dwarf_child(die, &echild) != 0)
+					continue;
+				edie = &echild;
+				do {
+					const char *ename;
+					int btf_kind_max;
+
+					if (dwarf_tag(edie) != DW_TAG_enumerator)
+						continue;
+					ename = attr_string(edie, DW_AT_name, conf);
+					if (!ename || strcmp(ename, "BTF_KIND_MAX") != 0)
+						continue;
+					btf_kind_max = attr_numeric(edie, DW_AT_const_value);
+					dwarves__set_btf_kind_max(conf, btf_kind_max);
+					return;
+				} while (dwarf_siblingof(edie, edie) == 0);
+			} while (dwarf_siblingof(die, die) == 0);
+		}
+		off = noff;
+	}
+}
+
 static int dwarf_cus__process_cus(struct dwarf_cus *dcus)
 {
+	dwarf__find_btf_kind_max(dcus);
+
 	if (dcus->conf->nr_jobs > 1)
 		return dwarf_cus__threaded_process_cus(dcus);
 
diff --git a/dwarves.h b/dwarves.h
index eb1a6df..f4d9347 100644
--- a/dwarves.h
+++ b/dwarves.h
@@ -1480,4 +1480,6 @@ extern const char tabs[];
 #define DW_TAG_skeleton_unit 0x4a
 #endif
 
+void dwarves__set_btf_kind_max(struct conf_load *conf_load, int btf_kind_max);
+
 #endif /* _DWARVES_H_ */
-- 
2.39.3


  reply	other threads:[~2023-07-20 20:15 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-07-20 20:14 [RFC dwarves 0/2] dwarves: detect BTF kinds supported by kernel Alan Maguire
2023-07-20 20:14 ` Alan Maguire [this message]
2023-07-26 10:39   ` [RFC dwarves 1/2] dwarves: auto-detect maximum kind supported by vmlinux Jiri Olsa
2023-07-26 15:28     ` Alan Maguire
2023-07-27 15:47       ` Alexei Starovoitov
2023-07-20 20:14 ` [RFC dwarves 2/2] btf_encoder: learn BTF_KIND_MAX value from base BTF when generating split BTF Alan Maguire

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230720201443.224040-2-alan.maguire@oracle.com \
    --to=alan.maguire@oracle.com \
    --cc=acme@kernel.org \
    --cc=andrii.nakryiko@gmail.com \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=haoluo@google.com \
    --cc=john.fastabend@gmail.com \
    --cc=jolsa@kernel.org \
    --cc=kpsingh@kernel.org \
    --cc=martin.lau@linux.dev \
    --cc=mykolal@fb.com \
    --cc=sdf@google.com \
    --cc=song@kernel.org \
    --cc=yhs@fb.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).