BPF Archive mirror
 help / color / mirror / Atom feed
* [PATCH dwarves] btf_encoder: add "distilled_base" BTF feature to split BTF generation
@ 2024-04-24 15:54 Alan Maguire
  0 siblings, 0 replies; 4+ messages in thread
From: Alan Maguire @ 2024-04-24 15:54 UTC (permalink / raw
  To: andrii, ast
  Cc: jolsa, acme, quentin, eddyz87, mykolal, daniel, martin.lau, song,
	yonghong.song, john.fastabend, kpsingh, sdf, haoluo, houtao1, bpf,
	masahiroy, mcgrof, nathan, Alan Maguire

Adding "distilled_base" to --btf_features when generating split BTF will
create split and .BTF.base BTF - the latter allows us to map references
from split BTF to base BTF, even if that base BTF has changed.  It does
this by providing just enough information about the base types in the
.BTF.base section.

Patch is applicable on the "next" branch of dwarves, and requires the
libbpf from the series in [1]

Signed-off-by: Alan Maguire <alan.maguire@oracle.com>

[1] https://lore.kernel.org/bpf/20240424154806.3417662-1-alan.maguire@oracle.com/
---
 btf_encoder.c      | 40 ++++++++++++++++++++++++++++------------
 dwarves.h          |  1 +
 man-pages/pahole.1 |  3 +++
 pahole.c           |  1 +
 4 files changed, 33 insertions(+), 12 deletions(-)

diff --git a/btf_encoder.c b/btf_encoder.c
index e1e3529..cc76f62 100644
--- a/btf_encoder.c
+++ b/btf_encoder.c
@@ -75,7 +75,8 @@ struct btf_encoder {
 			  verbose,
 			  force,
 			  gen_floats,
-			  is_rel;
+			  is_rel,
+			  gen_distilled_base;
 	uint32_t	  array_index_id;
 	struct {
 		struct var_info *vars;
@@ -1255,9 +1256,9 @@ static int btf_encoder__write_raw_file(struct btf_encoder *encoder)
 	return err;
 }
 
-static int btf_encoder__write_elf(struct btf_encoder *encoder)
+static int btf_encoder__write_elf(struct btf_encoder *encoder, const struct btf *btf,
+				  const char *btf_secname)
 {
-	struct btf *btf = encoder->btf;
 	const char *filename = encoder->filename;
 	GElf_Shdr shdr_mem, *shdr;
 	Elf_Data *btf_data = NULL;
@@ -1297,7 +1298,7 @@ static int btf_encoder__write_elf(struct btf_encoder *encoder)
 		if (shdr == NULL)
 			continue;
 		char *secname = elf_strptr(elf, strndx, shdr->sh_name);
-		if (strcmp(secname, ".BTF") == 0) {
+		if (strcmp(secname, btf_secname) == 0) {
 			btf_data = elf_getdata(scn, btf_data);
 			break;
 		}
@@ -1341,11 +1342,11 @@ static int btf_encoder__write_elf(struct btf_encoder *encoder)
 			goto unlink;
 		}
 
-		snprintf(cmd, sizeof(cmd), "%s --add-section .BTF=%s %s",
-			 llvm_objcopy, tmp_fn, filename);
+		snprintf(cmd, sizeof(cmd), "%s --add-section %s=%s %s",
+			 llvm_objcopy, btf_secname, tmp_fn, filename);
 		if (system(cmd)) {
-			fprintf(stderr, "%s: failed to add .BTF section to '%s': %d!\n",
-				__func__, filename, errno);
+			fprintf(stderr, "%s: failed to add %s section to '%s': %d!\n",
+				__func__, btf_secname, filename, errno);
 			goto unlink;
 		}
 
@@ -1380,12 +1381,26 @@ int btf_encoder__encode(struct btf_encoder *encoder)
 		fprintf(stderr, "%s: btf__dedup failed!\n", __func__);
 		return -1;
 	}
-
-	if (encoder->raw_output)
+	if (encoder->raw_output) {
 		err = btf_encoder__write_raw_file(encoder);
-	else
-		err = btf_encoder__write_elf(encoder);
+	} else {
+		struct btf *btf = encoder->btf, *distilled_base;
 
+		if (encoder->gen_distilled_base) {
+			if (btf__distill_base(encoder->btf, &distilled_base, &btf) < 0) {
+				fprintf(stderr, "could not generate distilled base BTF: %s\n",
+					strerror(errno));
+				return -1;
+			}
+		}
+		err = btf_encoder__write_elf(encoder, btf, BTF_ELF_SEC);
+		if (!err && encoder->gen_distilled_base)
+			err = btf_encoder__write_elf(encoder, distilled_base, BTF_BASE_ELF_SEC);
+		if (btf != encoder->btf) {
+			btf__free((struct btf *)btf__base_btf(btf));
+			btf__free(btf);
+		}
+	}
 	return err;
 }
 
@@ -1659,6 +1674,7 @@ struct btf_encoder *btf_encoder__new(struct cu *cu, const char *detached_filenam
 		encoder->force		 = conf_load->btf_encode_force;
 		encoder->gen_floats	 = conf_load->btf_gen_floats;
 		encoder->skip_encoding_vars = conf_load->skip_encoding_btf_vars;
+		encoder->gen_distilled_base = conf_load->btf_gen_distilled_base;
 		encoder->verbose	 = verbose;
 		encoder->has_index_type  = false;
 		encoder->need_index_type = false;
diff --git a/dwarves.h b/dwarves.h
index dd35a4e..5f5e2b6 100644
--- a/dwarves.h
+++ b/dwarves.h
@@ -94,6 +94,7 @@ struct conf_load {
 	bool			btf_gen_floats;
 	bool			btf_encode_force;
 	bool			reproducible_build;
+	bool			btf_gen_distilled_base;
 	uint8_t			hashtable_bits;
 	uint8_t			max_hashtable_bits;
 	uint16_t		kabi_prefix_len;
diff --git a/man-pages/pahole.1 b/man-pages/pahole.1
index e3c58e0..bfeb0ff 100644
--- a/man-pages/pahole.1
+++ b/man-pages/pahole.1
@@ -316,6 +316,9 @@ Supported non-standard features (not enabled for 'default')
 	reproducible_build Ensure generated BTF is consistent every time;
 	                   without this parallel BTF encoding can result in
 	                   inconsistent BTF ids.
+	distilled_base     For split BTF, generate a distilled version of
+	                   the associated base BTF to support later relocation
+	                   of split BTF with a possibly changed base.
 .fi
 
 So for example, specifying \-\-btf_encode=var,enum64 will result in a BTF encoding that (as well as encoding basic BTF information) will contain variables and enum64 values.
diff --git a/pahole.c b/pahole.c
index 750b847..79d01dc 100644
--- a/pahole.c
+++ b/pahole.c
@@ -1290,6 +1290,7 @@ struct btf_feature {
 	BTF_DEFAULT_FEATURE(optimized_func, btf_gen_optimized, false),
 	BTF_DEFAULT_FEATURE(consistent_func, skip_encoding_btf_inconsistent_proto, false),
 	BTF_NON_DEFAULT_FEATURE(reproducible_build, reproducible_build, false),
+	BTF_NON_DEFAULT_FEATURE(distilled_base, btf_gen_distilled_base, false),
 };
 
 #define BTF_MAX_FEATURE_STR	1024
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH dwarves] btf_encoder: add "distilled_base" BTF feature to split BTF generation
@ 2024-05-10 10:48 Alan Maguire
  2024-05-11  9:24 ` Eduard Zingerman
  0 siblings, 1 reply; 4+ messages in thread
From: Alan Maguire @ 2024-05-10 10:48 UTC (permalink / raw
  To: andrii, jolsa, acme, quentin
  Cc: eddyz87, mykolal, ast, daniel, martin.lau, song, yonghong.song,
	john.fastabend, kpsingh, sdf, haoluo, houtao1, bpf, masahiroy,
	mcgrof, nathan, Alan Maguire

Adding "distilled_base" to --btf_features when generating split BTF will
create split and .BTF.base BTF - the latter allows us to map references
from split BTF to base BTF, even if that base BTF has changed.  It does
this by providing just enough information about the base types in the
.BTF.base section.

Patch is applicable on the "next" branch of dwarves, and requires the
libbpf from the series in [1]

Signed-off-by: Alan Maguire <alan.maguire@oracle.com>

[1] https://lore.kernel.org/bpf/20240510103052.850012-1-alan.maguire@oracle.com/

---
 btf_encoder.c      | 40 ++++++++++++++++++++++++++++------------
 dwarves.h          |  1 +
 man-pages/pahole.1 |  3 +++
 pahole.c           |  1 +
 4 files changed, 33 insertions(+), 12 deletions(-)

diff --git a/btf_encoder.c b/btf_encoder.c
index 19e9d90..6814549 100644
--- a/btf_encoder.c
+++ b/btf_encoder.c
@@ -75,7 +75,8 @@ struct btf_encoder {
 			  verbose,
 			  force,
 			  gen_floats,
-			  is_rel;
+			  is_rel,
+			  gen_distilled_base;
 	uint32_t	  array_index_id;
 	struct {
 		struct var_info *vars;
@@ -1255,9 +1256,9 @@ static int btf_encoder__write_raw_file(struct btf_encoder *encoder)
 	return err;
 }
 
-static int btf_encoder__write_elf(struct btf_encoder *encoder)
+static int btf_encoder__write_elf(struct btf_encoder *encoder, const struct btf *btf,
+				  const char *btf_secname)
 {
-	struct btf *btf = encoder->btf;
 	const char *filename = encoder->filename;
 	GElf_Shdr shdr_mem, *shdr;
 	Elf_Data *btf_data = NULL;
@@ -1297,7 +1298,7 @@ static int btf_encoder__write_elf(struct btf_encoder *encoder)
 		if (shdr == NULL)
 			continue;
 		char *secname = elf_strptr(elf, strndx, shdr->sh_name);
-		if (strcmp(secname, ".BTF") == 0) {
+		if (strcmp(secname, btf_secname) == 0) {
 			btf_data = elf_getdata(scn, btf_data);
 			break;
 		}
@@ -1341,11 +1342,11 @@ static int btf_encoder__write_elf(struct btf_encoder *encoder)
 			goto unlink;
 		}
 
-		snprintf(cmd, sizeof(cmd), "%s --add-section .BTF=%s %s",
-			 llvm_objcopy, tmp_fn, filename);
+		snprintf(cmd, sizeof(cmd), "%s --add-section %s=%s %s",
+			 llvm_objcopy, btf_secname, tmp_fn, filename);
 		if (system(cmd)) {
-			fprintf(stderr, "%s: failed to add .BTF section to '%s': %d!\n",
-				__func__, filename, errno);
+			fprintf(stderr, "%s: failed to add %s section to '%s': %d!\n",
+				__func__, btf_secname, filename, errno);
 			goto unlink;
 		}
 
@@ -1380,12 +1381,26 @@ int btf_encoder__encode(struct btf_encoder *encoder)
 		fprintf(stderr, "%s: btf__dedup failed!\n", __func__);
 		return -1;
 	}
-
-	if (encoder->raw_output)
+	if (encoder->raw_output) {
 		err = btf_encoder__write_raw_file(encoder);
-	else
-		err = btf_encoder__write_elf(encoder);
+	} else {
+		struct btf *btf = encoder->btf, *distilled_base;
 
+		if (encoder->gen_distilled_base) {
+			if (btf__distill_base(encoder->btf, &distilled_base, &btf) < 0) {
+				fprintf(stderr, "could not generate distilled base BTF: %s\n",
+					strerror(errno));
+				return -1;
+			}
+		}
+		err = btf_encoder__write_elf(encoder, btf, BTF_ELF_SEC);
+		if (!err && encoder->gen_distilled_base)
+			err = btf_encoder__write_elf(encoder, distilled_base, BTF_BASE_ELF_SEC);
+		if (btf != encoder->btf) {
+			btf__free((struct btf *)btf__base_btf(btf));
+			btf__free(btf);
+		}
+	}
 	return err;
 }
 
@@ -1659,6 +1674,7 @@ struct btf_encoder *btf_encoder__new(struct cu *cu, const char *detached_filenam
 		encoder->force		 = conf_load->btf_encode_force;
 		encoder->gen_floats	 = conf_load->btf_gen_floats;
 		encoder->skip_encoding_vars = conf_load->skip_encoding_btf_vars;
+		encoder->gen_distilled_base = conf_load->btf_gen_distilled_base;
 		encoder->verbose	 = verbose;
 		encoder->has_index_type  = false;
 		encoder->need_index_type = false;
diff --git a/dwarves.h b/dwarves.h
index dd35a4e..5f5e2b6 100644
--- a/dwarves.h
+++ b/dwarves.h
@@ -94,6 +94,7 @@ struct conf_load {
 	bool			btf_gen_floats;
 	bool			btf_encode_force;
 	bool			reproducible_build;
+	bool			btf_gen_distilled_base;
 	uint8_t			hashtable_bits;
 	uint8_t			max_hashtable_bits;
 	uint16_t		kabi_prefix_len;
diff --git a/man-pages/pahole.1 b/man-pages/pahole.1
index 19bf197..dae7050 100644
--- a/man-pages/pahole.1
+++ b/man-pages/pahole.1
@@ -316,6 +316,9 @@ Supported non-standard features (not enabled for 'default')
 	reproducible_build Ensure generated BTF is consistent every time;
 	                   without this parallel BTF encoding can result in
 	                   inconsistent BTF ids.
+	distilled_base     For split BTF, generate a distilled version of
+	                   the associated base BTF to support later relocation
+	                   of split BTF with a possibly changed base.
 .fi
 
 So for example, specifying \-\-btf_encode=var,enum64 will result in a BTF encoding that (as well as encoding basic BTF information) will contain variables and enum64 values.
diff --git a/pahole.c b/pahole.c
index 750b847..79d01dc 100644
--- a/pahole.c
+++ b/pahole.c
@@ -1290,6 +1290,7 @@ struct btf_feature {
 	BTF_DEFAULT_FEATURE(optimized_func, btf_gen_optimized, false),
 	BTF_DEFAULT_FEATURE(consistent_func, skip_encoding_btf_inconsistent_proto, false),
 	BTF_NON_DEFAULT_FEATURE(reproducible_build, reproducible_build, false),
+	BTF_NON_DEFAULT_FEATURE(distilled_base, btf_gen_distilled_base, false),
 };
 
 #define BTF_MAX_FEATURE_STR	1024
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH dwarves] btf_encoder: add "distilled_base" BTF feature to split BTF generation
  2024-05-10 10:48 Alan Maguire
@ 2024-05-11  9:24 ` Eduard Zingerman
  0 siblings, 0 replies; 4+ messages in thread
From: Eduard Zingerman @ 2024-05-11  9:24 UTC (permalink / raw
  To: Alan Maguire, andrii, jolsa, acme, quentin
  Cc: mykolal, ast, daniel, martin.lau, song, yonghong.song,
	john.fastabend, kpsingh, sdf, haoluo, houtao1, bpf, masahiroy,
	mcgrof, nathan

On Fri, 2024-05-10 at 11:48 +0100, Alan Maguire wrote:
> Adding "distilled_base" to --btf_features when generating split BTF will
> create split and .BTF.base BTF - the latter allows us to map references
> from split BTF to base BTF, even if that base BTF has changed.  It does
> this by providing just enough information about the base types in the
> .BTF.base section.
> 
> Patch is applicable on the "next" branch of dwarves, and requires the
> libbpf from the series in [1]
> 
> Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
> 
> [1] https://lore.kernel.org/bpf/20240510103052.850012-1-alan.maguire@oracle.com/
> 
> ---

Acked-by: Eduard Zingerman <eddyz87@gmail.com>

[...]

> diff --git a/btf_encoder.c b/btf_encoder.c

[...]

> @@ -1297,7 +1298,7 @@ static int btf_encoder__write_elf(struct btf_encoder *encoder)
>  		if (shdr == NULL)
>  			continue;
>  		char *secname = elf_strptr(elf, strndx, shdr->sh_name);
> -		if (strcmp(secname, ".BTF") == 0) {
> +		if (strcmp(secname, btf_secname) == 0) {

Nit: comments in this function still refer to '.BTF' section.

>  			btf_data = elf_getdata(scn, btf_data);
>  			break;
>  		}

[...]

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH dwarves] btf_encoder: add "distilled_base" BTF feature to split BTF generation
@ 2024-05-17 10:27 Alan Maguire
  0 siblings, 0 replies; 4+ messages in thread
From: Alan Maguire @ 2024-05-17 10:27 UTC (permalink / raw
  To: andrii, jolsa, acme, quentin
  Cc: eddyz87, mykolal, ast, daniel, martin.lau, song, yonghong.song,
	john.fastabend, kpsingh, sdf, haoluo, houtao1, bpf, masahiroy,
	mcgrof, nathan, Alan Maguire

Adding "distilled_base" to --btf_features when generating split BTF will
create split and .BTF.base BTF - the latter allows us to map references
from split BTF to base BTF, even if that base BTF has changed.  It does
this by providing just enough information about the base types in the
.BTF.base section.

Patch is applicable on the "next" branch of dwarves, and requires the
libbpf from the series in [1]

Signed-off-by: Alan Maguire <alan.maguire@oracle.com>

[1] https://lore.kernel.org/bpf/20240517102246.4070184-1-alan.maguire@oracle.com/
---
 btf_encoder.c      | 40 ++++++++++++++++++++++++++++------------
 dwarves.h          |  1 +
 man-pages/pahole.1 |  4 ++++
 pahole.c           |  1 +
 4 files changed, 34 insertions(+), 12 deletions(-)

diff --git a/btf_encoder.c b/btf_encoder.c
index c2df2bc..0d7c657 100644
--- a/btf_encoder.c
+++ b/btf_encoder.c
@@ -93,7 +93,8 @@ struct btf_encoder {
 			  gen_floats,
 			  skip_encoding_decl_tag,
 			  tag_kfuncs,
-			  is_rel;
+			  is_rel,
+			  gen_distilled_base;
 	uint32_t	  array_index_id;
 	struct {
 		struct var_info *vars;
@@ -1284,9 +1285,9 @@ static int btf_encoder__write_raw_file(struct btf_encoder *encoder)
 	return err;
 }
 
-static int btf_encoder__write_elf(struct btf_encoder *encoder)
+static int btf_encoder__write_elf(struct btf_encoder *encoder, const struct btf *btf,
+				  const char *btf_secname)
 {
-	struct btf *btf = encoder->btf;
 	const char *filename = encoder->filename;
 	GElf_Shdr shdr_mem, *shdr;
 	Elf_Data *btf_data = NULL;
@@ -1326,7 +1327,7 @@ static int btf_encoder__write_elf(struct btf_encoder *encoder)
 		if (shdr == NULL)
 			continue;
 		char *secname = elf_strptr(elf, strndx, shdr->sh_name);
-		if (strcmp(secname, ".BTF") == 0) {
+		if (strcmp(secname, btf_secname) == 0) {
 			btf_data = elf_getdata(scn, btf_data);
 			break;
 		}
@@ -1370,11 +1371,11 @@ static int btf_encoder__write_elf(struct btf_encoder *encoder)
 			goto unlink;
 		}
 
-		snprintf(cmd, sizeof(cmd), "%s --add-section .BTF=%s %s",
-			 llvm_objcopy, tmp_fn, filename);
+		snprintf(cmd, sizeof(cmd), "%s --add-section %s=%s %s",
+			 llvm_objcopy, btf_secname, tmp_fn, filename);
 		if (system(cmd)) {
-			fprintf(stderr, "%s: failed to add .BTF section to '%s': %d!\n",
-				__func__, filename, errno);
+			fprintf(stderr, "%s: failed to add %s section to '%s': %d!\n",
+				__func__, btf_secname, filename, errno);
 			goto unlink;
 		}
 
@@ -1755,12 +1756,26 @@ int btf_encoder__encode(struct btf_encoder *encoder)
 		fprintf(stderr, "%s: btf__dedup failed!\n", __func__);
 		return -1;
 	}
-
-	if (encoder->raw_output)
+	if (encoder->raw_output) {
 		err = btf_encoder__write_raw_file(encoder);
-	else
-		err = btf_encoder__write_elf(encoder);
+	} else {
+		struct btf *btf = encoder->btf, *distilled_base;
 
+		if (encoder->gen_distilled_base) {
+			if (btf__distill_base(encoder->btf, &distilled_base, &btf) < 0) {
+				fprintf(stderr, "could not generate distilled base BTF: %s\n",
+					strerror(errno));
+				return -1;
+			}
+		}
+		err = btf_encoder__write_elf(encoder, btf, BTF_ELF_SEC);
+		if (!err && encoder->gen_distilled_base)
+			err = btf_encoder__write_elf(encoder, distilled_base, BTF_BASE_ELF_SEC);
+		if (btf != encoder->btf) {
+			btf__free((struct btf *)btf__base_btf(btf));
+			btf__free(btf);
+		}
+	}
 	return err;
 }
 
@@ -2037,6 +2052,7 @@ struct btf_encoder *btf_encoder__new(struct cu *cu, const char *detached_filenam
 		encoder->skip_encoding_vars = conf_load->skip_encoding_btf_vars;
 		encoder->skip_encoding_decl_tag	 = conf_load->skip_encoding_btf_decl_tag;
 		encoder->tag_kfuncs	 = conf_load->btf_decl_tag_kfuncs;
+		encoder->gen_distilled_base = conf_load->btf_gen_distilled_base;
 		encoder->verbose	 = verbose;
 		encoder->has_index_type  = false;
 		encoder->need_index_type = false;
diff --git a/dwarves.h b/dwarves.h
index 7d566b6..b9e88e3 100644
--- a/dwarves.h
+++ b/dwarves.h
@@ -95,6 +95,7 @@ struct conf_load {
 	bool			btf_encode_force;
 	bool			reproducible_build;
 	bool			btf_decl_tag_kfuncs;
+	bool			btf_gen_distilled_base;
 	uint8_t			hashtable_bits;
 	uint8_t			max_hashtable_bits;
 	uint16_t		kabi_prefix_len;
diff --git a/man-pages/pahole.1 b/man-pages/pahole.1
index f060593..2f623b4 100644
--- a/man-pages/pahole.1
+++ b/man-pages/pahole.1
@@ -317,6 +317,10 @@ Supported non-standard features (not enabled for 'default')
 	                   without this parallel BTF encoding can result in
 	                   inconsistent BTF ids.
 	decl_tag_kfuncs    Inject a BTF_KIND_DECL_TAG for each discovered kfunc.
+	distilled_base     For split BTF, generate a distilled version of
+	                   the associated base BTF to support later relocation
+	                   of split BTF with a possibly changed base, storing
+	                   it in a .BTF.base ELF section.
 .fi
 
 So for example, specifying \-\-btf_encode=var,enum64 will result in a BTF encoding that (as well as encoding basic BTF information) will contain variables and enum64 values.
diff --git a/pahole.c b/pahole.c
index 954498d..fdb65d4 100644
--- a/pahole.c
+++ b/pahole.c
@@ -1291,6 +1291,7 @@ struct btf_feature {
 	BTF_DEFAULT_FEATURE(consistent_func, skip_encoding_btf_inconsistent_proto, false),
 	BTF_DEFAULT_FEATURE(decl_tag_kfuncs, btf_decl_tag_kfuncs, false),
 	BTF_NON_DEFAULT_FEATURE(reproducible_build, reproducible_build, false),
+	BTF_NON_DEFAULT_FEATURE(distilled_base, btf_gen_distilled_base, false),
 };
 
 #define BTF_MAX_FEATURE_STR	1024
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2024-05-17 10:27 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-04-24 15:54 [PATCH dwarves] btf_encoder: add "distilled_base" BTF feature to split BTF generation Alan Maguire
  -- strict thread matches above, loose matches on Subject: below --
2024-05-10 10:48 Alan Maguire
2024-05-11  9:24 ` Eduard Zingerman
2024-05-17 10:27 Alan Maguire

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 read-only IMAP folder(s) and NNTP newsgroup(s).