summaryrefslogtreecommitdiff
path: root/elf_info.c
diff options
context:
space:
mode:
authorKazuhito Hagio <k-hagio@ab.jp.nec.com>2019-11-08 22:36:26 +0000
committerKazuhito Hagio <k-hagio@ab.jp.nec.com>2019-11-13 12:51:05 -0500
commit82e6cce2219a8fe32d34a50b7e0d3dd620d739f1 (patch)
tree92923db27981de6cb138fea41aa3f74009907775 /elf_info.c
parent44dc8919f28ca9c49483c0f49bdde769aa67bc58 (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.c40
1 files changed, 37 insertions, 3 deletions
diff --git a/elf_info.c b/elf_info.c
index 204bfbf..e9c2671 100644
--- a/elf_info.c
+++ b/elf_info.c
@@ -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");