Problems writing ELF dumps with makedumpfile 1.2.9

Ken'ichi Ohmichi oomichi at mxs.nes.nec.co.jp
Wed Sep 24 04:07:10 EDT 2008


Hi Kevin,

Ken'ichi Ohmichi wrote:
>> My config file is attached. Kernel is 2.6.20 + Ubuntu patches.
>> It was built from http://packages.ubuntu.com/feisty/linux-source-2.6.20
>>
>> Since it might be easy to see the parts I have changed from the defaults,
>> the diff between my config and the Ubuntu "generic" config is below.
> 
> Thank you for your .config file.
> 
> I could reproduce this problem. I created the patch, and it was merged
> into DEVEL tree. Could you get the DEVEL package by the following command
> and test it ?
> 
> cvs -z3 -d:pserver:anonymous at makedumpfile.cvs.sourceforge.net:/cvsroot/makedumpfile co -r DEVEL -P makedumpfile
> 
> If you cannot download it, please try the attached patch for makedumpfile-1.2.9.

Sorry for forgetting one notice.

If you use a vmcoreinfo file by '-i' option, please re-create a vmcoreinfo
file again by a new makedumpfile which applied this patch.
If using an old vmcoreinfo file, makedumpfile cannot run correctly because
the vmcoreinfo file does not contain necessary information (symbol vmlist,
offset vm_struct.addr).


Thanks
Ken'ichi Ohmichi

