Hi Dave,
The section header in the vmss.core file doesn't actually contain anything that would
appear useful:
$ readelf -t vmss.core
There are 1 section headers, starting at offset 0x40:
Section Header:
[Nr] Name
Type Address Offset Link
Size EntSize Info Align
Flags
[ 0] <no-name>
NULL NULL 0000000000000000 0000000000000000 0
0000000000000000 0000000000000000 0 0
[0000000000000000]:
I made a mistake in my previous attempt at a patch. I didn't realize that the code
needed the contents of what the PT_NOTE program header describes included into the memory
with the elf and other headers, that's fixed in my temp code now. I've gotten the
vmcore up to this point at the moment so I've got more to investigate about why these
are failing:
please wait... (gathering module symbol data)
WARNING: cannot access vmalloc'd module memory
crash: cannot determine idle task addresses from init_tasks[] or runqueues[]
crash: cannot resolve "init_task_union"
Below is what I have so far but I'll need to look at going back and rewriting it so
any changes are conditional on e_shnum being non-zero.
$ diff -uprN crash-7.1.9/netdump.c crash-7.1.9.new/netdump.c
--- crash-7.1.9/netdump.c 2017-04-20 13:53:16.000000000 -0500
+++ crash-7.1.9.new/netdump.c 2017-06-27 17:57:03.912353796 -0500
@@ -291,7 +291,7 @@ is_netdump(char *file, ulong source_quer
goto bailout;
load64 = (Elf64_Phdr *)
- &eheader[sizeof(Elf64_Ehdr)+sizeof(Elf64_Phdr)];
+ &eheader[((Elf64_Ehdr *)&eheader[0])->e_phoff];
if ((load64->p_offset & (MIN_PAGE_SIZE-1)) ||
(load64->p_align == 0))
@@ -351,9 +351,9 @@ is_netdump(char *file, ulong source_quer
clean_exit(1);
}
nd->notes32 = (Elf32_Phdr *)
- &nd->elf_header[sizeof(Elf32_Ehdr)];
+ &nd->elf_header[nd->elf32->e_phoff];
nd->load32 = (Elf32_Phdr *)
- &nd->elf_header[sizeof(Elf32_Ehdr)+sizeof(Elf32_Phdr)];
+ &nd->elf_header[nd->elf32->e_phoff+sizeof(Elf32_Phdr)];
if (format == NETDUMP_ELF32)
nd->page_size = (uint)nd->load32->p_align;
dump_Elf32_Ehdr(nd->elf32);
@@ -380,9 +380,9 @@ is_netdump(char *file, ulong source_quer
clean_exit(1);
}
nd->notes64 = (Elf64_Phdr *)
- &nd->elf_header[sizeof(Elf64_Ehdr)];
+ &nd->elf_header[nd->elf64->e_phoff];
nd->load64 = (Elf64_Phdr *)
- &nd->elf_header[sizeof(Elf64_Ehdr)+sizeof(Elf64_Phdr)];
+ &nd->elf_header[nd->elf64->e_phoff+sizeof(Elf64_Phdr)];
if (format == NETDUMP_ELF64)
nd->page_size = (uint)nd->load64->p_align;
dump_Elf64_Ehdr(nd->elf64);
@@ -443,11 +443,9 @@ resize_elf_header(int fd, char *file, ch
Elf64_Phdr *load64;
Elf32_Off p_offset32;
Elf64_Off p_offset64;
- size_t header_size;
- uint num_pt_load_segments;
+ size_t header_size = 0;
eheader = *eheader_ptr;
- header_size = num_pt_load_segments = 0;
elf32 = (Elf32_Ehdr *)&eheader[0];
elf64 = (Elf64_Ehdr *)&eheader[0];
@@ -455,16 +453,20 @@ resize_elf_header(int fd, char *file, ch
{
case NETDUMP_ELF32:
case KDUMP_ELF32:
- num_pt_load_segments = elf32->e_phnum - 1;
- header_size = sizeof(Elf32_Ehdr) + sizeof(Elf32_Phdr) +
- (sizeof(Elf32_Phdr) * num_pt_load_segments);
+ header_size = elf32->e_shoff +
+ elf32->e_shnum * elf32->e_shentsize;
+ if (elf32->e_phoff > elf32->e_shoff)
+ header_size = elf32->e_phoff +
+ elf32->e_phnum * elf32->e_phentsize;
break;
case NETDUMP_ELF64:
case KDUMP_ELF64:
- num_pt_load_segments = elf64->e_phnum - 1;
- header_size = sizeof(Elf64_Ehdr) + sizeof(Elf64_Phdr) +
- (sizeof(Elf64_Phdr) * num_pt_load_segments);
+ header_size = elf64->e_shoff +
+ elf64->e_shnum * elf64->e_shentsize;
+ if (elf64->e_phoff > elf64->e_shoff)
+ header_size = elf64->e_phoff +
+ elf64->e_phnum * elf64->e_phentsize;
break;
}
@@ -494,26 +496,36 @@ resize_elf_header(int fd, char *file, ch
{
case NETDUMP_ELF32:
case KDUMP_ELF32:
- load32 = (Elf32_Phdr
*)&eheader[sizeof(Elf32_Ehdr)+sizeof(Elf32_Phdr)];
+ load32 = (Elf32_Phdr *)&eheader[elf32->e_phoff];
p_offset32 = load32->p_offset;
- for (i = 0; i < num_pt_load_segments; i++, load32 += 1) {
+ for (i = 0; i < elf32->e_phnum; i++, load32 += 1) {
if (load32->p_offset &&
- (p_offset32 > load32->p_offset))
- p_offset32 = load32->p_offset;
+ (load32->p_type == PT_NOTE))
+ p_offset32 = load32->p_offset +
+ load32->p_filesz;
+ }
+ if (header_size == p_offset32) {
+ return header_size;
+ } else {
+ header_size = (size_t)p_offset32;
}
- header_size = (size_t)p_offset32;
break;
case NETDUMP_ELF64:
case KDUMP_ELF64:
- load64 = (Elf64_Phdr
*)&eheader[sizeof(Elf64_Ehdr)+sizeof(Elf64_Phdr)];
+ load64 = (Elf64_Phdr *)&eheader[elf64->e_phoff];
p_offset64 = load64->p_offset;
- for (i = 0; i < num_pt_load_segments; i++, load64 += 1) {
+ for (i = 0; i < elf64->e_phnum; i++, load64 += 1) {
if (load64->p_offset &&
- (p_offset64 > load64->p_offset))
- p_offset64 = load64->p_offset;
+ (load64->p_type == PT_NOTE))
+ p_offset64 = load64->p_offset +
+ load64->p_filesz;
+ }
+ if (header_size == p_offset64) {
+ return header_size;
+ } else {
+ header_size = (size_t)p_offset64;
}
- header_size = (size_t)p_offset64;
break;
}
-----Original Message-----
From: crash-utility-bounces(a)redhat.com [mailto:crash-utility-
bounces(a)redhat.com] On Behalf Of Dave Anderson
Sent: Saturday, June 24, 2017 1:41 AM
To: Discussion list for crash utility usage, maintenance and development
<crash-utility(a)redhat.com>
Subject: Re: [Crash-utility] [RFC]: questions about section headers in ELF
format vmcores
----- Original Message -----
> Hi Dave,
>
> I've got some questions for you if you don't mind. I've got a vmcore
> created from a VMWare vmss file (I think using vmss2core) and crash
> just does this when I run it on it:
>
> $ crash -d5 vmlinux vmss.core
>
> crash64 7.1.9
> Copyright (C) 2002-2016 Red Hat, Inc.
> Copyright (C) 2004, 2005, 2006, 2010 IBM Corporation Copyright (C)
> 1999-2006 Hewlett-Packard Co Copyright (C) 2005, 2006, 2011, 2012
> Fujitsu Limited Copyright (C) 2006, 2007 VA Linux Systems Japan K.K.
> Copyright (C) 2005, 2011 NEC Corporation Copyright (C) 1999, 2002,
> 2007 Silicon Graphics, Inc.
> Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc.
> This program is free software, covered by the GNU General Public
> License, and you are welcome to change it and/or distribute copies of
> it under certain conditions. Enter "help copying" to see the conditions.
> This program has absolutely no warranty. Enter "help warranty" for
details.
>
>
> crash64: Elf64_Phdr pointer: 1875020 ELF header end: 1874fe4
>
> I spent a long time running gdb on crash and found that it makes some
> assumptions about the layout of ELF files that can't really be relied
> upon (Program headers have a fixed offset) and apparently no section
> headers. For the vmss.core file I have crash works out that the header
> size of the ELF and program headers is 4 bytes (which is definitely not
correct).
>
> I made some changes (see below) and can get it to get this far (some
> of the later information is definitely not correct and I've got to
> make changes to is_netdump since it has a fair number of issues as well):
>
> $ crash-7.1.9/crash -d5 vmlinux vmss.core
>
> crash 7.1.9
> Copyright (C) 2002-2016 Red Hat, Inc.
> Copyright (C) 2004, 2005, 2006, 2010 IBM Corporation Copyright (C)
> 1999-2006 Hewlett-Packard Co Copyright (C) 2005, 2006, 2011, 2012
> Fujitsu Limited Copyright (C) 2006, 2007 VA Linux Systems Japan K.K.
> Copyright (C) 2005, 2011 NEC Corporation Copyright (C) 1999, 2002,
> 2007 Silicon Graphics, Inc.
> Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc.
> This program is free software, covered by the GNU General Public
> License, and you are welcome to change it and/or distribute copies of
> it under certain conditions. Enter "help copying" to see the conditions.
> This program has absolutely no warranty. Enter "help warranty" for
details.
>
> vmcore_data:
> flags: c0 (KDUMP_LOCAL|KDUMP_ELF64)
> ndfd: 3
> ofp: 3b0458f040
> header_size: 352
> num_pt_load_segments: 3
> pt_load_segment[0]:
> file_offset: 4
> phys_start: 0
> phys_end: 0
> zero_fill: 218
> pt_load_segment[1]:
> file_offset: 700000001
> phys_start: fff80000
> phys_end: 1fff00000
> zero_fill: 100000000
> pt_load_segment[2]:
> file_offset: 700000001
> phys_start: 0
> phys_end: 0
> zero_fill: c0000000
> elf_header: 1376130
> elf32: 0
> notes32: 0
> load32: 0
> elf64: 1376130
> notes64: 1376170
> load64: 13761a8
> nt_prstatus: 0
> nt_prpsinfo: 0
> nt_taskstruct: 0
> task_struct: 0
> page_size: 0
> switch_stack: 0
> xen_kdump_data: (unused)
> num_prstatus_notes: 0
> num_qemu_notes: 0
> vmcoreinfo: 0
> size_vmcoreinfo: 0
> nt_prstatus_percpu:
> nt_qemu_percpu:
> backup_src_start: 0
> backup_src_size: 0
> backup_offset: 0
>
> Elf64_Ehdr:
> e_ident: \177ELF
> e_ident[EI_CLASS]: 2 (ELFCLASS64)
> e_ident[EI_DATA]: 1 (ELFDATA2LSB)
> e_ident[EI_VERSION]: 1 (EV_CURRENT)
> e_ident[EI_OSABI]: 0 (ELFOSABI_SYSV)
> e_ident[EI_ABIVERSION]: 0
> e_type: 4 (ET_CORE)
> e_machine: 62 (EM_X86_64)
> e_version: 1 (EV_CURRENT)
> e_entry: 0
> e_phoff: 80
> e_shoff: 40
> e_flags: 0
> e_ehsize: 40
> e_phentsize: 38
> e_phnum: 4
> e_shentsize: 40
> e_shnum: 1
> e_shstrndx: 0
> Elf64_Phdr:
> p_type: 0 (PT_NULL)
> p_offset: 0 (0)
> p_vaddr: 0
> p_paddr: 0
> p_filesz: 0 (0)
> p_memsz: 0 (0)
> p_flags: 0 ()
> p_align: 0
> Elf64_Phdr:
> p_type: 0 (PT_NULL)
> p_offset: 4 (4)
> p_vaddr: 160
> p_paddr: 0
> p_filesz: 0 (0)
> p_memsz: 536 (218)
> p_flags: 0 ()
> p_align: 0
> Elf64_Phdr:
> p_type: 0 (PT_NULL)
> p_offset: 30064771073 (700000001)
> p_vaddr: 4000001000
> p_paddr: fff80000
> p_filesz: 4294443008 (fff80000)
> p_memsz: 524288 (80000)
> p_flags: 0 ()
> p_align: 524288
> Elf64_Phdr:
> p_type: 1000 (?)
> p_offset: 30064771073 (700000001)
> p_vaddr: 1000
> p_paddr: 0
> p_filesz: 0 (0)
> p_memsz: 3221225472 (c0000000)
> p_flags: 0 ()
> p_align: 3221225472
> readmem: read_kdump()
> crash: pv_init_ops exists: ARCH_PVOPS
> gdb vmlinux
> GNU gdb (GDB) 7.6
> Copyright (C) 2013 Free Software Foundation, Inc.
> License GPLv3+: GNU GPL version 3 or later
> <
http://gnu.org/licenses/gpl.html>
> This is free software: you are free to change and redistribute it.
> There is NO WARRANTY, to the extent permitted by law. Type "show
copying"
> and "show warranty" for details.
> This GDB was configured as "x86_64-unknown-linux-gnu"...
>
> <readmem: ffffffff8165e250, KVADDR, "cpu_possible_mask", 8, (FOE),
> 7fffd7e36838>
> <read_kdump: addr: ffffffff8165e250 paddr: 165e250 cnt: 8>
> <readmem: ffffffff8165e240, KVADDR, "cpu_present_mask", 8, (FOE),
> 7fffd7e36838>
> <read_kdump: addr: ffffffff8165e240 paddr: 165e240 cnt: 8>
> <readmem: ffffffff8165e248, KVADDR, "cpu_online_mask", 8, (FOE),
> 7fffd7e36838>
> <read_kdump: addr: ffffffff8165e248 paddr: 165e248 cnt: 8>
> <readmem: ffffffff8165e238, KVADDR, "cpu_active_mask", 8, (FOE),
> 7fffd7e36838>
> <read_kdump: addr: ffffffff8165e238 paddr: 165e238 cnt: 8>
> <readmem: ffffffff819658d8, KVADDR, "pv_init_ops", 8, (ROE),
> 7fffd7e47a38>
> <read_kdump: addr: ffffffff819658d8 paddr: 19658d8 cnt: 8>
> <readmem: ffffffff81db6e18, KVADDR, "timekeeper xtime_sec", 8, (ROE),
> 7fffd7e36838>
> <read_kdump: addr: ffffffff81db6e18 paddr: 1db6e18 cnt: 8> xtime
> timespec.tv_sec: 0: Wed Dec 31 18:00:00 1969
> <readmem: ffffffff81951284, KVADDR, "init_uts_ns", 390, (ROE),
cfe2dc>
> <read_kdump: addr: ffffffff81951284 paddr: 1951284 cnt: 390>
> utsname:
> sysname:
> nodename:
> release:
> version:
> machine:
> domainname:
> base kernel version: 0.1.9
> <readmem: ffffffff8164d100, KVADDR, "accessible check", 8, (ROE|Q),
> 7fffd7e33ba8>
> <read_kdump: addr: ffffffff8164d100 paddr: 164d100 cnt: 8>
> <readmem: ffffffff8164d100, KVADDR, "read_string characters", 1499,
> (ROE|Q),
> 7fffd7e35f10>
> <read_kdump: addr: ffffffff8164d100 paddr: 164d100 cnt: 1499>
> WARNING: cannot read linux_banner string
> linux_banner:
>
> crash: vmlinux and vmss.core do not match!
>
> Usage:
>
> crash [OPTION]... NAMELIST MEMORY-IMAGE[@ADDRESS] (dumpfile
form)
> crash [OPTION]... [NAMELIST] (live system form)
>
> Enter "crash -h" for details.
>
> Using something like readelf:
>
> $ readelf --file-header vmss.core
> ELF Header:
> Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
> Class: ELF64
> Data: 2's complement, little endian
> Version: 1 (current)
> OS/ABI: UNIX - System V
> ABI Version: 0
> Type: CORE (Core file)
> Machine: Advanced Micro Devices X86-64
> Version: 0x1
> Entry point address: 0x0
> Start of program headers: 128 (bytes into file)
> Start of section headers: 64 (bytes into file)
> Flags: 0x0
> Size of this header: 64 (bytes)
> Size of program headers: 56 (bytes)
> Number of program headers: 4
> Size of section headers: 64 (bytes)
> Number of section headers: 1
> Section header string table index: 0
>
> Shows that the file has one section header (resize_elf_header didn't
> seem to do anything with section headers) and 4 program headers:
>
> Program Headers:
> Type Offset VirtAddr PhysAddr
> FileSiz MemSiz Flags Align
> NOTE 0x0000000000000160 0x0000000000000000 0x0000000000000000
> 0x0000000000000218 0x0000000000000000 0
> LOAD 0x0000004000001000 0x00000000fff80000 0x00000000fff80000
> 0x0000000000080000 0x0000000000080000 RWE 1000
> LOAD 0x0000000000001000 0x0000000000000000 0x0000000000000000
> 0x00000000c0000000 0x00000000c0000000 RWE 1000
> LOAD 0x00000000c0001000 0x0000000100000000 0x0000000100000000
> 0x0000003f40000000 0x0000003f40000000 RWE 1000
>
> The changes I made (note that I only tested the ELF64 code). In the
> first calculation of the header_size below it seems to assume that
> there will always be an ELF header followed by program headers (one
> for the note program header and then e_phnum-1 load program headers)
> but doesn't take into account the potential existence of a section header:
>
> --- crash-7.1.9/netdump.c 2017-04-20 13:53:16.000000000 -0500
> +++ crash-7.1.9.new/netdump.c 2017-06-22 23:48:23.282639936 -0500
> @@ -455,16 +455,20 @@ resize_elf_header(int fd, char *file, ch
> {
> case NETDUMP_ELF32:
> case KDUMP_ELF32:
> - num_pt_load_segments = elf32->e_phnum - 1;
> - header_size = sizeof(Elf32_Ehdr) + sizeof(Elf32_Phdr) +
> - (sizeof(Elf32_Phdr) * num_pt_load_segments);
> + header_size = elf32->e_shoff +
> + elf32->e_shnum * elf32->e_shentsize;
> + if (elf32->e_phoff > elf32->e_shoff)
> + header_size = elf32->e_phoff +
> + elf32->e_phnum * elf32->e_phentsize;
> break;
>
> case NETDUMP_ELF64:
> case KDUMP_ELF64:
> - num_pt_load_segments = elf64->e_phnum - 1;
> - header_size = sizeof(Elf64_Ehdr) + sizeof(Elf64_Phdr) +
> - (sizeof(Elf64_Phdr) * num_pt_load_segments);
> + header_size = elf64->e_shoff +
> + elf64->e_shnum * elf64->e_shentsize;
> + if (elf64->e_phoff > elf64->e_shoff)
> + header_size = elf64->e_phoff +
> + elf64->e_phnum * elf64->e_phentsize;
> break;
> }
>
> @@ -494,26 +498,34 @@ resize_elf_header(int fd, char *file, ch
> {
> case NETDUMP_ELF32:
> case KDUMP_ELF32:
> - load32 = (Elf32_Phdr
> *)&eheader[sizeof(Elf32_Ehdr)+sizeof(Elf32_Phdr)];
> + load32 = (Elf32_Phdr *)&eheader[elf32->e_phoff];
> p_offset32 = load32->p_offset;
> - for (i = 0; i < num_pt_load_segments; i++, load32 += 1) {
> + for (i = 0; i < elf32->e_phnum; i++, load32 += 1) {
> if (load32->p_offset &&
> (p_offset32 > load32->p_offset))
> p_offset32 = load32->p_offset;
> }
> - header_size = (size_t)p_offset32;
> + if (header_size == p_offset32) {
> + return header_size;
> + } else {
> + header_size = (size_t)p_offset32;
> + }
> break;
>
> case NETDUMP_ELF64:
> case KDUMP_ELF64:
> - load64 = (Elf64_Phdr
> *)&eheader[sizeof(Elf64_Ehdr)+sizeof(Elf64_Phdr)];
> + load64 = (Elf64_Phdr *)&eheader[elf64->e_phoff];
> p_offset64 = load64->p_offset;
> - for (i = 0; i < num_pt_load_segments; i++, load64 += 1) {
> + for (i = 0; i < elf64->e_phnum; i++, load64 += 1) {
> if (load64->p_offset &&
> (p_offset64 > load64->p_offset))
> p_offset64 = load64->p_offset;
> }
> - header_size = (size_t)p_offset64;
> + if (header_size == p_offset64) {
> + return header_size;
> + } else {
> + header_size = (size_t)p_offset64;
> + }
> break;
> }
>
> This shouldn't be considered a patch (yet) but more of a request for
> comments so about if section headers are expected in an ELF64 vmcore
> and if I can more generally trust values like e_shoff, e_shnum,
> e_shentsize, e_phoff, e_phnum, and e_phentsize from the ELF header in
> all vmcores so I can change the code to cope with the potential
> presense of a section header? I'm sort of hoping that you will tell me I can
rely on them being valid.
>
> Thanks
> Shane
I can't confidently tell you that those fields can be trusted.
I just did a quick test of your patch against a sampling of ~50 64-bit ELF
dumpfiles that I've got hanging around, and all of them generate the
message:
WARNING: Elf64_Nhdr pointer: 130d2b8 ELF header end: 130d2b8
i.e., where the offsets are equal. And then the session either fails, or there
are other odd messages.
These ELF vmcores consisted of netdumps, kdumps (both regular and
flattened format), virsh dumps, simple ELF vmcores from the snap.so
extension module, and even the single vmss.core file I have on hand.
In fact the vmss.core file I have does not have any section headers:
$ readelf -a vmss.core
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: CORE (Core file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x0
Start of program headers: 64 (bytes into file)
Start of section headers: 0 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 4
Size of section headers: 0 (bytes)
Number of section headers: 0
Section header string table index: 0
There are no sections in this file.
There are no sections to group in this file.
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
NOTE 0x0000000000000120 0x0000000000000000 0x0000000000000000
0x0000000000000218 0x0000000000000000 0
LOAD 0x0000000100001000 0x00000000fff80000 0x00000000fff80000
0x0000000000080000 0x0000000000080000 RWE 1000
LOAD 0x0000000000001000 0x0000000000000000 0x0000000000000000
0x00000000c0000000 0x00000000c0000000 RWE 1000
LOAD 0x00000000c0001000 0x0000000100000000 0x0000000100000000
0x0000000040000000 0x0000000040000000 RWE 1000
There is no dynamic section in this file.
There are no relocations in this file.
The decoding of unwind sections for machine type Advanced Micro Devices
X86-64 is not currently supported.
Dynamic symbol information is not available for displaying symbols.
No version information found in this file.
Displaying notes found at file offset 0x00000120 with length 0x00000218:
Owner Data size Description
CORE 0x00000150 NT_PRSTATUS (prstatus structure)
CORE 0x00000088 NT_PRPSINFO (prpsinfo structure)
CORE 0x00000010 NT_TASKSTRUCT (task structure)
What's in the new section anyway?
In any case, in order to absolutely prevent any backwards-compatibility
issues, I would be hesitant to make changes unless you can segregate your
code changes such that they only execute if the elf->e_shnum member is
non-zero.
Thanks,
Dave
--
Crash-utility mailing list
Crash-utility(a)redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility