diff -uNrp kexec-tools-testing-20070330.orig/kexec/crashdump-elf.c kexec-tools-testing-20070330/kexec/crashdump-elf.c --- kexec-tools-testing-20070330.orig/kexec/crashdump-elf.c 2008-08-26 20:35:33.000000000 +0900 +++ kexec-tools-testing-20070330/kexec/crashdump-elf.c 2008-08-26 20:36:28.000000000 +0900 @@ -38,6 +38,8 @@ int FUNC(struct kexec_info *info, uint64_t notes_addr, notes_len; uint64_t vmcoreinfo_addr, vmcoreinfo_len; int has_vmcoreinfo = 0; + uint64_t vmcoreinfo_addr_xen, vmcoreinfo_len_xen; + int has_vmcoreinfo_xen = 0; int (*get_note_info)(int cpu, uint64_t *addr, uint64_t *len); if (xen_present()) @@ -53,7 +55,13 @@ int FUNC(struct kexec_info *info, has_vmcoreinfo = 1; } - sz = sizeof(EHDR) + (nr_cpus + has_vmcoreinfo) * sizeof(PHDR) + ranges * sizeof(PHDR); + if (xen_present() && + get_xen_vmcoreinfo(&vmcoreinfo_addr_xen, &vmcoreinfo_len_xen) == 0) { + has_vmcoreinfo_xen = 1; + } + + sz = sizeof(EHDR) + (nr_cpus + has_vmcoreinfo + has_vmcoreinfo_xen) * sizeof(PHDR) + + ranges * sizeof(PHDR); /* * Certain architectures such as x86_64 and ia64 require a separate @@ -169,6 +177,21 @@ int FUNC(struct kexec_info *info, dfprintf_phdr(stdout, "vmcoreinfo header", phdr); } + if (has_vmcoreinfo_xen) { + phdr = (PHDR *) bufp; + bufp += sizeof(PHDR); + phdr->p_type = PT_NOTE; + phdr->p_flags = 0; + phdr->p_offset = phdr->p_paddr = vmcoreinfo_addr_xen; + phdr->p_vaddr = 0; + phdr->p_filesz = phdr->p_memsz = vmcoreinfo_len_xen; + /* Do we need any alignment of segments? */ + phdr->p_align = 0; + + (elf->e_phnum)++; + dfprintf_phdr(stdout, "vmcoreinfo_xen header", phdr); + } + /* Setup an PT_LOAD type program header for the region where * Kernel is mapped if info->kern_size is non-zero. */ diff -uNrp kexec-tools-testing-20070330.orig/kexec/crashdump.c kexec-tools-testing-20070330/kexec/crashdump.c --- kexec-tools-testing-20070330.orig/kexec/crashdump.c 2008-08-26 20:35:33.000000000 +0900 +++ kexec-tools-testing-20070330/kexec/crashdump.c 2008-08-26 20:36:28.000000000 +0900 @@ -109,10 +109,8 @@ int get_crash_notes_per_cpu(int cpu, uin return 0; } -/* Returns the physical address of start of crash notes buffer for a kernel. */ -int get_kernel_vmcoreinfo(uint64_t *addr, uint64_t *len) +static int get_vmcoreinfo(char *kdump_info, uint64_t *addr, uint64_t *len) { - char kdump_info[PATH_MAX]; char line[MAX_LINE]; int count; FILE *fp; @@ -121,7 +119,6 @@ int get_kernel_vmcoreinfo(uint64_t *addr *addr = 0; *len = 0; - sprintf(kdump_info, "/sys/kernel/vmcoreinfo"); fp = fopen(kdump_info, "r"); if (!fp) return -1; @@ -137,3 +134,14 @@ int get_kernel_vmcoreinfo(uint64_t *addr return 0; } + +/* Returns the physical address of start of crash notes buffer for a kernel. */ +int get_kernel_vmcoreinfo(uint64_t *addr, uint64_t *len) +{ + return get_vmcoreinfo("/sys/kernel/vmcoreinfo", addr, len); +} + +int get_xen_vmcoreinfo(uint64_t *addr, uint64_t *len) +{ + return get_vmcoreinfo("/sys/hypervisor/vmcoreinfo", addr, len); +} diff -uNrp kexec-tools-testing-20070330.orig/kexec/crashdump.h kexec-tools-testing-20070330/kexec/crashdump.h --- kexec-tools-testing-20070330.orig/kexec/crashdump.h 2008-08-26 20:35:33.000000000 +0900 +++ kexec-tools-testing-20070330/kexec/crashdump.h 2008-08-26 20:36:28.000000000 +0900 @@ -3,6 +3,7 @@ extern int get_crash_notes_per_cpu(int cpu, uint64_t *addr, uint64_t *len); extern int get_kernel_vmcoreinfo(uint64_t *addr, uint64_t *len); +extern int get_xen_vmcoreinfo(uint64_t *addr, uint64_t *len); /* Need to find a better way to determine per cpu notes section size. */ #define MAX_NOTE_BYTES 1024 diff -uNrp kexec-tools-testing-20070330.orig/makedumpfile/makedumpfile.c kexec-tools-testing-20070330/makedumpfile/makedumpfile.c --- kexec-tools-testing-20070330.orig/makedumpfile/makedumpfile.c 2008-08-26 20:35:33.000000000 +0900 +++ kexec-tools-testing-20070330/makedumpfile/makedumpfile.c 2008-08-26 20:38:36.000000000 +0900 @@ -1,4 +1,4 @@ -/* +/* * makedumpfile.c * * Copyright (C) 2006, 2007 NEC Corporation @@ -210,8 +210,11 @@ readmem(int type_addr, unsigned long lon } break; case VADDR_XEN: - if (!(paddr = kvtop_xen(addr))) + if (!(paddr = kvtop_xen(addr))) { + ERRMSG("Can't convert a virtual address(%llx) to offset.\n", + addr); return FALSE; + } if (!(offset = paddr_to_offset(paddr))) { ERRMSG("Can't convert a physical address(%llx) to offset.\n", @@ -259,7 +262,7 @@ get_kernel_version(char *release) if (min == LONG_MAX) return FALSE; - start = end + 1; + start = end + 1; rel = strtol(start, &end, 10); if (rel == LONG_MAX) return FALSE; @@ -320,7 +323,7 @@ check_release() if (info->kernel_version == FALSE) { if (!info->flag_read_vmcoreinfo) ERRMSG("Or %s and %s don't match.\n", - dwarf_info.vmlinux_name, info->name_memory); + info->name_vmlinux, info->name_memory); return FALSE; } @@ -419,6 +422,15 @@ print_usage() MSG(" [--xen-vmcoreinfo VMCOREINFO]:\n"); MSG(" Specify the VMCOREINFO of Xen to analyze Xen's memory usage.\n"); MSG("\n"); + MSG(" [--xen_phys_start XEN_PHYS_START_ADDRESS]:\n"); + MSG(" This option is only for x86_64.\n"); + MSG(" Specify the XEN_PHYS_START_ADDRESS, if the xen code/data is relocatable\n"); + MSG(" and VMCORE does not contain XEN_PHYS_START_ADDRESS in the CRASHINFO.\n"); + MSG("\n"); + MSG(" [-X]:\n"); + MSG(" Exclude all the user domain pages from Xen kdump's VMCORE, and extract\n"); + MSG(" the part of Xen and domain-0.\n"); + MSG("\n"); MSG(" [--message-level ML]:\n"); MSG(" Specify the message types.\n"); MSG(" Users can restrict output printed by specifying Message_Level (ML) with\n"); @@ -489,12 +501,22 @@ open_kernel_file() { int fd; - if ((fd = open(dwarf_info.vmlinux_name, O_RDONLY)) < 0) { - ERRMSG("Can't open the kernel file(%s). %s\n", - dwarf_info.vmlinux_name, strerror(errno)); - return FALSE; + if (info->name_vmlinux) { + if ((fd = open(info->name_vmlinux, O_RDONLY)) < 0) { + ERRMSG("Can't open the kernel file(%s). %s\n", + info->name_vmlinux, strerror(errno)); + return FALSE; + } + info->fd_vmlinux = fd; + } + if (info->name_xen_syms) { + if ((fd = open(info->name_xen_syms, O_RDONLY)) < 0) { + ERRMSG("Can't open the kernel file(%s). %s\n", + info->name_xen_syms, strerror(errno)); + return FALSE; + } + info->fd_xen_syms = fd; } - dwarf_info.vmlinux_fd = fd; return TRUE; } @@ -609,7 +631,7 @@ open_files_for_creating_dumpfile() if (info->flag_read_vmcoreinfo) { if (!open_vmcoreinfo("r")) return FALSE; - } else if (dwarf_info.vmlinux_name) { + } else { if (!open_kernel_file()) return FALSE; } @@ -822,7 +844,8 @@ int get_elf_info() { int i, j, phnum, num_load, elf_format; - unsigned long tmp; + off_t offset_note; + unsigned long tmp, size_note; Elf64_Phdr load64; Elf32_Phdr load32; @@ -854,6 +877,8 @@ get_elf_info() strerror(errno)); goto out; } + offset_note = 0; + size_note = 0; for (i = 0, j = 0; i < phnum; i++) { if (info->flag_elf64) { /* ELF64 */ if (!get_elf64_phdr(info->fd_memory, info->name_memory, @@ -861,6 +886,10 @@ get_elf_info() ERRMSG("Can't find Phdr %d.\n", i); goto out; } + if (load64.p_type == PT_NOTE) { + offset_note = load64.p_offset; + size_note = load64.p_filesz; + } if (load64.p_type != PT_LOAD) continue; @@ -882,6 +911,10 @@ get_elf_info() ERRMSG("Can't find Phdr %d.\n", i); goto out; } + if (load32.p_type == PT_NOTE) { + offset_note = load32.p_offset; + size_note = load32.p_filesz; + } if (load32.p_type != PT_LOAD) continue; @@ -899,6 +932,14 @@ get_elf_info() j++; } } + if (offset_note == 0 || size_note == 0) { + ERRMSG("Can't find PT_NOTE Phdr.\n"); + goto out; + } + if (!get_pt_note_info(offset_note, size_note)) { + ERRMSG("Can't get PT_NOTE information.\n"); + goto out; + } /* * FIXME @@ -939,14 +980,14 @@ get_symbol_addr(char *symname) char *sym_name = NULL; const off_t failed = (off_t)-1; - if (lseek(dwarf_info.vmlinux_fd, 0, SEEK_SET) == failed) { + if (lseek(dwarf_info.fd_debuginfo, 0, SEEK_SET) == failed) { ERRMSG("Can't seek the kernel file(%s). %s\n", - dwarf_info.vmlinux_name, strerror(errno)); + dwarf_info.name_debuginfo, strerror(errno)); return NOT_FOUND_SYMBOL; } - if (!(elfd = elf_begin(dwarf_info.vmlinux_fd, ELF_C_READ, NULL))) { + if (!(elfd = elf_begin(dwarf_info.fd_debuginfo, ELF_C_READ, NULL))) { ERRMSG("Can't get first elf header of %s.\n", - dwarf_info.vmlinux_name); + dwarf_info.name_debuginfo); return NOT_FOUND_SYMBOL; } while ((scn = elf_nextscn(elfd, scn)) != NULL) { @@ -1005,14 +1046,14 @@ get_next_symbol_addr(char *symname) char *sym_name = NULL; const off_t failed = (off_t)-1; - if (lseek(dwarf_info.vmlinux_fd, 0, SEEK_SET) == failed) { + if (lseek(dwarf_info.fd_debuginfo, 0, SEEK_SET) == failed) { ERRMSG("Can't seek the kernel file(%s). %s\n", - dwarf_info.vmlinux_name, strerror(errno)); + dwarf_info.name_debuginfo, strerror(errno)); return NOT_FOUND_SYMBOL; } - if (!(elfd = elf_begin(dwarf_info.vmlinux_fd, ELF_C_READ, NULL))) { + if (!(elfd = elf_begin(dwarf_info.fd_debuginfo, ELF_C_READ, NULL))) { ERRMSG("Can't get first elf header of %s.\n", - dwarf_info.vmlinux_name); + dwarf_info.name_debuginfo); return NOT_FOUND_SYMBOL; } while ((scn = elf_nextscn(elfd, scn)) != NULL) { @@ -1220,7 +1261,7 @@ __search_mapping(Dwarf *dwarfd, Dwarf_Di continue; return TRUE; - } while (!dwarf_siblingof(walker, walker)); + } while (!dwarf_siblingof(walker, walker)); return FALSE; } @@ -1248,7 +1289,7 @@ search_mapping(Dwarf *dwarfd, Dwarf_Die continue; if (__search_mapping(dwarfd, &die_struct, offset)) return TRUE; - } while (!dwarf_siblingof(walker, walker)); + } while (!dwarf_siblingof(walker, walker)); return FALSE; } @@ -1265,7 +1306,7 @@ search_member(Dwarf *dwarfd, Dwarf_Die * return; walker = &child; - + do { tag = dwarf_tag(walker); name = dwarf_diename(walker); @@ -1323,7 +1364,7 @@ search_member(Dwarf *dwarfd, Dwarf_Die * continue; return; } - } while (!dwarf_siblingof(walker, walker)); + } while (!dwarf_siblingof(walker, walker)); /* * Return even if not found. @@ -1458,7 +1499,7 @@ search_number(Dwarf *dwarfd, Dwarf_Die * *found = TRUE; dwarf_info.enum_number = (long)const_value; - } while (!dwarf_siblingof(walker, walker)); + } while (!dwarf_siblingof(walker, walker)); } while (!dwarf_siblingof(die, die)); } @@ -1551,9 +1592,9 @@ search_symbol(Dwarf *dwarfd, Dwarf_Die * static void search_die_tree(Dwarf *dwarfd, Dwarf_Die *die, int *found) { - Dwarf_Die child; + Dwarf_Die child; - /* + /* * start by looking at the children */ if (dwarf_child(die, &child) == 0) @@ -1592,14 +1633,14 @@ get_debug_info(void) int ret = FALSE; - if (lseek(dwarf_info.vmlinux_fd, 0, SEEK_SET) == failed) { + if (lseek(dwarf_info.fd_debuginfo, 0, SEEK_SET) == failed) { ERRMSG("Can't seek the kernel file(%s). %s\n", - dwarf_info.vmlinux_name, strerror(errno)); + dwarf_info.name_debuginfo, strerror(errno)); return FALSE; } - if (!(elfd = elf_begin(dwarf_info.vmlinux_fd, ELF_C_READ_MMAP, NULL))) { + if (!(elfd = elf_begin(dwarf_info.fd_debuginfo, ELF_C_READ_MMAP, NULL))) { ERRMSG("Can't get first elf header of %s.\n", - dwarf_info.vmlinux_name); + dwarf_info.name_debuginfo); return FALSE; } if (!(dwarfd = dwarf_begin_elf(elfd, DWARF_C_READ, NULL))) { @@ -1902,22 +1943,22 @@ get_str_osrelease_from_vmlinux() ERRMSG("Can't get the symbol of system_utsname.\n"); return FALSE; } - offset = vaddr_to_offset_slow(dwarf_info.vmlinux_fd, - dwarf_info.vmlinux_name, utsname); + offset = vaddr_to_offset_slow(dwarf_info.fd_debuginfo, + dwarf_info.name_debuginfo, utsname); if (!offset) { ERRMSG("Can't convert vaddr (%lx) of utsname to an offset.\n", utsname); return FALSE; } - if (lseek(dwarf_info.vmlinux_fd, offset, SEEK_SET) == failed) { - ERRMSG("Can't seek %s. %s\n", dwarf_info.vmlinux_name, + if (lseek(dwarf_info.fd_debuginfo, offset, SEEK_SET) == failed) { + ERRMSG("Can't seek %s. %s\n", dwarf_info.name_debuginfo, strerror(errno)); return FALSE; } - if (read(dwarf_info.vmlinux_fd, &system_utsname, sizeof system_utsname) + if (read(dwarf_info.fd_debuginfo, &system_utsname, sizeof system_utsname) != sizeof system_utsname) { - ERRMSG("Can't read %s. %s\n", dwarf_info.vmlinux_name, + ERRMSG("Can't read %s. %s\n", dwarf_info.name_debuginfo, strerror(errno)); return FALSE; } @@ -1983,6 +2024,9 @@ generate_vmcoreinfo() ERRMSG("Can't get the size of page.\n"); return FALSE; } + dwarf_info.fd_debuginfo = info->fd_vmlinux; + dwarf_info.name_debuginfo = info->name_vmlinux; + if (!get_symbol_info()) return FALSE; @@ -2116,6 +2160,8 @@ read_vmcoreinfo_basic_info() while (fgets(buf, BUFSIZE_FGETS, info->file_vmcoreinfo)) { i = strlen(buf); + if (!i) + break; if (buf[i - 1] == '\n') buf[i - 1] = '\0'; if (strncmp(buf, STR_OSRELEASE, strlen(STR_OSRELEASE)) == 0) { @@ -2173,6 +2219,8 @@ read_vmcoreinfo_symbol(char *str_symbol) while (fgets(buf, BUFSIZE_FGETS, info->file_vmcoreinfo)) { i = strlen(buf); + if (!i) + break; if (buf[i - 1] == '\n') buf[i - 1] = '\0'; if (strncmp(buf, str_symbol, strlen(str_symbol)) == 0) { @@ -2204,6 +2252,8 @@ read_vmcoreinfo_structure(char *str_stru while (fgets(buf, BUFSIZE_FGETS, info->file_vmcoreinfo)) { i = strlen(buf); + if (!i) + break; if (buf[i - 1] == '\n') buf[i - 1] = '\0'; if (strncmp(buf, str_structure, strlen(str_structure)) == 0) { @@ -2233,6 +2283,8 @@ read_vmcoreinfo_string(char *str_in, cha while (fgets(buf, BUFSIZE_FGETS, info->file_vmcoreinfo)) { i = strlen(buf); + if (!i) + break; if (buf[i - 1] == '\n') buf[i - 1] = '\0'; if (strncmp(buf, str_in, strlen(str_in)) == 0) { @@ -2313,93 +2365,32 @@ read_vmcoreinfo() } int -get_pt_note_info(int *flag_elf64, off_t *offset, unsigned long *size) +get_pt_note_info(off_t off_note, unsigned long sz_note) { - Elf64_Phdr phdr64; - Elf32_Phdr phdr32; - int i, phnum, num_load, elf_format; - - (*offset) = 0; - (*size) = 0; - - elf_format = check_elf_format(info->fd_memory, info->name_memory, - &phnum, &num_load); - - if (elf_format == ELF64) - (*flag_elf64) = TRUE; - else if (elf_format == ELF32) - (*flag_elf64) = FALSE; - else - return FALSE; - - for (i = 0; i < phnum; i++) { - if (flag_elf64) { /* ELF64 */ - if (!get_elf64_phdr(info->fd_memory, info->name_memory, - i, &phdr64)) { - ERRMSG("Can't find Phdr %d.\n", i); - return FALSE; - } - if (phdr64.p_type != PT_NOTE) - continue; - - (*offset) = phdr64.p_offset; - (*size) = phdr64.p_filesz; - break; - } else { /* ELF32 */ - if (!get_elf32_phdr(info->fd_memory, info->name_memory, - i, &phdr32)) { - ERRMSG("Can't find Phdr %d.\n", i); - return FALSE; - } - if (phdr32.p_type != PT_NOTE) - continue; - - (*offset) = phdr32.p_offset; - (*size) = phdr32.p_filesz; - break; - } - } - if (*offset == 0 || *size == 0) { - ERRMSG("Can't find PT_NOTE Phdr.\n"); - return FALSE; - } - return TRUE; -} - -int -is_vmcoreinfo_in_vmcore(int *flag_found) -{ - off_t offset, off_note; - int flag_elf64; - unsigned long sz_note; - char buf[VMCOREINFO_NOTE_NAME_BYTES]; + int n_type; + off_t offset; + char buf[VMCOREINFO_XEN_NOTE_NAME_BYTES]; Elf64_Nhdr note64; Elf32_Nhdr note32; const off_t failed = (off_t)-1; - (*flag_found) = FALSE; - - /* - * Get information about PT_NOTE segment. - */ - if (!get_pt_note_info(&flag_elf64, &off_note, &sz_note)) - return FALSE; - offset = off_note; + n_type = 0; while (offset < off_note + sz_note) { if (lseek(info->fd_memory, offset, SEEK_SET) == failed) { ERRMSG("Can't seek the dump memory(%s). %s\n", info->name_memory, strerror(errno)); return FALSE; } - if (flag_elf64) { + if (info->flag_elf64) { if (read(info->fd_memory, ¬e64, sizeof(note64)) != sizeof(note64)) { ERRMSG("Can't read the dump memory(%s). %s\n", info->name_memory, strerror(errno)); return FALSE; } + n_type = note64.n_type; } else { if (read(info->fd_memory, ¬e32, sizeof(note32)) != sizeof(note32)) { @@ -2407,37 +2398,80 @@ is_vmcoreinfo_in_vmcore(int *flag_found) info->name_memory, strerror(errno)); return FALSE; } + n_type = note32.n_type; } if (read(info->fd_memory, &buf, sizeof(buf)) != sizeof(buf)) { ERRMSG("Can't read the dump memory(%s). %s\n", info->name_memory, strerror(errno)); return FALSE; } - if (strncmp(VMCOREINFO_NOTE_NAME, buf, + /* + * Check whether /proc/vmcore contains vmcoreinfo, + * and get both the offset and the size. + * + * NOTE: The owner name of xen should be checked at first, + * because its name is "VMCOREINFO_XEN" and the one + * of linux is "VMCOREINFO". + */ + if (!strncmp(VMCOREINFO_XEN_NOTE_NAME, buf, + VMCOREINFO_XEN_NOTE_NAME_BYTES)) { + if (info->flag_elf64) { + info->offset_vmcoreinfo_xen = offset + + (sizeof(note64) + + ((note64.n_namesz + 3) & ~3)); + info->size_vmcoreinfo_xen = note64.n_descsz; + } else { + info->offset_vmcoreinfo_xen = offset + + (sizeof(note32) + + ((note32.n_namesz + 3) & ~3)); + info->size_vmcoreinfo_xen = note32.n_descsz; + } + } else if (!strncmp(VMCOREINFO_NOTE_NAME, buf, VMCOREINFO_NOTE_NAME_BYTES)) { - if (flag_elf64) { - offset += sizeof(Elf64_Nhdr) - + ((note64.n_namesz + 3) & ~3) - + ((note64.n_descsz + 3) & ~3); + if (info->flag_elf64) { + info->offset_vmcoreinfo = offset + + (sizeof(note64) + + ((note64.n_namesz + 3) & ~3)); + info->size_vmcoreinfo = note64.n_descsz; } else { - offset += sizeof(Elf32_Nhdr) - + ((note32.n_namesz + 3) & ~3) - + ((note32.n_descsz + 3) & ~3); + info->offset_vmcoreinfo = offset + + (sizeof(note32) + + ((note32.n_namesz + 3) & ~3)); + info->size_vmcoreinfo = note32.n_descsz; + } + /* + * Check whether /proc/vmcore contains xen's note. + */ + } else if (n_type == XEN_ELFNOTE_CRASH_INFO) { + vt.mem_flags |= MEMORY_XEN; + if (info->flag_elf64) { + info->offset_xen_crash_info = offset + + (sizeof(note64) + + ((note64.n_namesz + 3) & ~3)); + info->size_xen_crash_info = note64.n_descsz; + } else { + info->offset_xen_crash_info = offset + + (sizeof(note32) + + ((note32.n_namesz + 3) & ~3)); + info->size_xen_crash_info = note32.n_descsz; } - continue; } - if (flag_elf64) { - info->offset_vmcoreinfo = offset + (sizeof(note64) - + ((note64.n_namesz + 3) & ~3)); - info->size_vmcoreinfo = note64.n_descsz; + + if (info->flag_elf64) { + offset += sizeof(Elf64_Nhdr) + + ((note64.n_namesz + 3) & ~3) + + ((note64.n_descsz + 3) & ~3); } else { - info->offset_vmcoreinfo = offset + (sizeof(note32) - + ((note32.n_namesz + 3) & ~3)); - info->size_vmcoreinfo = note32.n_descsz; + offset += sizeof(Elf32_Nhdr) + + ((note32.n_namesz + 3) & ~3) + + ((note32.n_descsz + 3) & ~3); } - (*flag_found) = TRUE; - break; } + if (vt.mem_flags & MEMORY_XEN) + DEBUG_MSG("Xen kdump\n"); + else + DEBUG_MSG("Linux kdump\n"); + return TRUE; } @@ -2445,45 +2479,46 @@ is_vmcoreinfo_in_vmcore(int *flag_found) * Extract vmcoreinfo from /proc/vmcore and output it to /tmp/vmcoreinfo.tmp. */ int -copy_vmcoreinfo() +copy_vmcoreinfo(off_t offset, unsigned long size) { int fd; char buf[VMCOREINFO_BYTES]; const off_t failed = (off_t)-1; - if (!info->offset_vmcoreinfo || !info->size_vmcoreinfo) + if (!offset || !size){ + ERRMSG("Can't get offset_vmcoreinfo(%lx) or \ + size_vmcoreinfo(%lx)\n", offset, size); return FALSE; - + } if ((fd = mkstemp(info->name_vmcoreinfo)) < 0) { ERRMSG("Can't open the vmcoreinfo file(%s). %s\n", - info->name_vmcoreinfo, strerror(errno)); + info->name_vmcoreinfo, strerror(errno)); return FALSE; } - if (lseek(info->fd_memory, info->offset_vmcoreinfo, SEEK_SET) - == failed) { + if (lseek(info->fd_memory, offset, SEEK_SET) == failed) { ERRMSG("Can't seek the dump memory(%s). %s\n", - info->name_memory, strerror(errno)); + info->name_memory, strerror(errno)); return FALSE; } - if (read(info->fd_memory, &buf, info->size_vmcoreinfo) - != info->size_vmcoreinfo) { + if (read(info->fd_memory, &buf, size) != size) { ERRMSG("Can't read the dump memory(%s). %s\n", - info->name_memory, strerror(errno)); + info->name_memory, strerror(errno)); return FALSE; } - if (write(fd, &buf, info->size_vmcoreinfo) != info->size_vmcoreinfo) { + if (write(fd, &buf, size) != size) { ERRMSG("Can't write the vmcoreinfo file(%s). %s\n", - info->name_vmcoreinfo, strerror(errno)); + info->name_vmcoreinfo, strerror(errno)); return FALSE; } if (close(fd) < 0) { ERRMSG("Can't close the vmcoreinfo file(%s). %s\n", - info->name_vmcoreinfo, strerror(errno)); + info->name_vmcoreinfo, strerror(errno)); return FALSE; } return TRUE; } + /* * Get the number of online nodes. */ @@ -3165,8 +3200,6 @@ get_mem_map() int initial() { - int vmcoreinfo_in_vmcore = FALSE; - if (!get_elf_info()) return FALSE; @@ -3174,15 +3207,18 @@ initial() return FALSE; /* - * Get the debug information for analysis from the vmcoreinfo file + * Get the debug information for analysis from the vmcoreinfo file */ if (info->flag_read_vmcoreinfo) { if (!read_vmcoreinfo()) return FALSE; /* - * Get the debug information for analysis from the kernel file + * Get the debug information for analysis from the kernel file */ - } else if (info->flag_vmlinux) { + } else if (info->name_vmlinux) { + dwarf_info.fd_debuginfo = info->fd_vmlinux; + dwarf_info.name_debuginfo = info->name_vmlinux; + if (!get_symbol_info()) return FALSE; @@ -3196,19 +3232,6 @@ initial() */ } else { /* - * Check whether /proc/vmcore contains vmcoreinfo, - * and get both the offset and the size. - */ - if (!is_vmcoreinfo_in_vmcore(&vmcoreinfo_in_vmcore)) - return FALSE; - - if (!vmcoreinfo_in_vmcore) { - MSG("%s doesn't contain vmcoreinfo.\n", - info->name_memory); - MSG("'-x' or '-i' must be specified.\n"); - return FALSE; - } - /* * Copy vmcoreinfo to /tmp/vmcoreinfoXXXXXX. */ if ((info->name_vmcoreinfo @@ -3218,7 +3241,8 @@ initial() return FALSE; } strcpy(info->name_vmcoreinfo, FILENAME_VMCOREINFO); - if (!copy_vmcoreinfo()) + if (!copy_vmcoreinfo(info->offset_vmcoreinfo, + info->size_vmcoreinfo)) return FALSE; /* * Read vmcoreinfo from /tmp/vmcoreinfoXXXXXX. @@ -3229,6 +3253,7 @@ initial() return FALSE; unlink(info->name_vmcoreinfo); } + if (info->dump_level <= DL_EXCLUDE_ZERO) { if (!get_mem_map_without_mm()) return FALSE; @@ -3427,7 +3452,7 @@ read_buf_from_stdin(void *buf, int buf_s while (read_size != buf_size) { tmp_read_size = read(STDIN_FILENO, buf + read_size, - buf_size - read_size); + buf_size - read_size); if (tmp_read_size < 0) { ERRMSG("Can't read STDIN. %s\n", strerror(errno)); @@ -3565,7 +3590,7 @@ rearrange_dumpdata() goto out; read_size += tmp_read_size; - } + } /* * Read the next header. */ @@ -3574,7 +3599,7 @@ rearrange_dumpdata() goto out; } - } while ((0 <= fdh.offset) && (0 < fdh.buf_size)); + } while ((0 <= fdh.offset) && (0 < fdh.buf_size)); if ((fdh.offset != END_FLAG_FLAT_HEADER) || (fdh.buf_size != END_FLAG_FLAT_HEADER)) { @@ -4161,7 +4186,7 @@ get_loads_dumpfile() /* * If the number of the contiguous pages to be excluded * is 256 or more, those pages are excluded really. - * And a new PT_LOAD segment is created. + * And a new PT_LOAD segment is created. */ if (num_excluded >= PFN_EXCLUDED) { num_new_load++; @@ -4274,7 +4299,7 @@ write_elf_header() /* * PT_NOTE(1) + PT_LOAD(1+) */ - ehdr64.e_phnum = 1 + num_loads_dumpfile; + ehdr64.e_phnum = 1 + num_loads_dumpfile; } else { /* ELF32 */ if (!get_elf32_ehdr(&ehdr32)) { ERRMSG("Can't get ehdr32.\n"); @@ -4283,7 +4308,7 @@ write_elf_header() /* * PT_NOTE(1) + PT_LOAD(1+) */ - ehdr32.e_phnum = 1 + num_loads_dumpfile; + ehdr32.e_phnum = 1 + num_loads_dumpfile; } /* @@ -4321,7 +4346,7 @@ write_elf_header() offset_note_memory = note64.p_offset; offset_note_dumpfile = sizeof(ehdr64) + sizeof(Elf64_Phdr) * ehdr64.e_phnum; - note64.p_offset = offset_note_dumpfile; + note64.p_offset = offset_note_dumpfile; size_note = note64.p_filesz; if (!write_buffer(info->fd_dumpfile, sizeof(ehdr64), ¬e64, @@ -4346,7 +4371,7 @@ write_elf_header() offset_note_memory = note32.p_offset; offset_note_dumpfile = sizeof(ehdr32) + sizeof(Elf32_Phdr) * ehdr32.e_phnum; - note32.p_offset = offset_note_dumpfile; + note32.p_offset = offset_note_dumpfile; size_note = note32.p_filesz; if (!write_buffer(info->fd_dumpfile, sizeof(ehdr32), ¬e32, @@ -4630,7 +4655,7 @@ write_elf_pages() /* * If the number of the contiguous pages to be excluded * is 256 or more, those pages are excluded really. - * And a new PT_LOAD segment is created. + * And a new PT_LOAD segment is created. */ if (info->flag_elf64) { /* ELF64 */ load64.p_memsz = memsz; @@ -5182,9 +5207,16 @@ close_dump_bitmap() void close_kernel_file() { - if ((dwarf_info.vmlinux_fd = close(dwarf_info.vmlinux_fd)) < 0) - ERRMSG("Can't close the kernel file(%s). %s\n", - dwarf_info.vmlinux_name, strerror(errno)); + if (info->name_vmlinux) { + if ((info->fd_vmlinux = close(info->fd_vmlinux)) < 0) + ERRMSG("Can't close the kernel file(%s). %s\n", + info->name_vmlinux, strerror(errno)); + } + if (info->name_xen_syms) { + if ((info->fd_xen_syms = close(info->fd_xen_syms)) < 0) + ERRMSG("Can't close the kernel file(%s). %s\n", + info->name_xen_syms, strerror(errno)); + } } /* @@ -5263,7 +5295,12 @@ get_symbol_info_xen() */ SYMBOL_INIT(pgd_l2, "idle_pg_table_l2"); /* x86 */ SYMBOL_INIT(pgd_l3, "idle_pg_table_l3"); /* x86-PAE */ + if (SYMBOL(pgd_l3) == NOT_FOUND_SYMBOL) + SYMBOL_INIT(pgd_l3, "idle_pg_table"); /* x86-PAE */ SYMBOL_INIT(pgd_l4, "idle_pg_table_4"); /* x86_64 */ + if (SYMBOL(pgd_l4) == NOT_FOUND_SYMBOL) + SYMBOL_INIT(pgd_l4, "idle_pg_table"); /* x86_64 */ + SYMBOL_INIT(xen_heap_start, "xen_heap_start"); /* ia64 */ SYMBOL_INIT(xen_pstart, "xen_pstart"); /* ia64 */ SYMBOL_INIT(frametable_pg_dir, "frametable_pg_dir"); /* ia64 */ @@ -5289,6 +5326,39 @@ get_structure_info_xen() } int +get_xen_phys_start(void) +{ + off_t offset; + unsigned long xen_phys_start; + const off_t failed = (off_t)-1; + + if (info->xen_phys_start) + return TRUE; + + if (info->size_xen_crash_info >= SIZE_XEN_CRASH_INFO_V2) { + offset = info->offset_xen_crash_info + info->size_xen_crash_info + - sizeof(unsigned long) * 2; + if (lseek(info->fd_memory, offset, SEEK_SET) == failed) { + ERRMSG("Can't seek the dump memory(%s). %s\n", + info->name_memory, strerror(errno)); + return FALSE; + } + if (read(info->fd_memory, &xen_phys_start, sizeof(unsigned long)) + != sizeof(unsigned long)) { + ERRMSG("Can't read the dump memory(%s). %s\n", + info->name_memory, strerror(errno)); + return FALSE; + } + info->xen_phys_start = xen_phys_start; + } else { + ERRMSG("info->size_xen_crash_info=%lx \n", info->size_xen_crash_info); + } + + ERRMSG("xen_phys_start=%lx \n", info->xen_phys_start); + return TRUE; +} + +int get_xen_info() { unsigned long domain; @@ -5358,6 +5428,7 @@ get_xen_info() ERRMSG("Can't get the domain_id.\n"); return FALSE; } + info->domain_list[num_domain].domain_addr = domain; info->domain_list[num_domain].domain_id = domain_id; /* @@ -5379,10 +5450,12 @@ get_xen_info() ERRMSG("Can't get the symbol of dom_xen.\n"); return FALSE; } + if (!readmem(VADDR_XEN, SYMBOL(dom_xen), &domain, sizeof(domain))) { ERRMSG("Can't get the value of dom_xen.\n"); return FALSE; } + if (!readmem(VADDR_XEN, domain + OFFSET(domain.domain_id), &domain_id, sizeof(domain_id))) { ERRMSG( "Can't get the value of dom_xen domain_id.\n"); @@ -5448,6 +5521,7 @@ show_data_xen() MSG("OFFSET(domain.next_in_list): %ld\n", OFFSET(domain.next_in_list)); MSG("\n"); + MSG("xen_phys_start: %lx\n", info->xen_phys_start); MSG("frame_table_vaddr: %lx\n", info->frame_table_vaddr); MSG("xen_heap_start: %lx\n", info->xen_heap_start); MSG("xen_heap_end:%lx\n", info->xen_heap_end); @@ -5468,6 +5542,8 @@ generate_vmcoreinfo_xen() ERRMSG("Can't get the size of page.\n"); return FALSE; } + dwarf_info.fd_debuginfo = info->fd_xen_syms; + dwarf_info.name_debuginfo = info->name_xen_syms; if (!get_symbol_info_xen()) return FALSE; @@ -5530,6 +5606,8 @@ read_vmcoreinfo_basic_info_xen() while (fgets(buf, BUFSIZE_FGETS, info->file_vmcoreinfo)) { i = strlen(buf); + if (!i) + break; if (buf[i - 1] == '\n') buf[i - 1] = '\0'; if (strncmp(buf, STR_PAGESIZE, strlen(STR_PAGESIZE)) == 0) { @@ -5615,7 +5693,7 @@ is_select_domain(unsigned int id) int i; /* selected domain is fix to dom0 only now !! - (yes... domain_list is not necessary right now, + (yes... domain_list is not necessary right now, it can get from "dom0" directly) */ for (i = 0; i < info->num_domain; i++) { @@ -5791,15 +5869,48 @@ initial_xen() if (!get_elf_info()) return FALSE; + /* + * Get the debug information for analysis from the vmcoreinfo file + */ if (info->flag_read_vmcoreinfo) { if (!read_vmcoreinfo_xen()) return FALSE; - } else { + /* + * Get the debug information for analysis from the xen-syms file + */ + } else if (info->name_xen_syms) { + dwarf_info.fd_debuginfo = info->fd_xen_syms; + dwarf_info.name_debuginfo = info->name_xen_syms; + if (!get_symbol_info_xen()) return FALSE; if (!get_structure_info_xen()) return FALSE; + /* + * Copy vmcoreinfo to /tmp/vmcoreinfoXXXXXX. + */ + } else { + if ((info->name_vmcoreinfo + = malloc(sizeof(FILENAME_VMCOREINFO))) == NULL) { + ERRMSG("Can't allocate memory for the name(%s). %s\n", + FILENAME_VMCOREINFO, strerror(errno)); + return FALSE; + } + strcpy(info->name_vmcoreinfo, FILENAME_VMCOREINFO); + if (!copy_vmcoreinfo(info->offset_vmcoreinfo_xen, + info->size_vmcoreinfo_xen)) + return FALSE; + /* + * Read vmcoreinfo from /tmp/vmcoreinfoXXXXXX. + */ + if (!open_vmcoreinfo("r")) + return FALSE; + if (!read_vmcoreinfo_xen()) + return FALSE; + unlink(info->name_vmcoreinfo); } + if (!get_xen_phys_start()) + return FALSE; if (!get_xen_info()) return FALSE; @@ -5849,15 +5960,16 @@ handle_xen() MSG("\n"); MSG("The dumpfile is saved to %s.\n", info->name_dumpfile); - return COMPLETED; + return TRUE; out: return FALSE; #endif } static struct option longopts[] = { - {"xen-syms", required_argument, NULL, 'X'}, + {"xen-syms", required_argument, NULL, 'y'}, {"xen-vmcoreinfo", required_argument, NULL, 'z'}, + {"xen_phys_start", required_argument, NULL, 'P'}, {"message-level", required_argument, NULL, 'm'}, {"help", no_argument, NULL, 'h'}, {0, 0, 0, 0} @@ -5882,7 +5994,7 @@ main(int argc, char *argv[]) info->block_order = DEFAULT_ORDER; message_level = DEFAULT_MSG_LEVEL; - while ((opt = getopt_long(argc, argv, "b:cDd:EFfg:hi:Rvx:", longopts, + while ((opt = getopt_long(argc, argv, "b:cDd:EFfg:hi:RvXx:y:", longopts, NULL)) != -1) { switch (opt) { case 'b': @@ -5922,6 +6034,9 @@ main(int argc, char *argv[]) case 'm': message_level = atoi(optarg); break; + case 'P': + info->xen_phys_start = strtoul(optarg, NULL, 0); + break; case 'R': info->flag_rearrange = 1; break; @@ -5929,15 +6044,15 @@ main(int argc, char *argv[]) info->flag_show_version = 1; break; case 'X': - info->flag_xen = 1; - dwarf_info.vmlinux_name = optarg; + info->flag_exclude_xen_dom = 1; break; case 'x': - info->flag_vmlinux = 1; - dwarf_info.vmlinux_name = optarg; + info->name_vmlinux = optarg; + break; + case 'y': + info->name_xen_syms = optarg; break; case 'z': - info->flag_xen = 1; info->flag_read_vmcoreinfo = 1; info->name_vmcoreinfo = optarg; break; @@ -5969,8 +6084,9 @@ main(int argc, char *argv[]) } if (info->flag_compress || info->dump_level || info->flag_elf_dumpfile || info->flag_read_vmcoreinfo - || !dwarf_info.vmlinux_name || info->flag_flatten - || info->flag_rearrange) { + || info->flag_flatten || info->flag_rearrange + || info->flag_exclude_xen_dom + || (!info->name_vmlinux && !info->name_xen_syms)){ MSG("Commandline parameter is invalid.\n"); print_usage(); goto out; @@ -5993,7 +6109,7 @@ main(int argc, char *argv[]) goto out; } if ((info->flag_compress && info->flag_elf_dumpfile) - || (info->flag_vmlinux && info->flag_read_vmcoreinfo)) { + || (info->name_vmlinux && info->flag_read_vmcoreinfo)) { MSG("Commandline parameter is invalid.\n"); print_usage(); goto out; @@ -6012,12 +6128,12 @@ main(int argc, char *argv[]) * Parameters for outputting the dump data of the * flattened format to STDOUT. */ - info->name_memory = argv[optind]; + info->name_memory = argv[optind]; } else if ((argc == optind + 1) && !info->flag_flatten && info->flag_rearrange && !info->dump_level && !info->flag_compress - && !info->flag_vmlinux && !info->flag_read_vmcoreinfo + && !info->name_vmlinux && !info->flag_read_vmcoreinfo && !info->flag_elf_dumpfile) { /* * Parameters for creating dumpfile from the dump data @@ -6043,7 +6159,7 @@ main(int argc, char *argv[]) if (!open_files_for_generating_vmcoreinfo()) goto out; - if (info->flag_xen) { + if (info->name_xen_syms ) { if (!generate_vmcoreinfo_xen()) goto out; } else { @@ -6057,7 +6173,7 @@ main(int argc, char *argv[]) MSG("\n"); MSG("The vmcoreinfo is saved to %s.\n", info->name_vmcoreinfo); - } else if (info->flag_xen) { + } else if (info->flag_exclude_xen_dom ) { if (!info->flag_elf_dumpfile) { MSG("-E must be specified with --xen-syms or --xen-vmcoreinfo.\n"); goto out; @@ -6067,8 +6183,8 @@ main(int argc, char *argv[]) print_usage(); goto out; } - info->dump_level |= DL_EXCLUDE_XEN; - return handle_xen(); + if (!handle_xen()) + goto out; } else if (info->flag_rearrange) { if (!open_files_for_rearranging_dumpdata()) @@ -6140,6 +6256,9 @@ out: free(info->mem_map_data); if (info->dump_header != NULL) free(info->dump_header); + if (info->name_vmcoreinfo) { + unlink(info->name_vmcoreinfo); + } if (info != NULL) free(info); diff -uNrp kexec-tools-testing-20070330.orig/makedumpfile/makedumpfile.h kexec-tools-testing-20070330/makedumpfile/makedumpfile.h --- kexec-tools-testing-20070330.orig/makedumpfile/makedumpfile.h 2007-09-07 17:37:08.000000000 +0900 +++ kexec-tools-testing-20070330/makedumpfile/makedumpfile.h 2008-08-26 20:36:28.000000000 +0900 @@ -71,6 +71,7 @@ enum { #define MEMORY_PAGETABLE_4L (1 << 0) #define MEMORY_PAGETABLE_3L (1 << 1) #define MEMORY_X86_PAE (1 << 2) +#define MEMORY_XEN (1 << 3) /* * Type of address @@ -406,7 +407,11 @@ do { \ #define VMCOREINFO_BYTES (4096) #define VMCOREINFO_NOTE_NAME "VMCOREINFO" #define VMCOREINFO_NOTE_NAME_BYTES (sizeof(VMCOREINFO_NOTE_NAME)) +#define VMCOREINFO_XEN_NOTE_NAME "VMCOREINFO_XEN" +#define VMCOREINFO_XEN_NOTE_NAME_BYTES (sizeof(VMCOREINFO_XEN_NOTE_NAME)) #define FILENAME_VMCOREINFO "/tmp/vmcoreinfoXXXXXX" +#define VMCOREINFO_LINUX (0x01) +#define VMCOREINFO_XEN (0x02) /* * field name of vmcoreinfo file @@ -440,6 +445,9 @@ do { \ #define ELF64 (2) #define STRLEN_OSRELEASE (65) /* same length as diskdump.h */ +#define XEN_ELFNOTE_CRASH_INFO (0x1000001) +#define SIZE_XEN_CRASH_INFO_V2 (sizeof(unsigned long) * 10) + /* * The value of dependence on machine */ @@ -634,7 +642,6 @@ struct DumpInfo { int flag_compress; /* flag of compression */ int flag_elf64; /* flag of ELF64 memory */ int flag_elf_dumpfile; /* flag of creating ELF dumpfile */ - int flag_vmlinux; /* flag of vmlinux */ int flag_generate_vmcoreinfo;/* flag of generating vmcoreinfo file */ int flag_read_vmcoreinfo; /* flag of reading vmcoreinfo file */ int flag_exclude_free; /* flag of excluding free page */ @@ -645,7 +652,7 @@ struct DumpInfo { int flag_rearrange; /* flag of creating dumpfile from flattened format */ int flag_force; /* overwrite existing stuff */ - int flag_xen; + int flag_exclude_xen_dom;/* exclude Domain-U from xen-kdump */ long page_size; /* size of page */ long page_shift; unsigned long long max_mapnr; /* number of page descriptor */ @@ -679,6 +686,10 @@ struct DumpInfo { unsigned int num_mem_map; struct mem_map_data *mem_map_data; + int fd_vmlinux; + char *name_vmlinux; + int fd_xen_syms; + char *name_xen_syms; /* * Dump memory image info: */ @@ -710,10 +721,15 @@ struct DumpInfo { */ off_t offset_vmcoreinfo; unsigned long size_vmcoreinfo; + off_t offset_vmcoreinfo_xen; + unsigned long size_vmcoreinfo_xen; /* * for Xen extraction */ + off_t offset_xen_crash_info; + unsigned long size_xen_crash_info; + unsigned long xen_phys_start; unsigned long xen_heap_start; /* start mfn of xen heap area */ unsigned long xen_heap_end; /* end mfn(+1) of xen heap area */ unsigned long frame_table_vaddr; @@ -898,8 +914,8 @@ enum { struct dwarf_info { unsigned int cmd; /* IN */ - int vmlinux_fd; /* IN */ - char *vmlinux_name; /* IN */ + int fd_debuginfo; /* IN */ + char *name_debuginfo; /* IN */ char *struct_name; /* IN */ char *symbol_name; /* IN */ char *member_name; /* IN */ @@ -920,6 +936,7 @@ int check_elf_format(int fd, char *filen int get_elf64_phdr(int fd, char *filename, int num, Elf64_Phdr *phdr); int get_elf32_phdr(int fd, char *filename, int num, Elf32_Phdr *phdr); int get_str_osrelease_from_vmlinux(); +int get_pt_note_info(off_t off_note, unsigned long sz_note); /* * for Xen extraction @@ -990,11 +1007,14 @@ int get_xen_info_x86(); #define HYPERVISOR_VIRT_END (0xffff880000000000) #define DIRECTMAP_VIRT_START (0xffff830000000000) #define DIRECTMAP_VIRT_END (0xffff840000000000) +#define XEN_VIRT_START (0xffff828c80000000) #define is_xen_vaddr(x) \ ((x) >= HYPERVISOR_VIRT_START && (x) < HYPERVISOR_VIRT_END) #define is_direct(x) \ ((x) >= DIRECTMAP_VIRT_START && (x) < DIRECTMAP_VIRT_END) +#define is_xen_text(x) \ + ((x) >= XEN_VIRT_START && (x) < DIRECTMAP_VIRT_START) unsigned long long kvtop_xen_x86_64(unsigned long kvaddr); #define kvtop_xen(X) kvtop_xen_x86_64(X) diff -uNrp kexec-tools-testing-20070330.orig/makedumpfile/x86_64.c kexec-tools-testing-20070330/makedumpfile/x86_64.c --- kexec-tools-testing-20070330.orig/makedumpfile/x86_64.c 2008-08-26 20:35:33.000000000 +0900 +++ kexec-tools-testing-20070330/makedumpfile/x86_64.c 2008-08-26 20:36:28.000000000 +0900 @@ -102,11 +102,18 @@ kvtop_xen_x86_64(unsigned long kvaddr) { unsigned long long dirp, entry; - if (!is_xen_vaddr(kvaddr)) + if (!is_xen_vaddr(kvaddr)){ + ERRMSG("!is_xen_vaddr(kvaddr=%lx)\n",kvaddr); return 0; + } + + if (is_xen_text(kvaddr)){ + return (unsigned long)kvaddr - XEN_VIRT_START + info->xen_phys_start; + } - if (is_direct(kvaddr)) + if (is_direct(kvaddr)){ return (unsigned long)kvaddr - DIRECTMAP_VIRT_START; + } dirp = kvtop_xen_x86_64(SYMBOL(pgd_l4)); dirp += pml4_index(kvaddr) * sizeof(unsigned long long);