> -------------------------------
> [PATCH] Add vtop_x86 support.
> 
> On x86 machine, the existing makedumpfile translates a virtual address
> only by referring PT_LOAD header of /proc/vmcore. This feature is not
> enough for x86 machine, because some kernel data is located in vmalloc
> area. Then, this patch adds the translating feature for vmalloc address.
> 
> Signed-off-by: Ken'ichi Ohmichi <oomichi at mxs.nes.nec.co.jp>
> ---
> diff -puN backup/makedumpfile-1.2.9/makedumpfile.c makedumpfile/makedumpfile.c
> --- backup/makedumpfile-1.2.9/makedumpfile.c	2008-09-04 16:31:58.000000000 +0900
> +++ makedumpfile/makedumpfile.c	2008-09-24 14:56:02.000000000 +0900
> @@ -1803,6 +1803,7 @@ get_symbol_info(void)
>  	SYMBOL_INIT(_stext, "_stext");
>  	SYMBOL_INIT(swapper_pg_dir, "swapper_pg_dir");
>  	SYMBOL_INIT(init_level4_pgt, "init_level4_pgt");
> +	SYMBOL_INIT(vmlist, "vmlist");
>  	SYMBOL_INIT(phys_base, "phys_base");
>  	SYMBOL_INIT(node_online_map, "node_online_map");
>  	SYMBOL_INIT(node_states, "node_states");
> @@ -1910,6 +1911,8 @@ get_structure_info(void)
>  	OFFSET_INIT(node_memblk_s.size, "node_memblk_s", "size");
>  	OFFSET_INIT(node_memblk_s.nid, "node_memblk_s", "nid");
>  
> +	OFFSET_INIT(vm_struct.addr, "vm_struct", "addr");
> +
>  	ENUM_NUMBER_INIT(NR_FREE_PAGES, "NR_FREE_PAGES");
>  	ENUM_NUMBER_INIT(N_ONLINE, "N_ONLINE");
>  
> @@ -2095,6 +2098,7 @@ generate_vmcoreinfo(void)
>  	WRITE_SYMBOL("_stext", _stext);
>  	WRITE_SYMBOL("swapper_pg_dir", swapper_pg_dir);
>  	WRITE_SYMBOL("init_level4_pgt", init_level4_pgt);
> +	WRITE_SYMBOL("vmlist", vmlist);
>  	WRITE_SYMBOL("phys_base", phys_base);
>  	WRITE_SYMBOL("node_online_map", node_online_map);
>  	WRITE_SYMBOL("node_states", node_states);
> @@ -2142,6 +2146,7 @@ generate_vmcoreinfo(void)
>  	WRITE_MEMBER_OFFSET("node_memblk_s.start_paddr", node_memblk_s.start_paddr);
>  	WRITE_MEMBER_OFFSET("node_memblk_s.size", node_memblk_s.size);
>  	WRITE_MEMBER_OFFSET("node_memblk_s.nid", node_memblk_s.nid);
> +	WRITE_MEMBER_OFFSET("vm_struct.addr", vm_struct.addr);
>  
>  	if (SYMBOL(node_data) != NOT_FOUND_SYMBOL)
>  		WRITE_ARRAY_LENGTH("node_data", node_data);
> @@ -2339,6 +2344,7 @@ read_vmcoreinfo(void)
>  	READ_SYMBOL("_stext", _stext);
>  	READ_SYMBOL("swapper_pg_dir", swapper_pg_dir);
>  	READ_SYMBOL("init_level4_pgt", init_level4_pgt);
> +	READ_SYMBOL("vmlist", vmlist);
>  	READ_SYMBOL("phys_base", phys_base);
>  	READ_SYMBOL("node_online_map", node_online_map);
>  	READ_SYMBOL("node_states", node_states);
> @@ -2379,6 +2385,7 @@ read_vmcoreinfo(void)
>  	READ_MEMBER_OFFSET("node_memblk_s.start_paddr", node_memblk_s.start_paddr);
>  	READ_MEMBER_OFFSET("node_memblk_s.size", node_memblk_s.size);
>  	READ_MEMBER_OFFSET("node_memblk_s.nid", node_memblk_s.nid);
> +	READ_MEMBER_OFFSET("vm_struct.addr", vm_struct.addr);
>  
>  	READ_ARRAY_LENGTH("node_data", node_data);
>  	READ_ARRAY_LENGTH("pgdat_list", pgdat_list);
> diff -puN backup/makedumpfile-1.2.9/makedumpfile.h makedumpfile/makedumpfile.h
> --- backup/makedumpfile-1.2.9/makedumpfile.h	2008-09-04 16:31:58.000000000 +0900
> +++ makedumpfile/makedumpfile.h	2008-09-24 15:59:13.000000000 +0900
> @@ -498,6 +498,24 @@ do { \
>  #define _SECTION_SIZE_BITS_PAE	(30)
>  #define _MAX_PHYSMEM_BITS	(32)
>  #define _MAX_PHYSMEM_BITS_PAE	(36)
> +
> +#define PGDIR_SHIFT_3LEVEL	(30)
> +#define PTRS_PER_PTE_3LEVEL	(512)
> +#define PTRS_PER_PGD_3LEVEL	(4)
> +#define PMD_SHIFT		(21)  /* only used by PAE translators */
> +#define PTRS_PER_PMD		(512) /* only used by PAE translators */
> +#define PTE_SHIFT		(12)  /* only used by PAE translators */
> +#define PTRS_PER_PTE		(512) /* only used by PAE translators */
> +
> +#define pgd_index_PAE(address)  (((address) >> PGDIR_SHIFT_3LEVEL) & (PTRS_PER_PGD_3LEVEL - 1))
> +#define pmd_index(address)  (((address) >> PMD_SHIFT) & (PTRS_PER_PMD - 1))
> +#define pte_index(address)  (((address) >> PTE_SHIFT) & (PTRS_PER_PTE - 1))
> +
> +#define _PAGE_PRESENT		(0x001)
> +#define _PAGE_PSE		(0x080)
> +
> +#define ENTRY_MASK		(~0x8000000000000fffULL)
> +
>  #endif /* x86 */
>  
>  #ifdef __x86_64__
> @@ -611,10 +629,11 @@ do { \
>   */
>  #ifdef __x86__
>  int get_machdep_info_x86(void);
> +unsigned long long vaddr_to_paddr_x86(unsigned long vaddr);
>  #define get_phys_base()		TRUE
>  #define get_machdep_info()	get_machdep_info_x86()
>  #define get_versiondep_info()	TRUE
> -#define vaddr_to_paddr(X)	vaddr_to_paddr_general(X)
> +#define vaddr_to_paddr(X)	vaddr_to_paddr_x86(X)
>  #endif /* x86 */
>  
>  #ifdef __x86_64__
> @@ -840,6 +859,7 @@ struct symbol_table {
>  	unsigned long long 	_stext;
>  	unsigned long long 	swapper_pg_dir;
>  	unsigned long long 	init_level4_pgt;
> +	unsigned long long 	vmlist;
>  	unsigned long long 	phys_base;
>  	unsigned long long 	node_online_map;
>  	unsigned long long 	node_states;
> @@ -919,6 +939,9 @@ struct offset_table {
>  		long	size;
>  		long	nid;
>  	} node_memblk_s;
> +	struct vm_struct {
> +		long	addr;
> +	} vm_struct;
>  
>  	/*
>  	 * for Xen extraction
> @@ -1051,19 +1074,6 @@ struct domain_list {
>  #define is_direct(x) \
>  	((x) >= DIRECTMAP_VIRT_START && (x) < DIRECTMAP_VIRT_END)
>  
> -#define PGDIR_SHIFT_3LEVEL   (30)
> -#define PTRS_PER_PTE_3LEVEL  (512)
> -#define PTRS_PER_PGD_3LEVEL  (4)
> -#define PMD_SHIFT            (21)    /* only used by PAE translators */
> -#define PTRS_PER_PMD         (512)   /* only used by PAE translators */
> -#define PTE_SHIFT            (12)    /* only used by PAE translators */
> -#define PTRS_PER_PTE         (512)   /* only used by PAE translators */
> -
> -#define _PAGE_PRESENT   0x001
> -#define _PAGE_PSE       0x080
> -
> -#define ENTRY_MASK	(~0x8000000000000fffULL)
> -
>  unsigned long long kvtop_xen_x86(unsigned long kvaddr);
>  #define kvtop_xen(X)	kvtop_xen_x86(X)
>  
> diff -puN backup/makedumpfile-1.2.9/x86.c makedumpfile/x86.c
> --- backup/makedumpfile-1.2.9/x86.c	2008-09-04 16:31:58.000000000 +0900
> +++ makedumpfile/x86.c	2008-09-24 16:06:25.000000000 +0900
> @@ -20,6 +20,8 @@
>  int
>  get_machdep_info_x86(void)
>  {
> +	unsigned long vmlist, vmalloc_start;
> +
>  	/* PAE */
>  	if ((vt.mem_flags & MEMORY_X86_PAE)
>  	    || ((SYMBOL(pkmap_count) != NOT_FOUND_SYMBOL)
> @@ -28,6 +30,7 @@ get_machdep_info_x86(void)
>  	      == 512)) {
>  		DEBUG_MSG("\n");
>  		DEBUG_MSG("PAE          : ON\n");
> +		vt.mem_flags |= MEMORY_X86_PAE;
>  		info->section_size_bits = _SECTION_SIZE_BITS_PAE;
>  		info->max_physmem_bits  = _MAX_PHYSMEM_BITS_PAE;
>  	} else {
> @@ -38,9 +41,123 @@ get_machdep_info_x86(void)
>  	}
>  	info->page_offset = __PAGE_OFFSET;
>  
> +	if (SYMBOL(_stext) == NOT_FOUND_SYMBOL) {
> +		ERRMSG("Can't get the symbol of _stext.\n");
> +		return FALSE;
> +	}
> +	info->kernel_start = SYMBOL(_stext) & ~KVBASE_MASK;
> +	DEBUG_MSG("kernel_start : %lx\n", info->kernel_start);
> +
> +	/*
> +	 * For the compatibility, makedumpfile should run without the symbol
> +	 * vmlist and the offset of vm_struct.addr if they are not necessary.
> +	 */
> +	if ((SYMBOL(vmlist) == NOT_FOUND_SYMBOL)
> +	    || (OFFSET(vm_struct.addr) == NOT_FOUND_STRUCTURE)) {
> +		return TRUE;
> +	}
> +	if (!readmem(VADDR, SYMBOL(vmlist), &vmlist, sizeof(vmlist))) {
> +		ERRMSG("Can't get vmlist.\n");
> +		return FALSE;
> +	}
> +	if (!readmem(VADDR, vmlist + OFFSET(vm_struct.addr), &vmalloc_start,
> +	    sizeof(vmalloc_start))) {
> +		ERRMSG("Can't get vmalloc_start.\n");
> +		return FALSE;
> +	}
> +	info->vmalloc_start = vmalloc_start;
> +	DEBUG_MSG("vmalloc_start: %lx\n", vmalloc_start);
> +
>  	return TRUE;
>  }
>  
> +unsigned long long
> +vtop_x86_PAE(unsigned long vaddr)
> +{
> +	unsigned long long page_dir, pgd_pte, pmd_paddr, pmd_pte;
> +	unsigned long long pte_paddr, pte;
> +
> +	if (SYMBOL(swapper_pg_dir) == NOT_FOUND_SYMBOL) {
> +		ERRMSG("Can't get the symbol of swapper_pg_dir.\n");
> +		return NOT_PADDR;
> +	}
> +
> +	page_dir  = SYMBOL(swapper_pg_dir);
> +	page_dir += pgd_index_PAE(vaddr) * sizeof(unsigned long long);
> +	if (!readmem(VADDR, page_dir, &pgd_pte, sizeof(pgd_pte))) {
> +		ERRMSG("Can't get pgd_pte (page_dir:%llx).\n", page_dir);
> +		return NOT_PADDR;
> +	}
> +	if (!(pgd_pte & _PAGE_PRESENT))
> +		return NOT_PADDR;
> +
> +	if (info->vaddr_for_vtop == vaddr)
> +		MSG("  PGD : %16llx => %16llx\n", page_dir, pgd_pte);
> +
> +	pmd_paddr  = pgd_pte & ENTRY_MASK;
> +	pmd_paddr += pmd_index(vaddr) * sizeof(unsigned long long);
> +	if (!readmem(PADDR, pmd_paddr, &pmd_pte, sizeof(pmd_pte))) {
> +		ERRMSG("Can't get pmd_pte (pmd_paddr:%llx).\n", pmd_paddr);
> +		return NOT_PADDR;
> +	}
> +	if (!(pmd_pte & _PAGE_PRESENT))
> +		return NOT_PADDR;
> +
> +	if (info->vaddr_for_vtop == vaddr)
> +		MSG("  PMD : %16llx => %16llx\n", pmd_paddr, pmd_pte);
> +
> +	if (pmd_pte & _PAGE_PSE)
> +		return (pmd_pte & ENTRY_MASK) + (vaddr & ((1UL << PMD_SHIFT) - 1));
> +
> +	pte_paddr  = pmd_pte & ENTRY_MASK;
> +	pte_paddr += pte_index(vaddr) * sizeof(unsigned long long);
> +	if (!readmem(PADDR, pte_paddr, &pte, sizeof(pte)))
> +		return NOT_PADDR;
> +
> +	if (!(pte & _PAGE_PRESENT))
> +		return NOT_PADDR;
> +
> +	if (info->vaddr_for_vtop == vaddr)
> +		MSG("  PTE : %16llx => %16llx\n", pte_paddr, pte);
> +
> +	return (pte & ENTRY_MASK) + (vaddr & ((1UL << PTE_SHIFT) - 1));
> +}
> +
> +int
> +is_vmalloc_addr_x86(unsigned long vaddr)
> +{
> +	return (info->vmalloc_start && vaddr >= info->vmalloc_start);
> +}
> +
> +unsigned long long
> +vaddr_to_paddr_x86(unsigned long vaddr)
> +{
> +	unsigned long long paddr;
> +
> +	if ((paddr = vaddr_to_paddr_general(vaddr)) != NOT_PADDR)
> +		return paddr;
> +
> +	if ((SYMBOL(vmlist) == NOT_FOUND_SYMBOL)
> +	    || (OFFSET(vm_struct.addr) == NOT_FOUND_STRUCTURE)) {
> +		ERRMSG("Can't get necessary information for vmalloc translation.\n");
> +		return NOT_PADDR;
> +	}
> +	if (!is_vmalloc_addr_x86(vaddr))
> +		return (vaddr - info->kernel_start);
> +
> +	if (vt.mem_flags & MEMORY_X86_PAE) {
> +		paddr = vtop_x86_PAE(vaddr);
> +	} else {
> +		/*
> +		 * TODO: Support vmalloc translation of not-PAE kernel.
> +		 */
> +		ERRMSG("This makedumpfile does not support vmalloc ");
> +		ERRMSG("translation of not-PAE kernel.\n");
> +		return NOT_PADDR;
> +	}
> +	return paddr;
> +}
> +
>  /*
>   * for Xen extraction
>   */
> 
> 
> 
> 
> 
> ------------------------------------------------------------------------
> 
> _______________________________________________
> kexec mailing list
> kexec at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/kexec






More information about the kexec mailing list