[PATCH 01/10] util_lib: add paddr_to_offset function and expose raw vmcoreinfo data

Pnina Feder <[email protected]>
Newsgroups org.infradead.lists.kexec
Message-ID <[email protected]>
Add paddr_to_offset() to translate physical addresses to file offsets,
complementing the existing vaddr_to_offset() for virtual addresses.

Store raw vmcoreinfo note data when parsing ELF notes and provide
elf_get_raw_vmcoreinfo() accessor to retrieve it. This allows callers
to access the unparsed vmcoreinfo content for external processing.
and fix compilation warnings.

Change-Id: Icc75c22d6b2d95b6c951ccf647819d7e9cc4e7de
Signed-off-by: Pnina Feder <[email protected]>
---
 util_lib/elf_info.c         | 53 ++++++++++++++++++++++++++++++++-----
 util_lib/include/elf_info.h | 11 ++++----
 2 files changed, 52 insertions(+), 12 deletions(-)

diff --git a/util_lib/elf_info.c b/util_lib/elf_info.c
index 589bc1ad..fd7d1d5b 100644
--- a/util_lib/elf_info.c
+++ b/util_lib/elf_info.c
@@ -16,7 +16,8 @@
  */
 
 #include <inttypes.h>
-#include <elf_info.h>
+
+#include "elf_info.h"
 
 /* The 32bit and 64bit note headers make it clear we don't care */
 typedef Elf32_Nhdr Elf_Nhdr;
@@ -27,6 +28,9 @@ static Elf64_Phdr *phdr;
 static int num_pt_loads;
 
 static char osrelease[4096];
+/* Raw vmcoreinfo storage */
+static char *raw_vmcoreinfo = NULL;
+static size_t raw_vmcoreinfo_len = 0;
 
 /* VMCOREINFO symbols for lockless printk ringbuffer */
 static loff_t prb_vaddr;
@@ -140,6 +144,21 @@ static uint64_t vaddr_to_offset(uint64_t vaddr)
 	exit(30);
 }
 
+uint64_t paddr_to_offset(uint64_t paddr){
+	ssize_t i;
+
+	for (i = 0; i < ehdr.e_phnum; i++) {
+		if (phdr[i].p_paddr > paddr)
+			continue;
+		if ((phdr[i].p_paddr + phdr[i].p_memsz) <= paddr)
+			continue;
+		return phdr[i].p_offset + (paddr - phdr[i].p_paddr);
+	}
+	fprintf(stderr, "No program header covering paddr 0x%llx found kexec bug?\n",
+		(unsigned long long)paddr);
+	return (uint64_t)-1;
+}
+
 static unsigned machine_pointer_bits(void)
 {
 	uint8_t bits = 0;
@@ -646,6 +665,16 @@ static int scan_notes(int fd, loff_t start, loff_t lsize)
 
 		if ((memcmp(n_name, "VMCOREINFO", 11) != 0) || (n_type != 0))
 			continue;
+
+		/* Save raw vmcoreinfo for later use */
+		if (raw_vmcoreinfo)
+			free(raw_vmcoreinfo);
+		raw_vmcoreinfo = malloc(n_descsz);
+		if (raw_vmcoreinfo) {
+			memcpy(raw_vmcoreinfo, n_desc, n_descsz);
+			raw_vmcoreinfo_len = n_descsz;
+		}
+
 		scan_vmcoreinfo(n_desc, n_descsz);
 	}
 
@@ -776,7 +805,7 @@ static void dump_dmesg_legacy(int fd, void (*handler)(char*, unsigned int))
 	 * To collect full dmesg including the part before `dmesg -c` is useful
 	 * for later debugging. Use same logic as what crash utility is using.
 	 */
-	logged_chars = log_end < log_buf_len ? log_end : log_buf_len;
+	logged_chars = log_end < (unsigned int)log_buf_len ? log_end : (unsigned int)log_buf_len;
 
 	if (handler)
 		handler(buf + (log_buf_len - logged_chars), logged_chars);
@@ -873,7 +902,7 @@ static void dump_dmesg_structured(int fd, void (*handler)(char*, unsigned int))
 		uint16_t loglen;
 
 		ret = pread(fd, buf, log_sz, log_buf_offset + current_idx);
-		if (ret != log_sz) {
+		if (ret != (ssize_t)log_sz) {
 			fprintf(stderr, "Failed to read log of size %" PRId64 " bytes:"
 				" %s\n", log_sz, strerror(errno));
 			exit(65);
@@ -1165,7 +1194,7 @@ static void dump_dmesg_lockless(int fd, void (*handler)(char*, unsigned int))
 		exit(64);
 	}
 	ret = pread(fd, m.prb, printk_ringbuffer_sz, vaddr_to_offset(kaddr));
-	if (ret != printk_ringbuffer_sz) {
+	if (ret != (ssize_t)printk_ringbuffer_sz) {
 		fprintf(stderr, "Failed to read prb of size %zu bytes: %s\n",
 			printk_ringbuffer_sz, strerror(errno));
 		exit(65);
@@ -1184,7 +1213,7 @@ static void dump_dmesg_lockless(int fd, void (*handler)(char*, unsigned int))
 	}
 	ret = pread(fd, m.descs, prb_desc_sz * m.desc_ring_count,
 		    vaddr_to_offset(kaddr));
-	if (ret != prb_desc_sz * m.desc_ring_count) {
+	if (ret != (ssize_t)(prb_desc_sz * m.desc_ring_count)) {
 		fprintf(stderr,
 			"Failed to read descs of size %lu bytes: %s\n",
 			prb_desc_sz * m.desc_ring_count, strerror(errno));
@@ -1201,7 +1230,7 @@ static void dump_dmesg_lockless(int fd, void (*handler)(char*, unsigned int))
 	}
 	ret = pread(fd, m.infos, printk_info_sz * m.desc_ring_count,
 		    vaddr_to_offset(kaddr));
-	if (ret != printk_info_sz * m.desc_ring_count) {
+	if (ret != (ssize_t)(printk_info_sz * m.desc_ring_count)) {
 		fprintf(stderr,
 			"Failed to read infos of size %lu bytes: %s\n",
 			printk_info_sz * m.desc_ring_count, strerror(errno));
@@ -1222,7 +1251,7 @@ static void dump_dmesg_lockless(int fd, void (*handler)(char*, unsigned int))
 	}
 	ret = pread(fd, m.text_data, m.text_data_ring_size,
 		    vaddr_to_offset(kaddr));
-	if (ret != m.text_data_ring_size) {
+	if (ret != (ssize_t)(m.text_data_ring_size)) {
 		fprintf(stderr,
 			"Failed to read text_data of size %lu bytes: %s\n",
 			m.text_data_ring_size, strerror(errno));
@@ -1321,3 +1350,13 @@ int read_phys_offset_elf_kcore(int fd, long *phys_off)
 
 	return 2;
 }
+
+int elf_get_raw_vmcoreinfo(const char **data, size_t *size)
+{
+	if (!raw_vmcoreinfo || raw_vmcoreinfo_len == 0)
+		return -1;
+
+	*data = raw_vmcoreinfo;
+	*size = raw_vmcoreinfo_len;
+	return 0;
+}
diff --git a/util_lib/include/elf_info.h b/util_lib/include/elf_info.h
index fdf4c3d0..c2873365 100644
--- a/util_lib/include/elf_info.h
+++ b/util_lib/include/elf_info.h
@@ -24,13 +24,14 @@
 #include <ctype.h>
 
 int get_pt_load(int idx,
-	unsigned long long *phys_start,
-	unsigned long long *phys_end,
-	unsigned long long *virt_start,
-	unsigned long long *virt_end);
+		unsigned long long *phys_start,
+		unsigned long long *phys_end,
+		unsigned long long *virt_start,
+		unsigned long long *virt_end);
 int read_phys_offset_elf_kcore(int fd, long *phys_off);
 int read_elf(int fd);
 void dump_dmesg(int fd, void (*handler)(char*, unsigned int));
 extern void (*arch_scan_vmcoreinfo)(char *pos);
-
+uint64_t paddr_to_offset(uint64_t paddr);
+int elf_get_raw_vmcoreinfo(const char **data, size_t *size);
 #endif /* ELF_INFO_H */
-- 
2.43.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.