[Crash-utility] DD image

Dave Anderson anderson at redhat.com
Tue May 24 13:31:54 UTC 2011



----- 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




More information about the Crash-utility mailing list