[PATCH 1/1] btf_encoder: Generate a new .BTF section even if one exists

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



LLD generates a zero-length .BTF section (BFD doesn't generate this
section). It shares the same address as .BTF_ids (or any section below
it). E.g.:

  [24] .BTF              PROGBITS        ffffffff825a1900 17a1900 000000
  [25] .BTF_ids          PROGBITS        ffffffff825a1900 17a1900 000634

Writing new data to that section doesn't adjust the addresses of
following sections. As a result, the "-J" flag produces a corrupted
file, causing further commands to fail.

Instead of trying to adjust everything, just add a new section with the
.BTF data and adjust the name of the original .BTF section. (We can't
remove the old .BTF section because it has variables that are referenced
elsewhere.)

Link: https://lore.kernel.org/dwarves/20210317232657.mdnsuoqx6nbddjgt@xxxxxxxxxx/
Cc: Andrii Nakryiko <andrii.nakryiko@xxxxxxxxx>
Cc: Fangrui Song <maskray@xxxxxxxxxx>
Cc: dwarves@xxxxxxxxxxxxxxx
Signed-off-by: Bill Wendling <morbo@xxxxxxxxxx>
---
 btf_encoder.c | 88 +++++++++++++++++++++++++++++++--------------------
 1 file changed, 54 insertions(+), 34 deletions(-)

diff --git a/btf_encoder.c b/btf_encoder.c
index a5fa04a84ee2..bd1ce63e992c 100644
--- a/btf_encoder.c
+++ b/btf_encoder.c
@@ -1039,6 +1039,9 @@ static int btf_encoder__write_elf(struct btf_encoder *encoder)
 	Elf_Data *btf_data = NULL;
 	Elf_Scn *scn = NULL;
 	Elf *elf = NULL;
+	const char *llvm_objcopy;
+	char tmp_fn[PATH_MAX];
+	char cmd[PATH_MAX * 2];
 	const void *raw_btf_data;
 	uint32_t raw_btf_size;
 	int fd, err = -1;
@@ -1081,42 +1084,58 @@ static int btf_encoder__write_elf(struct btf_encoder *encoder)
 
 	raw_btf_data = btf__raw_data(btf, &raw_btf_size);
 
+	llvm_objcopy = getenv("LLVM_OBJCOPY");
+	if (!llvm_objcopy)
+		llvm_objcopy = "llvm-objcopy";
+
+	/* Use objcopy to add a .BTF section */
+	snprintf(tmp_fn, sizeof(tmp_fn), "%s.btf", filename);
+	close(fd);
+	fd = creat(tmp_fn, S_IRUSR | S_IWUSR);
+	if (fd == -1) {
+		fprintf(stderr, "%s: open(%s) failed!\n", __func__,
+			tmp_fn);
+		goto out;
+	}
+
+	if (write(fd, raw_btf_data, raw_btf_size) != raw_btf_size) {
+		fprintf(stderr, "%s: write of %d bytes to '%s' failed: %d!\n",
+			__func__, raw_btf_size, tmp_fn, errno);
+		goto unlink;
+	}
+
 	if (btf_data) {
-		/* Existing .BTF section found */
-		btf_data->d_buf = (void *)raw_btf_data;
-		btf_data->d_size = raw_btf_size;
-		elf_flagdata(btf_data, ELF_C_SET, ELF_F_DIRTY);
-
-		if (elf_update(elf, ELF_C_NULL) >= 0 &&
-		    elf_update(elf, ELF_C_WRITE) >= 0)
-			err = 0;
-		else
-			elf_error("elf_update failed");
-	} else {
-		const char *llvm_objcopy;
-		char tmp_fn[PATH_MAX];
-		char cmd[PATH_MAX * 2];
-
-		llvm_objcopy = getenv("LLVM_OBJCOPY");
-		if (!llvm_objcopy)
-			llvm_objcopy = "llvm-objcopy";
-
-		/* Use objcopy to add a .BTF section */
-		snprintf(tmp_fn, sizeof(tmp_fn), "%s.btf", filename);
-		close(fd);
-		fd = creat(tmp_fn, S_IRUSR | S_IWUSR);
-		if (fd == -1) {
-			fprintf(stderr, "%s: open(%s) failed!\n", __func__,
-				tmp_fn);
-			goto out;
-		}
-
-		if (write(fd, raw_btf_data, raw_btf_size) != raw_btf_size) {
-			fprintf(stderr, "%s: write of %d bytes to '%s' failed: %d!\n",
-				__func__, raw_btf_size, tmp_fn, errno);
+		/*
+		 * Existing .BTF section found. LLD creates a zero-sized .BTF
+		 * section. Adding data to that section doesn't change the
+		 * addresses of the other sections, causing an overwriting of
+		 * data. These commands are a bit convoluted, but they will add
+		 * a new .BTF section with the proper size. Note though that
+		 * the __start_btf and __stop_btf variables aren't affected by
+		 * this change, but then they aren't added when using
+		 * "--add-section" either.
+		 */
+		snprintf(cmd, sizeof(cmd),
+			 "%s --add-section .BTF.new=%s "
+			 "--rename-section .BTF=.BTF.old %s",
+			 llvm_objcopy, tmp_fn, filename);
+		if (system(cmd)) {
+			fprintf(stderr, "%s: failed to add .BTF section to '%s': %d!\n",
+				__func__, filename, errno);
 			goto unlink;
 		}
 
+		snprintf(cmd, sizeof(cmd),
+			 "%s --rename-section .BTF.new=.BTF %s",
+			 llvm_objcopy, filename);
+		if (system(cmd)) {
+			fprintf(stderr, "%s: failed to rename .BTF section to '%s': %d!\n",
+				__func__, filename, errno);
+			goto unlink;
+		}
+
+		err = 0;
+	} else {
 		snprintf(cmd, sizeof(cmd), "%s --add-section .BTF=%s %s",
 			 llvm_objcopy, tmp_fn, filename);
 		if (system(cmd)) {
@@ -1126,10 +1145,11 @@ static int btf_encoder__write_elf(struct btf_encoder *encoder)
 		}
 
 		err = 0;
-	unlink:
-		unlink(tmp_fn);
 	}
 
+unlink:
+	unlink(tmp_fn);
+
 out:
 	if (fd != -1)
 		close(fd);
-- 
2.38.1.584.g0f3c55d4c2-goog




[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux