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