diff options
author | Kazuhito Hagio <k-hagio@ab.jp.nec.com> | 2019-11-08 22:36:26 +0000 |
---|---|---|
committer | Kazuhito Hagio <k-hagio@ab.jp.nec.com> | 2019-11-13 12:51:05 -0500 |
commit | 82e6cce2219a8fe32d34a50b7e0d3dd620d739f1 (patch) | |
tree | 92923db27981de6cb138fea41aa3f74009907775 /elf_info.c | |
parent | 44dc8919f28ca9c49483c0f49bdde769aa67bc58 (diff) |
[PATCH] Add support for ELF extended numbering
In ELF dump mode, since makedumpfile cannot handle more than PN_XNUM
(0xFFFF) program headers, if a resulting dumpfile needs such a number
of program headers, it creates a broken ELF dumpfile like this:
# crash vmlinux dump.elf
...
WARNING: possibly corrupt Elf64_Nhdr: n_namesz: 4185522176 n_descsz: 3 n_type: f4000
...
WARNING: cannot read linux_banner string
crash: vmlinux and dump.elf do not match!
With this patch, if the actual number of program headers is PN_XNUM
or more, the e_phnum field of the ELF header is set to PN_XNUM, and
the actual number is set in the sh_info field of the section header
at index 0.
The section header is written just after the program headers, although
this order is not typical, for the sake of code simplisity.
Signed-off-by: Kazuhito Hagio <k-hagio@ab.jp.nec.com>
Diffstat (limited to 'elf_info.c')
-rw-r--r-- | elf_info.c | 40 |
1 files changed, 37 insertions, 3 deletions
@@ -123,8 +123,11 @@ check_elf_format(int fd, char *filename, int *phnum, unsigned int *num_load) (*num_load) = 0; if ((ehdr64.e_ident[EI_CLASS] == ELFCLASS64) && (ehdr32.e_ident[EI_CLASS] != ELFCLASS32)) { - (*phnum) = ehdr64.e_phnum; - for (i = 0; i < ehdr64.e_phnum; i++) { + if (!get_elf64_phnum(fd, filename, &ehdr64, phnum)) { + ERRMSG("Can't get phnum.\n"); + return FALSE; + } + for (i = 0; i < (*phnum); i++) { if (!get_elf64_phdr(fd, filename, i, &load64)) { ERRMSG("Can't find Phdr %d.\n", i); return FALSE; @@ -1036,6 +1039,34 @@ is_xen_memory(void) } int +get_elf64_phnum(int fd, char *filename, Elf64_Ehdr *ehdr, int *phnum) +{ + Elf64_Shdr shdr; + + /* + * Extended Numbering support + * See include/uapi/linux/elf.h and elf(5) for more information. + */ + if (ehdr->e_phnum == PN_XNUM) { + if (lseek(fd, ehdr->e_shoff, SEEK_SET) < 0) { + ERRMSG("Can't seek %s at 0x%lx. %s\n", filename, + ehdr->e_shoff, strerror(errno)); + return FALSE; + } + if (read(fd, &shdr, ehdr->e_shentsize) != ehdr->e_shentsize) { + ERRMSG("Can't read %s at 0x%lx. %s\n", filename, + ehdr->e_shoff, strerror(errno)); + return FALSE; + } + + *phnum = shdr.sh_info; + } else + *phnum = ehdr->e_phnum; + + return TRUE; +} + +int get_phnum_memory(void) { int phnum; @@ -1047,7 +1078,10 @@ get_phnum_memory(void) ERRMSG("Can't get ehdr64.\n"); return FALSE; } - phnum = ehdr64.e_phnum; + if (!get_elf64_phnum(fd_memory, name_memory, &ehdr64, &phnum)) { + ERRMSG("Can't get phnum.\n"); + return FALSE; + } } else { /* ELF32 */ if (!get_elf32_ehdr(fd_memory, name_memory, &ehdr32)) { ERRMSG("Can't get ehdr32.\n"); |