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
