----- Original Message -----
Hello Dave,
>On the other hand, it would also be fairly easy to create
>a small utility function that simply pre-pends an ELF header
>to the dumpfile -- one which has a single PT_LOAD section
>that describes the physical memory as one large chunk.
>For this simple format, you could take the snap.c extension
>module's generate_elf_header() function, have it create a
>an ELF header with just one PT_LOAD segment, and fold it
>into a standalone program. It has support for x86, x86_64,
>ppc64 and ia64.
I have chosen this way for my arm target. Though snap.c told me how to
create an elf header,
it is too difficult for me to modify it to support ELF32 of ARM in
addition to existing ELF64 support. So
I just prepend a fixed ELF header which generate_elf_header would
create.
(1) I tried "an ELF header with just one PT_LOAD segment" vmcore file
as you suggested and got the following,
---------------------
$ ./crash vmlinux vmcore
crash 5.1.5
Copyright (C) 2002-2011 Red Hat, Inc.
...
This program has absolutely no warranty. Enter "help warranty" for
details.
crash: vmcore: not a supported file format
Usage:
crash [OPTION]... NAMELIST MEMORY-IMAGE (dumpfile form)
crash [OPTION]... [NAMELIST] (live system form)
Enter "crash -h" for details.
----------------------
The following is information of the file got by readelf command. Is
there something wrong?
$ arm-eabi-readelf -a vmcore
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: CORE (Core file)
Machine: ARM
Version: 0x1
Entry point address: 0x0
Start of program headers: 52 (bytes into file)
Start of section headers: 0 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 1
Size of section headers: 0 (bytes)
Number of section headers: 0
Section header string table index: 0 <corrupt: out of range>
There are no sections in this file.
There are no sections in this file.
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000054 0xc0000000 0x00000000 0x20000000 0x20000000 RWE 0
There is no dynamic section in this file.
There are no relocations in this file.
There are no unwind sections in this file.
No version information found in this file.
------------------------------------------------
(2) Next I tried "an ELF header with an empty PT_NOTE segment and just
one PT_LOAD segment"
This time readelf command shows
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
NOTE 0x000074 0x00000000 0x00000000 0x00000 0x00000 0
LOAD 0x000074 0xc0000000 0x00000000 0x20000000 0x20000000 RWE 0
That's what you need -- it is presumed that there will be a minimum
of two program header sections:
(1) at least one PT_NOTE section (typically an NT_PRSTATUS note w/registers)
(2) at least one PT_LOAD section (which you have)
so without the empty PT_NOTE, it was failing here in is_netdump():
if ((elf32->e_ident[EI_CLASS] == ELFCLASS32) &&
(swap16(elf32->e_type, swap) == ET_CORE) &&
(swap32(elf32->e_version, swap) == EV_CURRENT) &&
(swap16(elf32->e_phnum, swap) >= 2)) {
because your elf32->e_phnum was 1:
Number of program headers: 1
So, yes, adding an empty PT_NOTE should be OK to get by that error.
And I could use this file as a core file for "arm-eabi-gdb
vmlinux > vmcore"
For example "show init_task" works normally.
Is this an expected behavior?
(3) Above vmcore file works for gdb, but it does not work for crash(5.1.5).
I got the following message and the crash command just exited.
crash: CONFIG_SPARSEMEM kernels not supported for this architecture
Would you please tell me how to support CONFIG_SPARSEMEM?
I tried to add "machdep->max_physmem_bits = _MAX_PHYSMEM_BITS;" in
arm.c and made some progress. But still I cannot reach the crash prompt.
I will appreciate any suggestion.
As far as the CONFIG_SPARSEMEM failure, I'm not exactly sure why that's
happening.
Looking at the latest upstream kernel, CONFIG_SPARSEMEM is not supported
by the ARM architecture. This is "arch/arm/include/asm/sparsemem.h":
#ifndef ASMARM_SPARSEMEM_H
#define ASMARM_SPARSEMEM_H
#include <asm/memory.h>
/*
* Two definitions are required for sparsemem:
*
* MAX_PHYSMEM_BITS: The number of physical address bits required
* to address the last byte of memory.
*
* SECTION_SIZE_BITS: The number of physical address bits to cover
* the maximum amount of memory in a section.
*
* Eg, if you have 2 banks of up to 64MB at 0x80000000, 0x84000000,
* then MAX_PHYSMEM_BITS is 32, SECTION_SIZE_BITS is 26.
*
* Define these in your mach/memory.h.
*/
#if !defined(SECTION_SIZE_BITS) || !defined(MAX_PHYSMEM_BITS)
#error Sparsemem is not supported on this platform
#endif
#endif
And "arch/arm/include/asm/memory.h" does not define either
SECTION_SIZE_BITS or MAX_PHYSMEM_BITS.
In any case, the "CONFIG_SPARSEMEM kernels not supported..."
error message is printed in sparse_mem_init(). But that function
should return immediately because IS_SPARSEMEM() should be FALSE
because the SPARSEMEM bit should not be set:
#define IS_SPARSEMEM() (vt->flags & SPARSEMEM)
void
sparse_mem_init(void)
{
ulong addr;
ulong mem_section_size;
int dimension;
if (!IS_SPARSEMEM())
return;
... [ cut ] ...
if (!MAX_PHYSMEM_BITS())
error(FATAL,
"CONFIG_SPARSEMEM kernels not supported for this
architecture\n");
In your case, IS_SPARSEMEM() is returning TRUE because
the SPARSEMEM bit in vt->flags is getting set here:
if (kernel_symbol_exists("mem_section"))
vt->flags |= SPARSEMEM;
... [ cut ] ...
sparse_mem_init();
I have 3 sample ARM dumpfiles, versions 2.6.35-rc3, 2.6.36-rc6, and
2.6.38-rc2, and none of them have a "mem_section" variable, so it
does not make it to the "if (!MAX_PHYSMEM_BITS())" check above.
The kernel's "mem_section" variable is declared in mm/sparse.c:
#ifdef CONFIG_SPARSEMEM_EXTREME
struct mem_section *mem_section[NR_SECTION_ROOTS]
____cacheline_internodealigned_in_smp;
#else
struct mem_section mem_section[NR_SECTION_ROOTS][SECTIONS_PER_ROOT]
____cacheline_internodealigned_in_smp;
#endif
EXPORT_SYMBOL(mem_section);
But the mm/Makefile only builds sparse.c into the kernel if
CONFIG_SPARSEMEM is turned on:
obj-$(CONFIG_SPARSEMEM) += sparse.o
So I don't understand how your kernel could have (and compile with)
a "mem_section" variable, since it needs MAX_PHYSMEM_BITS?
Dave