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


Reply via email to