Problems writing ELF dumps with makedumpfile 1.2.9

Ken'ichi Ohmichi oomichi at mxs.nes.nec.co.jp
Wed Sep 24 03:35:56 EDT 2008


Hi Kevin,

Worth, Kevin 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.


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





More information about the kexec mailing list