Hello, Attached is the patch to add separate tool for validating LKCD netdumps and blockdumps. We are planning to add this feature in our fork of crash-3.10. Our customers requested this feature, but we have found that the 'crash' does not print any warnings when someone tries to load incomplete vmcore. They need a simple way to verify if core file generated from LKCD is complete. -- Best regards, Vitaly Kuzmichev, Software Engineer, MontaVista Software, LLC.
Source: MontaVista Software, Inc. MR: 37433 Type: Enhancement Disposition: needs submitting to lkcd.sourceforge.net Signed-off-by: Vitaly Kuzmichev <vkuzmichev@xxxxxxxxxx> Description: Adding LKCD Vmcore validation (completeness checking) feature. diff -urpN crash-3.10-11.orig/check.c crash-3.10-11.new/check.c --- crash-3.10-11.orig/check.c 1970-01-01 03:00:00.000000000 +0300 +++ crash-3.10-11.new/check.c 2010-04-14 10:15:12.000000000 +0400 @@ -0,0 +1,234 @@ +/* check.c - core analysis suite + * + * Copyright (C) 2010 MontaVista Software LLC + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "check_defs.h" + +int check_pages = 0, only_header = 0, endless = 0, + verbose = 0, silent = 0, + print_header = 1, print_asmheader = 0, print_pages = 0; +off_t dump_header_offset = 0; + +void usage(const char *argv0) +{ + printf("\n"); + printf("%s %s - LKCD vmcore files validation feature\n", + basename(argv0), build_version); + printf("Usage: %s [-abhHpPsSv] FILE\n", argv0); + printf("\t-h\tThis help page\n"); + printf("\t-a\tPrint asm header\n"); + printf("\t-b\tThe FILE is device or device raw dump\n"); + printf("\t-H\tDo not check end page, print only dump header\n"); + printf("\t-p\tCheck all pages in the dump\n"); + printf("\t-P\tPrint each page header verbosely\n"); + printf("\t-s\tBe silent, print only result\n"); + printf("\t-S\tDo not print anything (result will be in return code)\n"); + printf("\t-v\tBe verbose, print all information from dump headers\n"); + printf("\tFILE\tVmcore or device file to check\n"); + printf("\n"); +} + +int main(int argc, char **argv) +{ + uint64_t magic; + uint32_t version; + int fd, opt, result; + char *file; + struct stat sb; + + lkcd_helper + lkcd_check_header = 0, + lkcd_check_asmheader = 0, + lkcd_check_pages = 0, + lkcd_check_end = 0; + /* + * Get and verify command line options. + */ + opterr = 0; + optind = 0; + while((opt = getopt(argc, argv, "abhHpPsSv")) != -1) { + switch (opt) { + case 'a': + print_asmheader = 1; + break; + case 'b': + dump_header_offset = LKCD_DUMP_HEADER_OFFSET; + endless = 1; + break; + case 'h': + usage(argv[0]); + return E_BADARGS; + case 'H': + only_header = 1; + break; + case 'p': + check_pages = 1; + break; + case 'P': + check_pages = 1; + print_pages = 1; + break; + case 's': + silent = 1; + verbose = 0; + break; + case 'S': + silent = 2; + verbose = 0; + break; + case 'v': + silent = 0; + verbose = 1; + break; + default: + usage(argv[0]); + return E_BADARGS; + } + } + + if (optind + 1 != argc) { + usage(argv[0]); + return E_BADARGS; + } + file = argv[optind]; + + if (stat(file, &sb)) { + perror(file); + return E_NOFILE; + } + switch (sb.st_mode & S_IFMT) { + case S_IFBLK: + case S_IFCHR: + dump_header_offset = LKCD_DUMP_HEADER_OFFSET; + endless = 1; + break; + case S_IFREG: + break; + case S_IFLNK: + case S_IFIFO: + case S_IFSOCK: + case S_IFDIR: + default: + usage(argv[0]); + return E_BADARGS; + } + + fd = open(file, O_RDONLY); + if (fd < 0) { + perror(file); + return E_NOFILE; + } + if (silent < 2) { + field("File name"); + printf("%s\n", file); + } + + if (lseek(fd, dump_header_offset, SEEK_SET) == ((off_t)-1)) { + incomplete("Could not jump to the dump header at " PRI2offs, + dump_header_offset, dump_header_offset); + goto bad; + } + if (read(fd, &magic, sizeof(uint64_t)) != sizeof(uint64_t)) { + incomplete("Can not read dump magic number"); + goto bad; + } + + if ((magic == LKCD_DUMP_MAGIC_NUMBER) || + (magic == LKCD_DUMP_MAGIC_LIVE)) + init_target_endianess(0); + else { + uint64_t magic2 = bswap_u64(magic); + if ((magic2 == LKCD_DUMP_MAGIC_NUMBER) || + (magic2 == LKCD_DUMP_MAGIC_LIVE)) + init_target_endianess(1); + else { + corrupted("Invalid magic number %" PRIu64 , magic); + goto bad; + } + } + magic = from_target_u64(magic); + + if (read(fd, &version, sizeof(uint32_t)) != sizeof(uint32_t)) { + incomplete("Can not find dump header"); + goto bad; + } + version = from_target_u32(version); + switch (version & ~(LKCD_DUMP_MCLX_V0|LKCD_DUMP_MCLX_V1)) { + case LKCD_DUMP_V1: + lkcd_check_header = lkcd_dump_check_header_v1; + lkcd_check_asmheader = lkcd_dump_check_asmheader_v1; + lkcd_check_pages = lkcd_dump_check_pages_v1; + lkcd_check_end = lkcd_dump_check_end_page_v1; + break; + + case LKCD_DUMP_V2: + case LKCD_DUMP_V3: + lkcd_check_header = lkcd_dump_check_header_v3; + lkcd_check_asmheader = lkcd_dump_check_asmheader_v3; + lkcd_check_pages = lkcd_dump_check_pages_v3; + lkcd_check_end = lkcd_dump_check_end_page_v3; + break; + + case LKCD_DUMP_V5: + case LKCD_DUMP_V6: + case LKCD_DUMP_V7: + lkcd_check_header = lkcd_dump_check_header_v5; + lkcd_check_asmheader = lkcd_dump_check_asmheader_v5; + lkcd_check_pages = lkcd_dump_check_pages_v5; + lkcd_check_end = lkcd_dump_check_end_page_v5; + break; + + case LKCD_DUMP_V8: + lkcd_check_header = lkcd_dump_check_header_v8; + lkcd_check_asmheader = lkcd_dump_check_asmheader_v8; + lkcd_check_pages = lkcd_dump_check_pages_v8; + lkcd_check_end = lkcd_dump_check_end_page_v8; + break; + + default: + corrupted("Unsupported LKCD dump version: %" PRIu32 " (%#" PRIx32 ")", + version & ~(LKCD_DUMP_MCLX_V0|LKCD_DUMP_MCLX_V1), version); + goto bad; + } + + result = lkcd_check_header(fd); + if(!result) + goto broken; + if(only_header) + goto done; + + result = lkcd_check_asmheader(fd); + if(!result) + goto broken; + + if (check_pages || endless) + result = lkcd_check_pages(fd); + else + result = lkcd_check_end(fd); + if (!result) + goto broken; + + complete(); +done: + close(fd); + return E_SUCCESS; +broken: + close(fd); + return E_BROKEN; +bad: + close(fd); + return E_BADFORMAT; +} + diff -urpN crash-3.10-11.orig/check_defs.h crash-3.10-11.new/check_defs.h --- crash-3.10-11.orig/check_defs.h 1970-01-01 03:00:00.000000000 +0300 +++ crash-3.10-11.new/check_defs.h 2010-04-14 10:15:12.000000000 +0400 @@ -0,0 +1,172 @@ +/* check_defs.h - core check suite + * + * Copyright (C) 2010 MontaVista Software LLC + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <stdio.h> +#include <unistd.h> +#include <fcntl.h> +#include <time.h> +#include <inttypes.h> +#include <stdint.h> +#include <stdlib.h> +#include <stdarg.h> +#include <sys/stat.h> +#include <sys/types.h> +#ifndef __USE_GNU +#define __USE_GNU +#include <string.h> +#undef __USE_GNU +#else +#include <string.h> +#endif + +#include "target_types.h" +#undef from_target_u16 +#undef from_target_u32 +#undef from_target_u64 + +#define E_SUCCESS 0 +#define E_BROKEN 1 +#define E_BADFORMAT 2 +#define E_NOFILE 3 +#define E_BADARGS 4 + +#define LKCD_DUMP_MAGIC_NUMBER (0xa8190173618f23edULL) +#define LKCD_DUMP_MAGIC_LIVE (0xa8190173618f23cdULL) + +#define LKCD_DUMP_V1 (0x1) +#define LKCD_DUMP_V2 (0x2) +#define LKCD_DUMP_V3 (0x3) +#define LKCD_DUMP_V5 (0x5) +#define LKCD_DUMP_V6 (0x6) +#define LKCD_DUMP_V7 (0x7) +#define LKCD_DUMP_V8 (0x8) +#define LKCD_DUMP_VERSION_NUMBER_MASK (0xf) + +#define LKCD_DUMP_MCLX_V0 (0x80000000) /* MCLX mod of LKCD */ +#define LKCD_DUMP_MCLX_V1 (0x40000000) /* Extra page header data */ +#define LKCD_OFFSET_TO_FIRST_PAGE (64 * 1024) +#define LKCD_OFFSET_TO_FIRST_BIG_PAGE (256 * 1024) +#define LKCD_DUMP_HEADER_OFFSET (1 << 16) + +#if (defined(__USE_FILE_OFFSET64) || _FILE_OFFSET_BITS == 64 || __WORDSIZE == 64) +#define PRI_off_t(c) __PRI64_PREFIX c +#else +#define PRI_off_t(c) c +#endif +#define PRIuoff_t PRI_off_t("u") +#define PRIxoff_t PRI_off_t("x") +#define PRI2offs "%" PRIuoff_t " (%#" PRIxoff_t ")" +#define PRI2offsNL PRI2offs "\n" + +#undef TRUE +#undef FALSE + +#define TRUE (1) +#define FALSE (0) + +#ifdef CRASH_X86 +#define NR_CPUS (32) +#endif +#ifdef CRASH_X86_64 +#define NR_CPUS (32) +#endif +#ifdef CRASH_ALPHA +#define NR_CPUS (64) +#endif +#ifdef CRASH_PPC +#define NR_CPUS (32) +#endif +#ifdef CRASH_IA64 +#define NR_CPUS (512) +#endif +#ifdef CRASH_PPC64 +#define NR_CPUS (128) +#endif +#ifdef CRASH_S390 +#define NR_CPUS (64) +#endif +#ifdef CRASH_S390X +#define NR_CPUS (64) +#endif +#ifdef CRASH_ARM +#define NR_CPUS (32) +#endif + +struct new_utsname { + char sysname[65]; + char nodename[65]; + char release[65]; + char version[65]; + char machine[65]; + char domainname[65]; +}; + +typedef int (*lkcd_helper)(int fd); + +extern int silent; +extern int verbose; +extern int print_header; +extern int print_asmheader; +extern int print_pages; +extern int check_pages; +extern int only_header; +extern int endless; +extern off_t dump_header_offset; +extern char *build_version; + +uint16_t bswap_u16(uint16_t v); +uint32_t bswap_u32(uint32_t v); +uint64_t bswap_u64(uint64_t v); +uint16_t dummy_u16(uint16_t v); +uint32_t dummy_u32(uint32_t v); +uint64_t dummy_u64(uint64_t v); + +typedef uint16_t (*target_conv_u16)(uint16_t v); +typedef uint32_t (*target_conv_u32)(uint32_t v); +typedef uint64_t (*target_conv_u64)(uint64_t v); +extern target_conv_u16 from_target_u16; +extern target_conv_u32 from_target_u32; +extern target_conv_u64 from_target_u64; + +void init_target_endianess(int swap); + +int field(const char *str); +int corrupted(const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); +int incomplete(const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); +int complete(); + +void arch_print_pt_regs(struct target_pt_regs *regs); + +int lkcd_dump_check_header_v1(int fd); +int lkcd_dump_check_asmheader_v1(int fd); +int lkcd_dump_check_pages_v1(int fd); +int lkcd_dump_check_end_page_v1(int fd); + +int lkcd_dump_check_header_v3(int fd); +int lkcd_dump_check_asmheader_v3(int fd); +int lkcd_dump_check_pages_v3(int fd); +int lkcd_dump_check_end_page_v3(int fd); + +int lkcd_dump_check_header_v5(int fd); +int lkcd_dump_check_asmheader_v5(int fd); +int lkcd_dump_check_pages_v5(int fd); +int lkcd_dump_check_end_page_v5(int fd); + +int lkcd_dump_check_header_v8(int fd); +int lkcd_dump_check_asmheader_v8(int fd); +int lkcd_dump_check_pages_v8(int fd); +int lkcd_dump_check_end_page_v8(int fd); + diff -urpN crash-3.10-11.orig/check_tools.c crash-3.10-11.new/check_tools.c --- crash-3.10-11.orig/check_tools.c 1970-01-01 03:00:00.000000000 +0300 +++ crash-3.10-11.new/check_tools.c 2010-04-14 10:15:12.000000000 +0400 @@ -0,0 +1,125 @@ +/* check_tools.c - core analysis suite + * + * Copyright (C) 2010 MontaVista Software LLC + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "check_defs.h" + +target_conv_u16 from_target_u16 = NULL; +target_conv_u32 from_target_u32 = NULL; +target_conv_u64 from_target_u64 = NULL; + +uint16_t bswap_u16(uint16_t v) +{ + return swap_target_u16(v); +} + +uint16_t dummy_u16(uint16_t v) +{ + return v; +} + +uint32_t bswap_u32(uint32_t v) +{ + return swap_target_u32(v); +} + +uint32_t dummy_u32(uint32_t v) +{ + return v; +} + +uint64_t bswap_u64(uint64_t v) +{ + return swap_target_u64(v); +} + +uint64_t dummy_u64(uint64_t v) +{ + return v; +} + +void init_target_endianess(int swap) +{ + if (swap) { + from_target_u16 = bswap_u16; + from_target_u32 = bswap_u32; + from_target_u64 = bswap_u64; + } else { + from_target_u16 = dummy_u16; + from_target_u32 = dummy_u32; + from_target_u64 = dummy_u64; + } +} + +int field(const char *str) +{ + int r; + + r = printf("%20s: ", str); + + return r; +} + +int corrupted(const char *fmt, ...) +{ + va_list args; + int r; + + if (silent > 1) + return 0; + + field("Result"); + printf("Vmcore file is corrupted\n"); + field("Details"); + va_start(args, fmt); + r = vprintf(fmt, args); + va_end(args); + printf("\n\n"); + + return r; +} + +int incomplete(const char *fmt, ...) +{ + va_list args; + int r; + + if (silent > 1) + return 0; + + field("Result"); + printf("Vmcore file is incomplete\n"); + field("Details"); + va_start(args, fmt); + r = vprintf(fmt, args); + va_end(args); + printf("\n\n"); + + return r; +} + +int complete() +{ + int r; + + if (silent > 1) + return 0; + + field("Result"); + r = printf("Vmcore file is complete\n\n"); + + return r; +} + diff -urpN crash-3.10-11.orig/lkcd_dump_v5.h crash-3.10-11.new/lkcd_dump_v5.h --- crash-3.10-11.orig/lkcd_dump_v5.h 2010-02-12 20:12:36.000000000 +0300 +++ crash-3.10-11.new/lkcd_dump_v5.h 2010-03-03 22:07:19.000000000 +0300 @@ -241,7 +241,7 @@ typedef struct __dump_header_asm { uint32_t dha_smp_current_task[DUMP_MAX_NUM_CPUS]; uint32_t dha_stack[DUMP_MAX_NUM_CPUS]; uint32_t dha_stack_ptr[DUMP_MAX_NUM_CPUS]; -} dump_header_asm_t __attribute__((packed)); +} __attribute__((packed)) dump_header_asm_t; /* Take care of target/host endians */ static void inline swap_asm_header(dump_header_asm_t *dh_asm) { diff -urpN crash-3.10-11.orig/lkcd_dump_v8.h crash-3.10-11.new/lkcd_dump_v8.h --- crash-3.10-11.orig/lkcd_dump_v8.h 2010-02-12 20:12:36.000000000 +0300 +++ crash-3.10-11.new/lkcd_dump_v8.h 2010-03-10 20:45:19.000000000 +0300 @@ -323,7 +323,7 @@ typedef struct __dump_header_asm { uint32_t dha_smp_current_task[DUMP_MAX_NUM_CPUS]; uint32_t dha_stack[DUMP_MAX_NUM_CPUS]; uint32_t dha_stack_ptr[DUMP_MAX_NUM_CPUS]; -} dump_header_asm_t __attribute__((packed)); +} __attribute__((packed)) dump_header_asm_t; /* Take care of target/host endians */ static void inline swap_asm_header(dump_header_asm_t *dh_asm) { @@ -345,12 +345,15 @@ static void inline swap_asm_header(dump_ reg = (uint32_t *)dh_asm->dha_smp_regs[cpu].dha_ARM_regs.uregs; for(i=0; i<len; i++) reg[i]=from_target_u32(reg[i]); + dh_asm->dha_smp_regs[cpu].dha_ARM_spsr = from_target_u32( + dh_asm->dha_smp_regs[cpu].dha_ARM_spsr); } } /*end of CRASH_ARM*/ #elif defined (CRASH_PPC) -#define DUMP_MAX_NUM_CPUS 1 +#define DUMP_ASM_MAGIC_NUMBER 0xdeaddeadULL /* magic number */ +#define DUMP_MAX_NUM_CPUS NR_CPUS typedef struct __dump_header_asm { @@ -379,7 +382,7 @@ typedef struct __dump_header_asm { uint32_t dha_smp_current_task[DUMP_MAX_NUM_CPUS]; uint32_t dha_stack[DUMP_MAX_NUM_CPUS]; uint32_t dha_stack_ptr[DUMP_MAX_NUM_CPUS]; -} dump_header_asm_t __attribute__((packed)); +} __attribute__((packed)) dump_header_asm_t; /* Take care of target/host endians */ static void inline swap_asm_header(dump_header_asm_t *dh_asm) { @@ -407,7 +410,8 @@ static void inline swap_asm_header(dump_ #elif defined (CRASH_X86) -#define DUMP_MAX_NUM_CPUS 32 +#define DUMP_ASM_MAGIC_NUMBER 0xdeaddeadULL /* magic number */ +#define DUMP_MAX_NUM_CPUS NR_CPUS typedef struct __dump_header_asm { /* the dump magic number -- unique to verify dump is valid */ @@ -435,7 +439,7 @@ typedef struct __dump_header_asm { uint32_t dha_smp_current_task[DUMP_MAX_NUM_CPUS]; uint32_t dha_stack[DUMP_MAX_NUM_CPUS]; uint32_t dha_stack_ptr[DUMP_MAX_NUM_CPUS]; -} dump_header_asm_t __attribute__((packed)); +} __attribute__((packed)) dump_header_asm_t; /* Take care of target/host endians */ static void inline swap_asm_header(dump_header_asm_t *dh_asm) { @@ -464,7 +468,8 @@ static void inline swap_asm_header(dump_ #elif defined(CRASH_PPC64) -#define DUMP_MAX_NUM_CPUS 2 +#define DUMP_ASM_MAGIC_NUMBER 0xdeaddeadULL /* magic number */ +#define DUMP_MAX_NUM_CPUS NR_CPUS typedef struct __dump_header_asm { @@ -487,7 +492,7 @@ typedef struct __dump_header_asm { uint64_t dha_smp_current_task[DUMP_MAX_NUM_CPUS]; uint64_t dha_stack[DUMP_MAX_NUM_CPUS]; uint64_t dha_stack_ptr[DUMP_MAX_NUM_CPUS]; -} dump_header_asm_t __attribute__((packed)); +} __attribute__((packed)) dump_header_asm_t; static inline void swap_asm_header(dump_header_asm_t *dh_asm) { int i, cpu, len; @@ -507,6 +512,123 @@ static inline void swap_asm_header(dump_ reg[i] = from_target_u64(reg[i]); } +#elif defined (CRASH_X86_64) + +#define DUMP_ASM_MAGIC_NUMBER 0xdeaddeadULL /* magic number */ +#define DUMP_MAX_NUM_CPUS NR_CPUS + +typedef struct __dump_header_asm { + + /* the dump magic number -- unique to verify dump is valid */ + uint64_t dha_magic_number; + + /* the version number of this dump */ + uint32_t dha_version; + + /* the size of this header (in case we can't read it) */ + uint32_t dha_header_size; + + /* the dump registers */ + struct target_pt_regs dha_regs; + + /* smp specific */ + uint32_t dha_smp_num_cpus; + int dha_dumping_cpu; + struct target_pt_regs dha_smp_regs[DUMP_MAX_NUM_CPUS]; + uint64_t dha_smp_current_task[DUMP_MAX_NUM_CPUS]; + uint64_t dha_stack[DUMP_MAX_NUM_CPUS]; + uint64_t dha_stack_ptr[DUMP_MAX_NUM_CPUS]; +} __attribute__((packed)) dump_header_asm_t; + +/* Take care of target/host endians */ +static void inline swap_asm_header(dump_header_asm_t *dh_asm) { + int i, cpu, len; + uint64_t *reg; + + /* Convert only fileds we're carry about */ + dh_asm->dha_magic_number = from_target_u64(dh_asm->dha_magic_number); + dh_asm->dha_version = from_target_u32(dh_asm->dha_version); + dh_asm->dha_header_size = from_target_u32(dh_asm->dha_header_size); + + dh_asm->dha_smp_num_cpus = from_target_u32(dh_asm->dha_smp_num_cpus); + if (dh_asm->dha_smp_num_cpus > DUMP_MAX_NUM_CPUS) + dh_asm->dha_smp_num_cpus = DUMP_MAX_NUM_CPUS; + dh_asm->dha_dumping_cpu = from_target_u32(dh_asm->dha_dumping_cpu); + len = sizeof(struct target_pt_regs) / sizeof(target_ulong); + for (cpu=0; cpu<dh_asm->dha_smp_num_cpus; cpu++) { + reg = (uint64_t *) (&dh_asm->dha_smp_regs[cpu]); + for(i=0; i<len; i++) + reg[i]=from_target_u64(reg[i]); + } +} + +#elif defined (CRASH_IA64) + +#define DUMP_ASM_MAGIC_NUMBER 0xdeaddeadULL /* magic number */ +#define DUMP_MAX_NUM_CPUS NR_CPUS + +typedef struct __dump_header_asm { + + /* the dump magic number -- unique to verify dump is valid */ + uint64_t dha_magic_number; + + /* the version number of this dump */ + uint32_t dha_version; + + /* the size of this header (in case we can't read it) */ + uint32_t dha_header_size; + + /* pointer to pt_regs, (OLD: (struct pt_regs *, NEW: (uint64_t)) */ + uint64_t dha_pt_regs; + + /* the dump registers */ + struct target_pt_regs dha_regs; + + /* the rnat register saved after flushrs */ + uint64_t dha_rnat; + + /* the pfs register saved after flushrs */ + uint64_t dha_pfs; + + /* the bspstore register saved after flushrs */ + uint64_t dha_bspstore; + + /* smp specific */ + uint32_t dha_smp_num_cpus; + uint32_t dha_dumping_cpu; + struct target_pt_regs dha_smp_regs[DUMP_MAX_NUM_CPUS]; + uint64_t dha_smp_current_task[DUMP_MAX_NUM_CPUS]; + uint64_t dha_stack[DUMP_MAX_NUM_CPUS]; + uint64_t dha_stack_ptr[DUMP_MAX_NUM_CPUS]; + +} __attribute__((packed)) dump_header_asm_t; + +/* Take care of target/host endians */ +static void inline swap_asm_header(dump_header_asm_t *dh_asm) { + int i, cpu, len; + uint64_t *reg; + + /* Convert only fileds we're carry about */ + dh_asm->dha_magic_number = from_target_u64(dh_asm->dha_magic_number); + dh_asm->dha_version = from_target_u32(dh_asm->dha_version); + dh_asm->dha_header_size = from_target_u32(dh_asm->dha_header_size); + dh_asm->dha_pt_regs = from_target_u64(dh_asm->dha_pt_regs); + dh_asm->dha_rnat = from_target_u64(dh_asm->dha_rnat); + dh_asm->dha_pfs = from_target_u64(dh_asm->dha_pfs); + dh_asm->dha_bspstore = from_target_u64(dh_asm->dha_bspstore); + + dh_asm->dha_smp_num_cpus = from_target_u32(dh_asm->dha_smp_num_cpus); + if (dh_asm->dha_smp_num_cpus > DUMP_MAX_NUM_CPUS) + dh_asm->dha_smp_num_cpus = DUMP_MAX_NUM_CPUS; + dh_asm->dha_dumping_cpu = from_target_u32(dh_asm->dha_dumping_cpu); + len = sizeof(struct target_pt_regs) / sizeof(target_ulong); + for (cpu=0; cpu<dh_asm->dha_smp_num_cpus; cpu++) { + reg = (uint64_t *) (&dh_asm->dha_smp_regs[cpu]); + for(i=0; i<len; i++) + reg[i]=from_target_u64(reg[i]); + } +} + #else /* @@ -517,7 +639,7 @@ typedef struct __dump_header_asm { uint64_t dha_magic_number; uint32_t dha_dumping_cpu; uint32_t dha_smp_regs[1]; -} dump_header_asm_t __attribute__((packed)); +} __attribute__((packed)) dump_header_asm_t; #define swap_asm_header(x) diff -urpN crash-3.10-11.orig/lkcd_v1_check.c crash-3.10-11.new/lkcd_v1_check.c --- crash-3.10-11.orig/lkcd_v1_check.c 1970-01-01 03:00:00.000000000 +0300 +++ crash-3.10-11.new/lkcd_v1_check.c 2010-04-14 10:15:12.000000000 +0400 @@ -0,0 +1,404 @@ +/* lkcd_v1_check.c - core analysis suite + * + * Copyright (C) 2010 MontaVista Software LLC + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "check_defs.h" +#define CONFIG_VMDUMP +#include "lkcd_vmdump_v1.h" + +static dump_header_t dump_header_v1 = { 0 }; +static dump_page_t dump_page = { 0 }; +static int arch_print_asmheader_v1(dump_header_t *dh); + +int lkcd_dump_check_header_v1(int fd) +{ + int others; + time_t sec; + uint16_t host, target; + char buf[64]; + dump_header_t *dh; + dh = &dump_header_v1; + + if (lseek(fd, dump_header_offset, SEEK_SET) == ((off_t)-1)) { + incomplete("Could not jump to the dump header at " PRI2offs, + dump_header_offset, dump_header_offset); + return FALSE; + } + + if (read(fd, dh, sizeof(dump_header_t)) != sizeof(dump_header_t)) { + incomplete("Could not read dump header"); + return FALSE; + } + + /* Swap everything from the target endian to mine.*/ + dh->dh_magic_number = from_target_u64(dh->dh_magic_number); + dh->dh_version = from_target_u32(dh->dh_version); + dh->dh_header_size = from_target_u32(dh->dh_header_size); + dh->dh_dump_level = from_target_u32(dh->dh_dump_level); + dh->dh_page_size = from_target_u32(dh->dh_page_size); + dh->dh_memory_size = from_target_u64(dh->dh_memory_size); + dh->dh_memory_start = from_target_u64(dh->dh_memory_start); + dh->dh_memory_end = from_target_u64(dh->dh_memory_end); + dh->dh_num_pages = from_target_u32(dh->dh_num_pages); + dh->dh_time.tv_sec = from_target_u64(dh->dh_time.tv_sec); + dh->dh_time.tv_usec = from_target_u64(dh->dh_time.tv_usec); + *(uint32_t *)(&dh->dh_current_task) = + from_target_u32(*(uint32_t *)(&dh->dh_current_task)); + + if (dh->dh_header_size != sizeof(dump_header_t)) { + corrupted("Header size paradox: dh_header_size = %" PRIu32 + ", sizeof(dump_header_t) = %zu", + dh->dh_header_size, sizeof(dump_header_t)); + return FALSE; + } + + if (silent || !print_header) + return TRUE; + + if (dump_header_offset != 0 || verbose) { + field("Dump header offset"); + printf(PRI2offsNL, dump_header_offset, dump_header_offset); + } + if (verbose) { + field("Magic number"); + printf("%#" PRIx64 " ", dh->dh_magic_number); + if (dh->dh_magic_number == DUMP_MAGIC_NUMBER) + printf("(DUMP_MAGIC_NUMBER)\n"); + else + printf("(?)\n"); + + field("Version"); + printf("%#" PRIx32 " (", dh->dh_version); + others = 0; + switch (dh->dh_version & LKCD_DUMP_VERSION_NUMBER_MASK) { + case LKCD_DUMP_V1: + printf("%sLKCD_DUMP_V1", others++ ? "|" : ""); + break; + case LKCD_DUMP_V2: + printf("%sLKCD_DUMP_V2", others++ ? "|" : ""); + break; + case LKCD_DUMP_V3: + printf("%sLKCD_DUMP_V3", others++ ? "|" : ""); + break; + } + if (dh->dh_version & LKCD_DUMP_MCLX_V0) + printf("%sLKCD_DUMP_MCLX_V0", others++ ? "|" : ""); + if (dh->dh_version & LKCD_DUMP_MCLX_V1) + printf("%sLKCD_DUMP_MCLX_V1", others++ ? "|" : ""); + printf(")\n"); + + field("Header size"); + printf("%" PRIu32 "\n", dh->dh_header_size); + } + + field("Dump level"); + printf("%#" PRIx32 " (", dh->dh_dump_level); + others = 0; + if (dh->dh_dump_level & DUMP_HEADER) + printf("%sDUMP_HEADER", others++ ? "|" : ""); + if (dh->dh_dump_level & DUMP_KERN) + printf("%sDUMP_KERN", others++ ? "|" : ""); + if (dh->dh_dump_level & DUMP_USED) + printf("%sDUMP_USED", others++ ? "|" : ""); + if (dh->dh_dump_level & DUMP_ALL) + printf("%sDUMP_ALL", others++ ? "|" : ""); + printf(")\n"); + + field("Dump compression"); + printf("DUMP_COMPRESS_RLE\n"); + + if (verbose) { + field("Page size"); + printf("%" PRIu32 "\n", dh->dh_page_size); + + field("Memory size"); + printf("%#" PRIx64 "\n", dh->dh_memory_size); + + field("Memory start"); + printf("%#" PRIx64 "\n", dh->dh_memory_start); + + field("Memory end"); + printf("%#" PRIx64 "\n", dh->dh_memory_end); + + field("Num pages"); + printf("%" PRIu32 "\n", dh->dh_num_pages); + + field("Current task"); + printf("%#llx\n", (unsigned long long) dh->dh_current_task); + } + + field("Crash time"); + sec = dh->dh_time.tv_sec; + strftime(buf, sizeof(buf), "%a %b %e %H:%M:%S %Z %Y", + localtime(&sec)); + printf("%s\n", buf); + + field("Kernel name"); + printf("%s\n", dh->dh_utsname.sysname); + field("Node name"); + printf("%s\n", dh->dh_utsname.nodename); + field("Domain name"); + printf("%s\n", dh->dh_utsname.domainname); + field("Kernel release"); + printf("%s\n", dh->dh_utsname.release); + field("Kernel version"); + printf("%s\n", dh->dh_utsname.version); + field("Machine name"); + printf("%s\n", dh->dh_utsname.machine); + + field("Machine type"); + host = 1; + target = from_target_u16(host); + if ((*(char *) &host) && host == target) + printf("little endian\n"); + else + printf("big endian\n"); + + field("Panic message"); + printf("%s\n", dh->dh_panic_string); + + return TRUE; +} + +static void inline swap_asm_header(dump_header_t *dh) { + int i, len; + target_ulong *reg; + + /* Convert only fileds we're carry about */ + dh->dh_esp = from_target_u32(dh->dh_esp); + dh->dh_eip = from_target_u32(dh->dh_eip); + + len = sizeof(struct target_pt_regs) / sizeof(target_ulong); + reg = (target_ulong *) (&dh->dh_regs); + if (sizeof(target_ulong) == 64) + for(i=0; i<len; i++) + reg[i]=from_target_u64(reg[i]); + else + for(i=0; i<len; i++) + reg[i]=from_target_u32(reg[i]); +} + +int lkcd_dump_check_asmheader_v1(int fd) +{ + dump_header_t *dh; + dh = &dump_header_v1; + + swap_asm_header(dh); + + if (silent || !print_asmheader) + return TRUE; + + return arch_print_asmheader_v1(dh); +} + +int lkcd_dump_check_pages_v1(int fd) +{ + int others; + unsigned long pgcnt = 0, cpgs = 0; + ssize_t i, rd; + off_t offs; + char buf[1024]; + dump_page_t *dp; + dump_header_t *dh; + dh = &dump_header_v1; + dp = &dump_page; + + offs = dump_header_offset; + if (dh->dh_page_size < LKCD_OFFSET_TO_FIRST_PAGE) + offs += LKCD_OFFSET_TO_FIRST_PAGE; + else + offs += LKCD_OFFSET_TO_FIRST_BIG_PAGE; + if (lseek(fd, offs, SEEK_SET) == ((off_t)-1)) { + incomplete("Could not jump to the page No %lu (%#lx) at " + "%#" PRIxoff_t, pgcnt, pgcnt, offs); + return FALSE; + } + + if (!silent) + printf("\n"); + do { + if (read(fd, dp, sizeof(dump_page_t)) != sizeof(dump_page_t)) { + incomplete("Could not read page header for page No " + "%lu (%#lx)", pgcnt, pgcnt); + return FALSE; + } + + dp->dp_address = from_target_u64(dp->dp_address); + dp->dp_size = from_target_u32(dp->dp_size); + dp->dp_flags = from_target_u32(dp->dp_flags); + + if (dp->dp_flags & ~(DUMP_COMPRESSED|DUMP_RAW| + DUMP_END|LKCD_DUMP_MCLX_V0)) { + corrupted("Unknown page flag in the dump: %#" PRIx32 + ", page No %lu (%#lx)", + dp->dp_flags, pgcnt, pgcnt); + return FALSE; + } + + if (dp->dp_size > dh->dh_page_size) { + corrupted("Page size paradox: dp_size = %#" PRIx32 + ", dh_page_size = %#" PRIx32 + ", page No %lu (%#lx)", dp->dp_flags, + dh->dh_page_size, pgcnt, pgcnt); + return FALSE; + } + + if ((print_pages || (verbose && !pgcnt)) && !silent) { + field("Page No"); + printf("%lu (%#lx)\n", pgcnt, pgcnt); + + field("Page offset"); + printf(PRI2offsNL, offs, offs); + + field("Page address"); + printf("%#" PRIx64 "\n", dp->dp_address); + + field("Page size"); + printf("%" PRIu32 "\n", dp->dp_size); + + field("Page flags"); + printf("%#" PRIx32 " (", dp->dp_flags); + others = 0; + if (dp->dp_flags & DUMP_COMPRESSED) { + printf("%sDUMP_COMPRESSED", others++ ? "|" : ""); + cpgs++; + } + if (dp->dp_flags & DUMP_RAW) + printf("%sDUMP_RAW", others++ ? "|" : ""); + if (dp->dp_flags & DUMP_END) + printf("%sDUMP_END", others++ ? "|" : ""); + if (dp->dp_flags & LKCD_DUMP_MCLX_V0) + printf("%sLKCD_DUMP_MCLX_V0", others++ ? "|" : ""); + printf(")\n"); + } + + if (dp->dp_flags & DUMP_END) + break; + + pgcnt++; + if (lseek(fd, dp->dp_size, SEEK_CUR) == ((off_t)-1)) { + incomplete("Could not jump to the page No %lu (%#lx)", + pgcnt, pgcnt); + return FALSE; + } + offs += dp->dp_size + sizeof(dump_page_t); + } while (1); + + if (pgcnt > dh->dh_num_pages) { + corrupted("Page count paradox: pgcnt = %lu, dh_num_pages = " + "%" PRIu32, pgcnt, dh->dh_num_pages); + return FALSE; + } + + if (pgcnt < dh->dh_num_pages) { + incomplete("%lu pages lost", + (unsigned long) dh->dh_num_pages - pgcnt); + return FALSE; + } + + if (!silent) { + field("Total pages found"); + printf("%lu (%#lx)\n", pgcnt, pgcnt); + field("Compressed pages"); + printf("%lu\n", cpgs); + field("End-page offset"); + printf(PRI2offsNL, offs, offs); + } + + offs += sizeof(dump_page_t); + do { + rd = read(fd, buf, sizeof(buf)); + + for (i = 0; i < rd; i++) + if (buf[i] != 'm') { + offs += i; + if (endless && !silent) { + field("Dump end"); + printf(PRI2offsNL, offs, offs); + + return TRUE; + } + corrupted("Found wrong symbol inside end page " + "at %#" PRIxoff_t, offs); + return FALSE; + } + + offs += rd; + } while (rd > 0); + + return TRUE; +} + +int lkcd_dump_check_end_page_v1(int fd) +{ + dump_page_t *dp; + char buf[1024]; + ssize_t i, len = 0; + off_t offs; + + offs = lseek(fd, 0, SEEK_END); + while (offs > 0) { + offs -= sizeof(buf); + if (lseek(fd, offs, SEEK_SET) == ((off_t)-1)) { + incomplete("Could not jump to the offset %#" PRIxoff_t, offs); + return FALSE; + } + if (read(fd, buf, sizeof(buf)) != sizeof(buf)) { + incomplete("Could not read last page at %#" PRIxoff_t, offs); + return FALSE; + } + for (i = sizeof(buf); i--; ) + if (buf[i] != 'm') { + i++; + if (i < sizeof(dump_page_t)) { + offs += sizeof(buf) / 2; + len -= sizeof(buf) / 2; + break; + } + i -= sizeof(dump_page_t); + goto found; + } + len += sizeof(buf); + } +found: + dp = (dump_page_t *)(buf + i); + offs += i; + if (from_target_u32(dp->dp_flags) == DUMP_END) + if(len) { + if (!silent) { + printf("\n"); + field("End-page offset"); + printf(PRI2offsNL, offs, offs); + } + + return TRUE; + } + + if(!len) + incomplete("Could not find final marker and page header for it."); + else + corrupted("Invalid page header before final marker."); + return FALSE; +} + +static int arch_print_asmheader_v1(dump_header_t *dh) +{ + if (verbose) { + printf("\n"); + arch_print_pt_regs(&dh->dh_regs); + } + return TRUE; +} + diff -urpN crash-3.10-11.orig/lkcd_v3_check.c crash-3.10-11.new/lkcd_v3_check.c --- crash-3.10-11.orig/lkcd_v3_check.c 1970-01-01 03:00:00.000000000 +0300 +++ crash-3.10-11.new/lkcd_v3_check.c 2010-04-14 10:15:12.000000000 +0400 @@ -0,0 +1,435 @@ +/* lkcd_v3_check.c - core analysis suite + * + * Copyright (C) 2010 MontaVista Software LLC + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "check_defs.h" +#define CONFIG_VMDUMP +#include "lkcd_vmdump_v2_v3.h" + +static dump_header_t dump_header_v3 = { 0 }; +static dump_header_asm_t dump_header_asm_v3 = { 0 }; +static dump_page_t dump_page = { 0 }; +static int arch_print_asmheader_v3(dump_header_asm_t *dha); + +int lkcd_dump_check_header_v3(int fd) +{ + int others; + time_t sec; + uint16_t host, target; + char buf[64]; + dump_header_t *dh; + dh = &dump_header_v3; + + if (lseek(fd, dump_header_offset, SEEK_SET) == ((off_t)-1)) { + incomplete("Could not jump to the dump header at " PRI2offs, + dump_header_offset, dump_header_offset); + return FALSE; + } + + if (read(fd, dh, sizeof(dump_header_t)) != sizeof(dump_header_t)) { + incomplete("Could not read dump header"); + return FALSE; + } + + /* Swap everything from the target endian to mine.*/ + dh->dh_magic_number = from_target_u64(dh->dh_magic_number); + dh->dh_version = from_target_u32(dh->dh_version); + dh->dh_header_size = from_target_u32(dh->dh_header_size); + dh->dh_dump_level = from_target_u32(dh->dh_dump_level); + dh->dh_page_size = from_target_u32(dh->dh_page_size); + dh->dh_memory_size = from_target_u64(dh->dh_memory_size); + dh->dh_memory_start = from_target_u64(dh->dh_memory_start); + dh->dh_memory_end = from_target_u64(dh->dh_memory_end); + dh->dh_num_pages = from_target_u32(dh->dh_num_pages); + dh->dh_time.tv_sec = from_target_u64(dh->dh_time.tv_sec); + dh->dh_time.tv_usec = from_target_u64(dh->dh_time.tv_usec); + *(uint32_t *)(&dh->dh_current_task) = + from_target_u32(*(uint32_t *)(&dh->dh_current_task)); + + if (dh->dh_header_size != sizeof(dump_header_t)) { + corrupted("Header size paradox: dh_header_size = %" PRIu32 + ", sizeof(dump_header_t) = %zu", + dh->dh_header_size, sizeof(dump_header_t)); + return FALSE; + } + + if (silent || !print_header) + return TRUE; + + if (dump_header_offset != 0 || verbose) { + field("Dump header offset"); + printf(PRI2offsNL, dump_header_offset, dump_header_offset); + } + if (verbose) { + field("Magic number"); + printf("%#" PRIx64 " ", dh->dh_magic_number); + if (dh->dh_magic_number == DUMP_MAGIC_NUMBER) + printf("(DUMP_MAGIC_NUMBER)\n"); + else + printf("(?)\n"); + + field("Version"); + printf("%#" PRIx32 " (", dh->dh_version); + others = 0; + switch (dh->dh_version & LKCD_DUMP_VERSION_NUMBER_MASK) { + case LKCD_DUMP_V1: + printf("%sLKCD_DUMP_V1", others++ ? "|" : ""); + break; + case LKCD_DUMP_V2: + printf("%sLKCD_DUMP_V2", others++ ? "|" : ""); + break; + case LKCD_DUMP_V3: + printf("%sLKCD_DUMP_V3", others++ ? "|" : ""); + break; + } + if (dh->dh_version & LKCD_DUMP_MCLX_V0) + printf("%sLKCD_DUMP_MCLX_V0", others++ ? "|" : ""); + if (dh->dh_version & LKCD_DUMP_MCLX_V1) + printf("%sLKCD_DUMP_MCLX_V1", others++ ? "|" : ""); + printf(")\n"); + + field("Header size"); + printf("%" PRIu32 "\n", dh->dh_header_size); + } + + field("Dump level"); + printf("%#" PRIx32 " (", dh->dh_dump_level); + others = 0; + if (dh->dh_dump_level & DUMP_HEADER) + printf("%sDUMP_HEADER", others++ ? "|" : ""); + if (dh->dh_dump_level & DUMP_KERN) + printf("%sDUMP_KERN", others++ ? "|" : ""); + if (dh->dh_dump_level & DUMP_USED) + printf("%sDUMP_USED", others++ ? "|" : ""); + if (dh->dh_dump_level & DUMP_ALL) + printf("%sDUMP_ALL", others++ ? "|" : ""); + printf(")\n"); + + field("Dump compression"); + printf("DUMP_COMPRESS_RLE\n"); + + if (verbose) { + field("Page size"); + printf("%" PRIu32 "\n", dh->dh_page_size); + + field("Memory size"); + printf("%#" PRIx64 "\n", dh->dh_memory_size); + + field("Memory start"); + printf("%#" PRIx64 "\n", dh->dh_memory_start); + + field("Memory end"); + printf("%#" PRIx64 "\n", dh->dh_memory_end); + + field("Num pages"); + printf("%" PRIu32 "\n", dh->dh_num_pages); + + field("Current task"); + printf("%#llx\n", (unsigned long long) dh->dh_current_task); + } + + field("Crash time"); + sec = dh->dh_time.tv_sec; + strftime(buf, sizeof(buf), "%a %b %e %H:%M:%S %Z %Y", + localtime(&sec)); + printf("%s\n", buf); + + field("Kernel name"); + printf("%s\n", dh->dh_utsname.sysname); + field("Node name"); + printf("%s\n", dh->dh_utsname.nodename); + field("Domain name"); + printf("%s\n", dh->dh_utsname.domainname); + field("Kernel release"); + printf("%s\n", dh->dh_utsname.release); + field("Kernel version"); + printf("%s\n", dh->dh_utsname.version); + field("Machine name"); + printf("%s\n", dh->dh_utsname.machine); + + field("Machine type"); + host = 1; + target = from_target_u16(host); + if ((*(char *) &host) && host == target) + printf("little endian\n"); + else + printf("big endian\n"); + + field("Panic message"); + printf("%s\n", dh->dh_panic_string); + + return TRUE; +} + +static void inline swap_asm_header(dump_header_asm_t *dh_asm) +{ + int i, len; + target_ulong *reg; + + /* Convert only fileds we're carry about */ + dh_asm->dha_magic_number = from_target_u64(dh_asm->dha_magic_number); + dh_asm->dha_version = from_target_u32(dh_asm->dha_version); + dh_asm->dha_header_size = from_target_u32(dh_asm->dha_header_size); + dh_asm->dha_esp = from_target_u32(dh_asm->dha_esp); + dh_asm->dha_eip = from_target_u32(dh_asm->dha_eip); + + len = sizeof(struct target_pt_regs) / sizeof(target_ulong); + reg = (target_ulong *) (&dh_asm->dha_regs); + if (sizeof(target_ulong) == 64) + for(i=0; i<len; i++) + reg[i]=from_target_u64(reg[i]); + else + for(i=0; i<len; i++) + reg[i]=from_target_u32(reg[i]); +} + +int lkcd_dump_check_asmheader_v3(int fd) +{ + dump_header_asm_t *dh_asm; + dh_asm = &dump_header_asm_v3; + + if (lseek(fd, dump_header_offset + sizeof(dump_header_t), SEEK_SET) + == ((off_t)-1)) { + incomplete("Could not jump to the asm header at %#" PRIxoff_t, + dump_header_offset + sizeof(dump_header_t)); + return FALSE; + } + + if (read(fd, dh_asm, sizeof(dump_header_asm_t)) != + sizeof(dump_header_asm_t)) { + incomplete("Could not read asm header at %#" PRIxoff_t, + dump_header_offset + sizeof(dump_header_t)); + return FALSE; + } + + swap_asm_header(dh_asm); + + if (silent || !print_asmheader) + return TRUE; + + return arch_print_asmheader_v3(dh_asm); +} + +int lkcd_dump_check_pages_v3(int fd) +{ + int others; + unsigned long pgcnt = 0, cpgs = 0; + ssize_t i, rd; + off_t offs; + char buf[1024]; + dump_page_t *dp; + dump_header_t *dh; + dh = &dump_header_v3; + dp = &dump_page; + + offs = dump_header_offset; + if (dh->dh_page_size < LKCD_OFFSET_TO_FIRST_PAGE) + offs += LKCD_OFFSET_TO_FIRST_PAGE; + else + offs += LKCD_OFFSET_TO_FIRST_BIG_PAGE; + if (lseek(fd, offs, SEEK_SET) == ((off_t)-1)) { + incomplete("Could not jump to the page No %lu (%#lx) at " + "%#" PRIxoff_t, pgcnt, pgcnt, offs); + return FALSE; + } + + if (!silent) + printf("\n"); + do { + if (read(fd, dp, sizeof(dump_page_t)) != sizeof(dump_page_t)) { + incomplete("Could not read page header for page No " + "%lu (%#lx)", pgcnt, pgcnt); + return FALSE; + } + + dp->dp_address = from_target_u64(dp->dp_address); + dp->dp_size = from_target_u32(dp->dp_size); + dp->dp_flags = from_target_u32(dp->dp_flags); + + if (dp->dp_flags & ~(DUMP_COMPRESSED|DUMP_RAW| + DUMP_END|LKCD_DUMP_MCLX_V0)) { + corrupted("Unknown page flag in the dump: %#" PRIx32 + ", page No %lu (%#lx)", + dp->dp_flags, pgcnt, pgcnt); + return FALSE; + } + + if (dp->dp_size > dh->dh_page_size) { + corrupted("Page size paradox: dp_size = %#" PRIx32 + ", dh_page_size = %#" PRIx32 + ", page No %lu (%#lx)", dp->dp_flags, + dh->dh_page_size, pgcnt, pgcnt); + return FALSE; + } + + if ((print_pages || (verbose && !pgcnt)) && !silent) { + field("Page No"); + printf("%lu (%#lx)\n", pgcnt, pgcnt); + + field("Page offset"); + printf(PRI2offsNL, offs, offs); + + field("Page address"); + printf("%#" PRIx64 "\n", dp->dp_address); + + field("Page size"); + printf("%" PRIu32 "\n", dp->dp_size); + + field("Page flags"); + printf("%#" PRIx32 " (", dp->dp_flags); + others = 0; + if (dp->dp_flags & DUMP_COMPRESSED) { + printf("%sDUMP_COMPRESSED", others++ ? "|" : ""); + cpgs++; + } + if (dp->dp_flags & DUMP_RAW) + printf("%sDUMP_RAW", others++ ? "|" : ""); + if (dp->dp_flags & DUMP_END) + printf("%sDUMP_END", others++ ? "|" : ""); + if (dp->dp_flags & LKCD_DUMP_MCLX_V0) + printf("%sLKCD_DUMP_MCLX_V0", others++ ? "|" : ""); + printf(")\n"); + } + + if (dp->dp_flags & DUMP_END) + break; + + pgcnt++; + if (lseek(fd, dp->dp_size, SEEK_CUR) == ((off_t)-1)) { + incomplete("Could not jump to the page No %lu (%#lx)", + pgcnt, pgcnt); + return FALSE; + } + offs += dp->dp_size + sizeof(dump_page_t); + } while (1); + + if (pgcnt > dh->dh_num_pages) { + corrupted("Page count paradox: pgcnt = %lu, dh_num_pages = " + "%" PRIu32, pgcnt, dh->dh_num_pages); + return FALSE; + } + + if (pgcnt < dh->dh_num_pages) { + incomplete("%lu pages lost", + (unsigned long) dh->dh_num_pages - pgcnt); + return FALSE; + } + + if (!silent) { + field("Total pages found"); + printf("%lu (%#lx)\n", pgcnt, pgcnt); + field("Compressed pages"); + printf("%lu\n", cpgs); + field("End-page offset"); + printf(PRI2offsNL, offs, offs); + } + + offs += sizeof(dump_page_t); + do { + rd = read(fd, buf, sizeof(buf)); + + for (i = 0; i < rd; i++) + if (buf[i] != 'm') { + offs += i; + if (endless && !silent) { + field("Dump end"); + printf(PRI2offsNL, offs, offs); + + return TRUE; + } + corrupted("Found wrong symbol inside end page " + "at %#" PRIxoff_t, offs); + return FALSE; + } + + offs += rd; + } while (rd > 0); + + return TRUE; +} + +int lkcd_dump_check_end_page_v3(int fd) +{ + dump_page_t *dp; + char buf[1024]; + ssize_t i, len = 0; + off_t offs; + + offs = lseek(fd, 0, SEEK_END); + while (offs > 0) { + offs -= sizeof(buf); + if (lseek(fd, offs, SEEK_SET) == ((off_t)-1)) { + incomplete("Could not jump to the offset %#" PRIxoff_t, offs); + return FALSE; + } + if (read(fd, buf, sizeof(buf)) != sizeof(buf)) { + incomplete("Could not read last page at %#" PRIxoff_t, offs); + return FALSE; + } + for (i = sizeof(buf); i--; ) + if (buf[i] != 'm') { + i++; + if (i < sizeof(dump_page_t)) { + offs += sizeof(buf) / 2; + len -= sizeof(buf) / 2; + break; + } + i -= sizeof(dump_page_t); + goto found; + } + len += sizeof(buf); + } +found: + dp = (dump_page_t *)(buf + i); + offs += i; + if (from_target_u32(dp->dp_flags) == DUMP_END) + if(len) { + if (!silent) { + printf("\n"); + field("End-page offset"); + printf(PRI2offsNL, offs, offs); + } + + return TRUE; + } + + if(!len) + incomplete("Could not find final marker and page header for it."); + else + corrupted("Invalid page header before final marker."); + return FALSE; +} + +static int arch_print_asmheader_v3(dump_header_asm_t *dha) +{ + dump_header_t *dh; + dh = &dump_header_v3; + + printf("\n"); + field("ASM Magic number"); + printf("%#" PRIx64 "\n", dha->dha_magic_number); + + field("Version"); + printf("%#" PRIx32 "\n", dha->dha_version); + + field("Header size"); + printf("%" PRIu32 "\n", dha->dha_header_size); + + if (verbose) { + arch_print_pt_regs(&dha->dha_regs); + } + return TRUE; +} + diff -urpN crash-3.10-11.orig/lkcd_v5_check.c crash-3.10-11.new/lkcd_v5_check.c --- crash-3.10-11.orig/lkcd_v5_check.c 1970-01-01 03:00:00.000000000 +0300 +++ crash-3.10-11.new/lkcd_v5_check.c 2010-04-14 10:15:12.000000000 +0400 @@ -0,0 +1,520 @@ +/* lkcd_v5_check.c - core analysis suite + * + * Copyright (C) 2010 MontaVista Software LLC + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "check_defs.h" +#include "lkcd_dump_v5.h" + +#if !defined (CRASH_X86) + +typedef struct __dump_header_asm { + /* the dump magic number -- unique to verify dump is valid */ + uint64_t dha_magic_number; + + /* the version number of this dump */ + uint32_t dha_version; + + /* the size of this header (in case we can't read it) */ + uint32_t dha_header_size; +} __attribute__((packed)) dump_header_asm_t; + +#define swap_asm_header(dh_asm) + +#endif + +static dump_header_t dump_header_v5 = { 0 }; +static dump_header_asm_t dump_header_asm_v5 = { 0 }; +static dump_page_t dump_page = { 0 }; +static int arch_print_asmheader_v5(dump_header_asm_t *dha); + +int lkcd_dump_check_header_v5(int fd) +{ + int others; + time_t sec; + uint16_t host, target; + char buf[64]; + dump_header_t *dh; + dh = &dump_header_v5; + + if (lseek(fd, dump_header_offset, SEEK_SET) == ((off_t)-1)) { + incomplete("Could not jump to the dump header at " PRI2offs, + dump_header_offset, dump_header_offset); + return FALSE; + } + + if (read(fd, dh, sizeof(dump_header_t)) != sizeof(dump_header_t)) { + incomplete("Could not read dump header"); + return FALSE; + } + + /* Swap everything from the target endian to mine.*/ + dh->dh_magic_number = from_target_u64(dh->dh_magic_number); + dh->dh_version = from_target_u32(dh->dh_version); + dh->dh_header_size = from_target_u32(dh->dh_header_size); + dh->dh_dump_level = from_target_u32(dh->dh_dump_level); + dh->dh_page_size = from_target_u32(dh->dh_page_size); + dh->dh_memory_size = from_target_u64(dh->dh_memory_size); + dh->dh_memory_start = from_target_u64(dh->dh_memory_start); + dh->dh_memory_end = from_target_u64(dh->dh_memory_end); + dh->dh_num_pages = from_target_u32(dh->dh_num_pages); + dh->dh_time.tv_sec = from_target_u64(dh->dh_time.tv_sec); + dh->dh_time.tv_usec = from_target_u64(dh->dh_time.tv_usec); + if (sizeof(target_ptr) == 64) + dh->dh_current_task = from_target_u64(dh->dh_current_task); + else + dh->dh_current_task = from_target_u32(dh->dh_current_task); + dh->dh_dump_compress = from_target_u32(dh->dh_dump_compress); + dh->dh_dump_flags = from_target_u32(dh->dh_dump_flags); + dh->dh_dump_device = from_target_u32(dh->dh_dump_device); + + if (dh->dh_header_size != sizeof(dump_header_t)) { + corrupted("Header size paradox: dh_header_size = %" PRIu32 + ", sizeof(dump_header_t) = %zu", + dh->dh_header_size, sizeof(dump_header_t)); + return FALSE; + } + + if (silent || !print_header) + return TRUE; + + if (dump_header_offset != 0 || verbose) { + field("Dump header offset"); + printf(PRI2offsNL, dump_header_offset, dump_header_offset); + } + if (verbose) { + field("Magic number"); + printf("%#" PRIx64 " ", dh->dh_magic_number); + if (dh->dh_magic_number == DUMP_MAGIC_NUMBER) + printf("(DUMP_MAGIC_NUMBER)\n"); + else if (dh->dh_magic_number == DUMP_MAGIC_LIVE) + printf("(DUMP_MAGIC_LIVE)\n"); + else + printf("(?)\n"); + + field("Version"); + printf("%#" PRIx32 " (", dh->dh_version); + others = 0; + switch (dh->dh_version & LKCD_DUMP_VERSION_NUMBER_MASK) { + case LKCD_DUMP_V1: + printf("%sLKCD_DUMP_V1", others++ ? "|" : ""); + break; + case LKCD_DUMP_V2: + printf("%sLKCD_DUMP_V2", others++ ? "|" : ""); + break; + case LKCD_DUMP_V3: + printf("%sLKCD_DUMP_V3", others++ ? "|" : ""); + break; + case LKCD_DUMP_V5: + printf("%sLKCD_DUMP_V5", others++ ? "|" : ""); + break; + case LKCD_DUMP_V6: + printf("%sLKCD_DUMP_V6", others++ ? "|" : ""); + break; + case LKCD_DUMP_V7: + printf("%sLKCD_DUMP_V7", others++ ? "|" : ""); + break; + case LKCD_DUMP_V8: + printf("%sLKCD_DUMP_V8", others++ ? "|" : ""); + break; + } + if (dh->dh_version & LKCD_DUMP_MCLX_V0) + printf("%sLKCD_DUMP_MCLX_V0", others++ ? "|" : ""); + if (dh->dh_version & LKCD_DUMP_MCLX_V1) + printf("%sLKCD_DUMP_MCLX_V1", others++ ? "|" : ""); + printf(")\n"); + + field("Header size"); + printf("%" PRIu32 "\n", dh->dh_header_size); + } + + field("Dump level"); + printf("%#" PRIx32 " (", dh->dh_dump_level); + others = 0; + if (dh->dh_dump_level & DUMP_LEVEL_HEADER) + printf("%sDUMP_LEVEL_HEADER", others++ ? "|" : ""); + if (dh->dh_dump_level & DUMP_LEVEL_KERN) + printf("%sDUMP_LEVEL_KERN", others++ ? "|" : ""); + if (dh->dh_dump_level & DUMP_LEVEL_USED) + printf("%sDUMP_LEVEL_USED", others++ ? "|" : ""); + if (dh->dh_dump_level & DUMP_LEVEL_ALL) + printf("%sDUMP_LEVEL_ALL", others++ ? "|" : ""); + printf(")\n"); + + field("Dump compression"); + printf("%#" PRIx32 " (", dh->dh_dump_compress); + others = 0; + if (dh->dh_dump_compress == DUMP_COMPRESS_NONE) + printf("%sDUMP_COMPRESS_NONE", others++ ? "|" : ""); + if (dh->dh_dump_compress & DUMP_COMPRESS_RLE) + printf("%sDUMP_COMPRESS_RLE", others++ ? "|" : ""); + if (dh->dh_dump_compress & DUMP_COMPRESS_GZIP) + printf("%sDUMP_COMPRESS_GZIP", others++ ? "|" : ""); + printf(")\n"); + + if (verbose) { + field("Dump flags"); + others = 0; + printf("%#" PRIx32 " (", dh->dh_dump_flags); + if (dh->dh_dump_flags & DUMP_FLAGS_NONDISRUPT) + printf("%sDUMP_FLAGS_NONDISRUPT", others++ ? "|" : ""); + printf(")\n"); + + field("Dump device"); + printf("%" PRIu32 "\n", dh->dh_dump_device); + + field("Page size"); + printf("%" PRIu32 "\n", dh->dh_page_size); + + field("Memory size"); + printf("%#" PRIx64 "\n", dh->dh_memory_size); + + field("Memory start"); + printf("%#" PRIx64 "\n", dh->dh_memory_start); + + field("Memory end"); + printf("%#" PRIx64 "\n", dh->dh_memory_end); + + field("Num pages"); + printf("%" PRIu32 "\n", dh->dh_num_pages); + + field("Current task"); + printf("%#llx\n", (unsigned long long) dh->dh_current_task); + } + + field("Crash time"); + sec = dh->dh_time.tv_sec; + strftime(buf, sizeof(buf), "%a %b %e %H:%M:%S %Z %Y", + localtime(&sec)); + printf("%s\n", buf); + + field("Kernel name"); + printf("%s\n", dh->dh_utsname_sysname); + field("Node name"); + printf("%s\n", dh->dh_utsname_nodename); + field("Domain name"); + printf("%s\n", dh->dh_utsname_domainname); + field("Kernel release"); + printf("%s\n", dh->dh_utsname_release); + field("Kernel version"); + printf("%s\n", dh->dh_utsname_version); + field("Machine name"); + printf("%s\n", dh->dh_utsname_machine); + + field("Machine type"); + host = 1; + target = from_target_u16(host); + if ((*(char *) &host) && host == target) + printf("little endian\n"); + else + printf("big endian\n"); + + field("Panic message"); + printf("%s\n", dh->dh_panic_string); + + return TRUE; +} + +int lkcd_dump_check_asmheader_v5(int fd) +{ + dump_header_asm_t *dh_asm; + dh_asm = &dump_header_asm_v5; + + if (lseek(fd, dump_header_offset + sizeof(dump_header_t), SEEK_SET) + == ((off_t)-1)) { + incomplete("Could not jump to the asm header at %#" PRIxoff_t, + dump_header_offset + sizeof(dump_header_t)); + return FALSE; + } + + if (read(fd, dh_asm, sizeof(dump_header_asm_t)) != + sizeof(dump_header_asm_t)) { + incomplete("Could not read asm header at %#" PRIxoff_t, + dump_header_offset + sizeof(dump_header_t)); + return FALSE; + } + + swap_asm_header(dh_asm); + + if (silent || !print_asmheader) + return TRUE; + + return arch_print_asmheader_v5(dh_asm); +} + +int lkcd_dump_check_pages_v5(int fd) +{ + int others; + unsigned long pgcnt = 0, cpgs = 0; + ssize_t i, rd; + off_t offs; + char buf[1024]; + dump_page_t *dp; + dump_header_t *dh; + dh = &dump_header_v5; + dp = &dump_page; + + offs = dump_header_offset; + if (dh->dh_page_size < LKCD_OFFSET_TO_FIRST_PAGE) + offs += LKCD_OFFSET_TO_FIRST_PAGE; + else + offs += LKCD_OFFSET_TO_FIRST_BIG_PAGE; + if (lseek(fd, offs, SEEK_SET) == ((off_t)-1)) { + incomplete("Could not jump to the page No %lu (%#lx) at " + "%#" PRIxoff_t, pgcnt, pgcnt, offs); + return FALSE; + } + + if (!silent) + printf("\n"); + do { + if (read(fd, dp, sizeof(dump_page_t)) != sizeof(dump_page_t)) { + incomplete("Could not read page header for page No " + "%lu (%#lx)", pgcnt, pgcnt); + return FALSE; + } + + dp->dp_address = from_target_u64(dp->dp_address); + dp->dp_size = from_target_u32(dp->dp_size); + dp->dp_flags = from_target_u32(dp->dp_flags); + + if (dp->dp_flags & ~(DUMP_DH_COMPRESSED|DUMP_DH_RAW| + DUMP_DH_END|LKCD_DUMP_MCLX_V0)) { + corrupted("Unknown page flag in the dump: %#" PRIx32 + ", page No %lu (%#lx)", + dp->dp_flags, pgcnt, pgcnt); + return FALSE; + } + + if (dp->dp_size > dh->dh_page_size) { + corrupted("Page size paradox: dp_size = %#" PRIx32 + ", dh_page_size = %#" PRIx32 + ", page No %lu (%#lx)", dp->dp_flags, + dh->dh_page_size, pgcnt, pgcnt); + return FALSE; + } + + if ((print_pages || (verbose && !pgcnt)) && !silent) { + field("Page No"); + printf("%lu (%#lx)\n", pgcnt, pgcnt); + + field("Page offset"); + printf(PRI2offsNL, offs, offs); + + field("Page address"); + printf("%#" PRIx64 "\n", dp->dp_address); + + field("Page size"); + printf("%" PRIu32 "\n", dp->dp_size); + + field("Page flags"); + printf("%#" PRIx32 " (", dp->dp_flags); + others = 0; + if (dp->dp_flags & DUMP_DH_COMPRESSED) { + printf("%sDUMP_DH_COMPRESSED", others++ ? "|" : ""); + cpgs++; + } + if (dp->dp_flags & DUMP_DH_RAW) + printf("%sDUMP_DH_RAW", others++ ? "|" : ""); + if (dp->dp_flags & DUMP_DH_END) + printf("%sDUMP_DH_END", others++ ? "|" : ""); + if (dp->dp_flags & LKCD_DUMP_MCLX_V0) + printf("%sLKCD_DUMP_MCLX_V0", others++ ? "|" : ""); + printf(")\n"); + } + + if (dp->dp_flags & DUMP_DH_END) + break; + + pgcnt++; + if (lseek(fd, dp->dp_size, SEEK_CUR) == ((off_t)-1)) { + incomplete("Could not jump to the page No %lu (%#lx)", + pgcnt, pgcnt); + return FALSE; + } + offs += dp->dp_size + sizeof(dump_page_t); + } while (1); + + if (pgcnt > dh->dh_num_pages) { + corrupted("Page count paradox: pgcnt = %lu, dh_num_pages = " + "%" PRIu32, pgcnt, dh->dh_num_pages); + return FALSE; + } + + if (pgcnt < dh->dh_num_pages) { + incomplete("%lu pages lost", + (unsigned long) dh->dh_num_pages - pgcnt); + return FALSE; + } + + if (!silent) { + field("Total pages found"); + printf("%lu (%#lx)\n", pgcnt, pgcnt); + field("Compressed pages"); + printf("%lu\n", cpgs); + field("End-page offset"); + printf(PRI2offsNL, offs, offs); + } + + offs += sizeof(dump_page_t); + do { + rd = read(fd, buf, sizeof(buf)); + + for (i = 0; i < rd; i++) + if (buf[i] != 'm') { + offs += i; + if (endless && !silent) { + field("Dump end"); + printf(PRI2offsNL, offs, offs); + + return TRUE; + } + corrupted("Found wrong symbol inside end page " + "at %#" PRIxoff_t, offs); + return FALSE; + } + + offs += rd; + } while (rd > 0); + + return TRUE; +} + +int lkcd_dump_check_end_page_v5(int fd) +{ + dump_page_t *dp; + char buf[1024]; + ssize_t i, len = 0; + off_t offs; + + offs = lseek(fd, 0, SEEK_END); + while (offs > 0) { + offs -= sizeof(buf); + if (lseek(fd, offs, SEEK_SET) == ((off_t)-1)) { + incomplete("Could not jump to the offset %#" PRIxoff_t, offs); + return FALSE; + } + if (read(fd, buf, sizeof(buf)) != sizeof(buf)) { + incomplete("Could not read last page at %#" PRIxoff_t, offs); + return FALSE; + } + for (i = sizeof(buf); i--; ) + if (buf[i] != 'm') { + i++; + if (i < sizeof(dump_page_t)) { + offs += sizeof(buf) / 2; + len -= sizeof(buf) / 2; + break; + } + i -= sizeof(dump_page_t); + goto found; + } + len += sizeof(buf); + } +found: + dp = (dump_page_t *)(buf + i); + offs += i; + if (from_target_u32(dp->dp_flags) == DUMP_DH_END) + if(len) { + if (!silent) { + printf("\n"); + field("End-page offset"); + printf(PRI2offsNL, offs, offs); + } + + return TRUE; + } + + if(!len) + incomplete("Could not find final marker and page header for it."); + else + corrupted("Invalid page header before final marker."); + return FALSE; +} + +#if defined (CRASH_X86) + +static int arch_print_asmheader_v5(dump_header_asm_t *dha) +{ + int cpu; + struct target_pt_regs *regs; + const char *fmt = "%#" PRIx32 "\n"; + dump_header_t *dh; + dh = &dump_header_v5; + + if (strcasecmp(dh->dh_utsname_machine, "i686") && + strcasecmp(dh->dh_utsname_machine, "i586") && + strcasecmp(dh->dh_utsname_machine, "i486") && + strcasecmp(dh->dh_utsname_machine, "i386") && + strcasecmp(dh->dh_utsname_machine, "athlon")) { + corrupted("Unsupported architecture: %s", dh->dh_utsname_machine); + return FALSE; + } + + printf("\n"); + if (verbose) { + field("ASM Magic number"); + printf("%#" PRIx64 "\n", dha->dha_magic_number); + + field("Version"); + printf("%#" PRIx32 "\n", dha->dha_version); + + field("Header size"); + printf("%" PRIu32 "\n", dha->dha_header_size); + } + + field("Num CPUs"); + printf("%" PRIu32 "\n", dha->dha_smp_num_cpus); + + field("Dumping CPU"); + printf("%" PRIu32 "\n", dha->dha_dumping_cpu); + + if (verbose) { + field("ESP register"); + printf(fmt, dha->dha_esp); + + field("EIP register"); + printf(fmt, dha->dha_eip); + + for (cpu=0; cpu<dha->dha_smp_num_cpus; cpu++) { + regs = &dha->dha_smp_regs[cpu]; + + field("CPU"); + printf("%d\n", cpu); + + arch_print_pt_regs(regs); + } + } + + return TRUE; +} + +#else + +static int arch_print_asmheader_v5(dump_header_asm_t *dha) +{ + printf("\n"); + field("ASM Magic number"); + printf("%#" PRIx64 "\n", dha->dha_magic_number); + + field("Version"); + printf("%#" PRIx32 "\n", dha->dha_version); + + field("Header size"); + printf("%" PRIu32 "\n", dha->dha_header_size); + + return TRUE; +} + +#endif /* if defined(CRASH_<ARCH>)*/ diff -urpN crash-3.10-11.orig/lkcd_v8_check.c crash-3.10-11.new/lkcd_v8_check.c --- crash-3.10-11.orig/lkcd_v8_check.c 1970-01-01 03:00:00.000000000 +0300 +++ crash-3.10-11.new/lkcd_v8_check.c 2010-04-14 10:15:12.000000000 +0400 @@ -0,0 +1,1015 @@ +/* lkcd_v8_check.c - core analysis suite + * + * Copyright (C) 2010 MontaVista Software LLC + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "check_defs.h" +#include "lkcd_dump_v8.h" + +static dump_header_t dump_header_v8 = { 0 }; +static dump_header_asm_t dump_header_asm_v8 = { 0 }; +static dump_page_t dump_page = { 0 }; +static int arch_print_asmheader_v8(dump_header_asm_t *dha); + +int lkcd_dump_check_header_v8(int fd) +{ + int others; + time_t sec; + uint16_t host, target; + char buf[64]; + dump_header_t *dh; + dh = &dump_header_v8; + + if (lseek(fd, dump_header_offset, SEEK_SET) == ((off_t)-1)) { + incomplete("Could not jump to the dump header at " PRI2offs, + dump_header_offset, dump_header_offset); + return FALSE; + } + + if (read(fd, dh, sizeof(dump_header_t)) != sizeof(dump_header_t)) { + incomplete("Could not read dump header"); + return FALSE; + } + + /* Swap everything from the target endian to mine.*/ + dh->dh_magic_number = from_target_u64(dh->dh_magic_number); + dh->dh_version = from_target_u32(dh->dh_version); + dh->dh_header_size = from_target_u32(dh->dh_header_size); + dh->dh_dump_level = from_target_u32(dh->dh_dump_level); + dh->dh_page_size = from_target_u32(dh->dh_page_size); + dh->dh_memory_size = from_target_u64(dh->dh_memory_size); + dh->dh_memory_start = from_target_u64(dh->dh_memory_start); + dh->dh_memory_end = from_target_u64(dh->dh_memory_end); + dh->dh_num_pages = from_target_u32(dh->dh_num_pages); + dh->dh_time.tv_sec = from_target_u64(dh->dh_time.tv_sec); + dh->dh_time.tv_usec = from_target_u64(dh->dh_time.tv_usec); + dh->dh_current_task = from_target_u64(dh->dh_current_task); + dh->dh_dump_compress = from_target_u32(dh->dh_dump_compress); + dh->dh_dump_flags = from_target_u32(dh->dh_dump_flags); + dh->dh_dump_device = from_target_u32(dh->dh_dump_device); + + if (dh->dh_header_size != sizeof(dump_header_t)) { + corrupted("Header size paradox: dh_header_size = %" PRIu32 + ", sizeof(dump_header_t) = %zu", + dh->dh_header_size, sizeof(dump_header_t)); + return FALSE; + } + + if (silent || !print_header) + return TRUE; + + if (dump_header_offset != 0 || verbose) { + field("Dump header offset"); + printf(PRI2offsNL, dump_header_offset, dump_header_offset); + } + if (verbose) { + field("Magic number"); + printf("%#" PRIx64 " ", dh->dh_magic_number); + if (dh->dh_magic_number == DUMP_MAGIC_NUMBER) + printf("(DUMP_MAGIC_NUMBER)\n"); + else if (dh->dh_magic_number == DUMP_MAGIC_LIVE) + printf("(DUMP_MAGIC_LIVE)\n"); + else + printf("(?)\n"); + + field("Version"); + printf("%#" PRIx32 " (", dh->dh_version); + others = 0; + switch (dh->dh_version & LKCD_DUMP_VERSION_NUMBER_MASK) { + case LKCD_DUMP_V1: + printf("%sLKCD_DUMP_V1", others++ ? "|" : ""); + break; + case LKCD_DUMP_V2: + printf("%sLKCD_DUMP_V2", others++ ? "|" : ""); + break; + case LKCD_DUMP_V3: + printf("%sLKCD_DUMP_V3", others++ ? "|" : ""); + break; + case LKCD_DUMP_V5: + printf("%sLKCD_DUMP_V5", others++ ? "|" : ""); + break; + case LKCD_DUMP_V6: + printf("%sLKCD_DUMP_V6", others++ ? "|" : ""); + break; + case LKCD_DUMP_V7: + printf("%sLKCD_DUMP_V7", others++ ? "|" : ""); + break; + case LKCD_DUMP_V8: + printf("%sLKCD_DUMP_V8", others++ ? "|" : ""); + break; + } + if (dh->dh_version & LKCD_DUMP_MCLX_V0) + printf("%sLKCD_DUMP_MCLX_V0", others++ ? "|" : ""); + if (dh->dh_version & LKCD_DUMP_MCLX_V1) + printf("%sLKCD_DUMP_MCLX_V1", others++ ? "|" : ""); + printf(")\n"); + + field("Header size"); + printf("%" PRIu32 "\n", dh->dh_header_size); + } + + field("Dump level"); + printf("%#" PRIx32 " (", dh->dh_dump_level); + others = 0; + if (dh->dh_dump_level & DUMP_LEVEL_HEADER) + printf("%sDUMP_LEVEL_HEADER", others++ ? "|" : ""); + if (dh->dh_dump_level & DUMP_LEVEL_KERN) + printf("%sDUMP_LEVEL_KERN", others++ ? "|" : ""); + if (dh->dh_dump_level & DUMP_LEVEL_USED) + printf("%sDUMP_LEVEL_USED", others++ ? "|" : ""); + if (dh->dh_dump_level & DUMP_LEVEL_ALL) + printf("%sDUMP_LEVEL_ALL", others++ ? "|" : ""); + printf(")\n"); + + field("Dump compression"); + printf("%#" PRIx32 " (", dh->dh_dump_compress); + others = 0; + if (dh->dh_dump_compress == DUMP_COMPRESS_NONE) + printf("%sDUMP_COMPRESS_NONE", others++ ? "|" : ""); + if (dh->dh_dump_compress & DUMP_COMPRESS_RLE) + printf("%sDUMP_COMPRESS_RLE", others++ ? "|" : ""); + if (dh->dh_dump_compress & DUMP_COMPRESS_GZIP) + printf("%sDUMP_COMPRESS_GZIP", others++ ? "|" : ""); + printf(")\n"); + + if (verbose) { + field("Dump flags"); + others = 0; + printf("%#" PRIx32 " (", dh->dh_dump_flags); + if (dh->dh_dump_flags & DUMP_FLAGS_NONDISRUPT) + printf("%sDUMP_FLAGS_NONDISRUPT", others++ ? "|" : ""); + printf(")\n"); + + field("Dump device"); + printf("%" PRIu32 "\n", dh->dh_dump_device); + + field("Page size"); + printf("%" PRIu32 "\n", dh->dh_page_size); + + field("Memory size"); + printf("%#" PRIx64 "\n", dh->dh_memory_size); + + field("Memory start"); + printf("%#" PRIx64 "\n", dh->dh_memory_start); + + field("Memory end"); + printf("%#" PRIx64 "\n", dh->dh_memory_end); + + field("Num pages"); + printf("%" PRIu32 "\n", dh->dh_num_pages); + + field("Current task"); + printf("%#" PRIx64 "\n", dh->dh_current_task); + } + + field("Crash time"); + sec = dh->dh_time.tv_sec; + strftime(buf, sizeof(buf), "%a %b %e %H:%M:%S %Z %Y", + localtime(&sec)); + printf("%s\n", buf); + + field("Kernel name"); + printf("%s\n", dh->dh_utsname_sysname); + field("Node name"); + printf("%s\n", dh->dh_utsname_nodename); + field("Domain name"); + printf("%s\n", dh->dh_utsname_domainname); + field("Kernel release"); + printf("%s\n", dh->dh_utsname_release); + field("Kernel version"); + printf("%s\n", dh->dh_utsname_version); + field("Machine name"); + printf("%s\n", dh->dh_utsname_machine); + + field("Machine type"); + host = 1; + target = from_target_u16(host); + if ((*(char *) &host) && host == target) + printf("little endian\n"); + else + printf("big endian\n"); + + field("Panic message"); + printf("%s\n", dh->dh_panic_string); + + return TRUE; +} + +int lkcd_dump_check_asmheader_v8(int fd) +{ + dump_header_asm_t *dh_asm; + dh_asm = &dump_header_asm_v8; + + if (lseek(fd, dump_header_offset + sizeof(dump_header_t), SEEK_SET) + == ((off_t)-1)) { + incomplete("Could not jump to the asm header at %#" PRIxoff_t, + dump_header_offset + sizeof(dump_header_t)); + return FALSE; + } + + if (read(fd, dh_asm, sizeof(dump_header_asm_t)) != + sizeof(dump_header_asm_t)) { + incomplete("Could not read asm header at %#" PRIxoff_t, + dump_header_offset + sizeof(dump_header_t)); + return FALSE; + } + + swap_asm_header(dh_asm); + + if (silent || !print_asmheader) + return TRUE; + + return arch_print_asmheader_v8(dh_asm); +} + +int lkcd_dump_check_pages_v8(int fd) +{ + int others; + unsigned long pgcnt = 0, cpgs = 0; + ssize_t i, rd; + off_t offs; + char buf[1024]; + dump_page_t *dp; + dump_header_t *dh; + dh = &dump_header_v8; + dp = &dump_page; + + offs = dump_header_offset; + if (dh->dh_page_size < LKCD_OFFSET_TO_FIRST_PAGE) + offs += LKCD_OFFSET_TO_FIRST_PAGE; + else + offs += LKCD_OFFSET_TO_FIRST_BIG_PAGE; + if (lseek(fd, offs, SEEK_SET) == ((off_t)-1)) { + incomplete("Could not jump to the page No %lu (%#lx) at " + "%#" PRIxoff_t, pgcnt, pgcnt, offs); + return FALSE; + } + + if (!silent) + printf("\n"); + do { + if (read(fd, dp, sizeof(dump_page_t)) != sizeof(dump_page_t)) { + incomplete("Could not read page header for page No " + "%lu (%#lx)", pgcnt, pgcnt); + return FALSE; + } + + dp->dp_address = from_target_u64(dp->dp_address); + dp->dp_size = from_target_u32(dp->dp_size); + dp->dp_flags = from_target_u32(dp->dp_flags); + + if (dp->dp_flags & ~(DUMP_DH_COMPRESSED|DUMP_DH_RAW| + DUMP_DH_END|LKCD_DUMP_MCLX_V0)) { + corrupted("Unknown page flag in the dump: %#" PRIx32 + ", page No %lu (%#lx)", + dp->dp_flags, pgcnt, pgcnt); + return FALSE; + } + + if (dp->dp_size > dh->dh_page_size) { + corrupted("Page size paradox: dp_size = %#" PRIx32 + ", dh_page_size = %#" PRIx32 + ", page No %lu (%#lx)", dp->dp_flags, + dh->dh_page_size, pgcnt, pgcnt); + return FALSE; + } + + if ((print_pages || (verbose && !pgcnt)) && !silent) { + field("Page No"); + printf("%lu (%#lx)\n", pgcnt, pgcnt); + + field("Page offset"); + printf(PRI2offsNL, offs, offs); + + field("Page address"); + printf("%#" PRIx64 "\n", dp->dp_address); + + field("Page size"); + printf("%" PRIu32 "\n", dp->dp_size); + + field("Page flags"); + printf("%#" PRIx32 " (", dp->dp_flags); + others = 0; + if (dp->dp_flags & DUMP_DH_COMPRESSED) { + printf("%sDUMP_DH_COMPRESSED", others++ ? "|" : ""); + cpgs++; + } + if (dp->dp_flags & DUMP_DH_RAW) + printf("%sDUMP_DH_RAW", others++ ? "|" : ""); + if (dp->dp_flags & DUMP_DH_END) + printf("%sDUMP_DH_END", others++ ? "|" : ""); + if (dp->dp_flags & LKCD_DUMP_MCLX_V0) + printf("%sLKCD_DUMP_MCLX_V0", others++ ? "|" : ""); + printf(")\n"); + } + + if (dp->dp_flags & DUMP_DH_END) + break; + + pgcnt++; + if (lseek(fd, dp->dp_size, SEEK_CUR) == ((off_t)-1)) { + incomplete("Could not jump to the page No %lu (%#lx)", + pgcnt, pgcnt); + return FALSE; + } + offs += dp->dp_size + sizeof(dump_page_t); + } while (1); + + if (pgcnt > dh->dh_num_pages) { + corrupted("Page count paradox: pgcnt = %lu, dh_num_pages = " + "%" PRIu32, pgcnt, dh->dh_num_pages); + return FALSE; + } + + if (pgcnt < dh->dh_num_pages) { + incomplete("%lu pages lost", + (unsigned long) dh->dh_num_pages - pgcnt); + return FALSE; + } + + if (!silent) { + field("Total pages found"); + printf("%lu (%#lx)\n", pgcnt, pgcnt); + field("Compressed pages"); + printf("%lu\n", cpgs); + field("End-page offset"); + printf(PRI2offsNL, offs, offs); + } + + offs += sizeof(dump_page_t); + do { + rd = read(fd, buf, sizeof(buf)); + + for (i = 0; i < rd; i++) + if (buf[i] != 'm') { + offs += i; + if (endless && !silent) { + field("Dump end"); + printf(PRI2offsNL, offs, offs); + + return TRUE; + } + corrupted("Found wrong symbol inside end page " + "at %#" PRIxoff_t, offs); + return FALSE; + } + + offs += rd; + } while (rd > 0); + + return TRUE; +} + +int lkcd_dump_check_end_page_v8(int fd) +{ + dump_page_t *dp; + char buf[1024]; + ssize_t i, len = 0; + off_t offs; + + offs = lseek(fd, 0, SEEK_END); + while (offs > 0) { + offs -= sizeof(buf); + if (lseek(fd, offs, SEEK_SET) == ((off_t)-1)) { + incomplete("Could not jump to the offset %#" PRIxoff_t, offs); + return FALSE; + } + if (read(fd, buf, sizeof(buf)) != sizeof(buf)) { + incomplete("Could not read last page at %#" PRIxoff_t, offs); + return FALSE; + } + for (i = sizeof(buf); i--; ) + if (buf[i] != 'm') { + i++; + if (i < sizeof(dump_page_t)) { + offs += sizeof(buf) / 2; + len -= sizeof(buf) / 2; + break; + } + i -= sizeof(dump_page_t); + goto found; + } + len += sizeof(buf); + } +found: + dp = (dump_page_t *)(buf + i); + offs += i; + if (from_target_u32(dp->dp_flags) == DUMP_DH_END) + if(len) { + if (!silent) { + printf("\n"); + field("End-page offset"); + printf(PRI2offsNL, offs, offs); + } + + return TRUE; + } + + if(!len) + incomplete("Could not find final marker and page header for it."); + else + corrupted("Invalid page header before final marker."); + return FALSE; +} + +#if defined (CRASH_ARM) + +void arch_print_pt_regs(struct target_pt_regs *regs) +{ + int i; + char buf[20]; + const char *fmt = "%#" PRIx32 "\n"; + + for (i=0; i<18; i++) { + sprintf(buf, "UREG[%d]", i); + field(buf); + printf(fmt, regs->uregs[i]); + } +} + +static int arch_print_asmheader_v8(dump_header_asm_t *dha) +{ + int cpu; + const char *fmt = "%#" PRIx32 "\n"; + _dump_regs_t *regs; + dump_header_t *dh; + dh = &dump_header_v8; + + if (strncasecmp(dh->dh_utsname_machine, "arm", 3)) { + corrupted("Unsupported architecture: %s", dh->dh_utsname_machine); + return FALSE; + } + + printf("\n"); + if (verbose) { + field("ASM Magic number"); + printf("%#" PRIx64 "\n", dha->dha_magic_number); + + field("Version"); + printf("%#" PRIx32 "\n", dha->dha_version); + + field("Header size"); + printf("%" PRIu32 "\n", dha->dha_header_size); + } + + field("Num CPUs"); + printf("%" PRIu32 "\n", dha->dha_smp_num_cpus); + + field("Dumping CPU"); + printf("%" PRIu32 "\n", dha->dha_dumping_cpu); + + if (verbose) { + field("Physical start"); + printf(fmt, dha->dha_physaddr_start); + + for (cpu=0; cpu<dha->dha_smp_num_cpus; cpu++) { + regs = &dha->dha_smp_regs[cpu]; + + field("CPU"); + printf("%d\n", cpu); + + field("Saved PSR"); + printf(fmt, regs->dha_ARM_spsr); + + arch_print_pt_regs(®s->dha_ARM_regs); + } + } + + return TRUE; +} + +#elif defined (CRASH_PPC) + +void arch_print_pt_regs(struct target_pt_regs *regs) +{ + int i; + char buf[20]; + const char *fmt = "%#" PRIx32 "\n"; + + for (i=0; i<32; i++) { + sprintf(buf, "GPR[%d]", i); + field(buf); + printf(fmt, regs->gpr[i]); + } + field("NIP"); + printf(fmt, regs->nip); + field("MSR"); + printf(fmt, regs->msr); + field("Orig. GPR3"); + printf(fmt, regs->orig_gpr3); + field("CTR"); + printf(fmt, regs->ctr); + field("LINK"); + printf(fmt, regs->link); + field("XER"); + printf(fmt, regs->xer); + field("CCR"); + printf(fmt, regs->ccr); + field("MQ"); + printf(fmt, regs->mq); + field("TRAP"); + printf(fmt, regs->trap); + field("DAR"); + printf(fmt, regs->dar); + field("DSISR"); + printf(fmt, regs->dsisr); + field("RESULT"); + printf(fmt, regs->result); +} + +static int arch_print_asmheader_v8(dump_header_asm_t *dha) +{ + int cpu; + const char *fmt = "%#" PRIx32 "\n"; + struct target_pt_regs *regs; + dump_header_t *dh; + dh = &dump_header_v8; + + if (strcasecmp(dh->dh_utsname_machine, "ppc") && + strcasecmp(dh->dh_utsname_machine, "ppc32")) { + corrupted("Unsupported architecture: %s", dh->dh_utsname_machine); + return FALSE; + } + + if (dha->dha_version != 0x2) { + corrupted("Unsupported ASM header version: %#" PRIx32, + dha->dha_version); + return FALSE; + } + + printf("\n"); + if (verbose) { + field("ASM Magic number"); + printf("%#" PRIx64 " ", dha->dha_magic_number); + if (dha->dha_magic_number == DUMP_ASM_MAGIC_NUMBER) + printf("(DUMP_ASM_MAGIC_NUMBER)\n"); + else + printf("(?)\n"); + + field("Version"); + printf("%#" PRIx32 "\n", dha->dha_version); + + field("Header size"); + printf("%" PRIu32 "\n", dha->dha_header_size); + } + + field("Num CPUs"); + printf("%" PRIu32 "\n", dha->dha_smp_num_cpus); + + field("Dumping CPU"); + printf("%" PRIu32 "\n", dha->dha_dumping_cpu); + + if (verbose) { + field("R1 (SP) register"); + printf(fmt, dha->dha_r1); + + field("NIP register"); + printf(fmt, dha->dha_nip); + + for (cpu=0; cpu<dha->dha_smp_num_cpus; cpu++) { + regs = &dha->dha_smp_regs[cpu]; + + field("CPU"); + printf("%d\n", cpu); + + arch_print_pt_regs(regs); + } + } + + return TRUE; +} + +#elif defined (CRASH_X86) + +void arch_print_pt_regs(struct target_pt_regs *regs) +{ + const char *fmt = "%#" PRIx32 "\n"; + + field("EAX"); + printf(fmt, regs->eax); + field("Orig. EAX"); + printf(fmt, regs->orig_eax); + field("EBX"); + printf(fmt, regs->ebx); + field("ECX"); + printf(fmt, regs->ecx); + field("EDX"); + printf(fmt, regs->edx); + field("ESI"); + printf(fmt, regs->esi); + field("EDI"); + printf(fmt, regs->edi); + field("EBP"); + printf(fmt, regs->ebp); + field("ESP"); + printf(fmt, regs->esp); + field("EIP"); + printf(fmt, regs->eip); + field("XDS"); + printf(fmt, regs->xds); + field("XES"); + printf(fmt, regs->xes); + field("XCS"); + printf(fmt, regs->xcs); + field("XSS"); + printf(fmt, regs->xss); + field("EFLAGS"); + printf(fmt, regs->eflags); +} + +static int arch_print_asmheader_v8(dump_header_asm_t *dha) +{ + int cpu; + struct target_pt_regs *regs; + const char *fmt = "%#" PRIx32 "\n"; + dump_header_t *dh; + dh = &dump_header_v8; + + if (strcasecmp(dh->dh_utsname_machine, "i686") && + strcasecmp(dh->dh_utsname_machine, "i586") && + strcasecmp(dh->dh_utsname_machine, "i486") && + strcasecmp(dh->dh_utsname_machine, "i386") && + strcasecmp(dh->dh_utsname_machine, "athlon")) { + corrupted("Unsupported architecture: %s", dh->dh_utsname_machine); + return FALSE; + } + + if (dha->dha_version != 0x3) { + corrupted("Unsupported ASM header version: %#" PRIx32, + dha->dha_version); + return FALSE; + } + + printf("\n"); + if (verbose) { + field("ASM Magic number"); + printf("%#" PRIx64 " ", dha->dha_magic_number); + if (dha->dha_magic_number == DUMP_ASM_MAGIC_NUMBER) + printf("(DUMP_ASM_MAGIC_NUMBER)\n"); + else + printf("(?)\n"); + + field("Version"); + printf("%#" PRIx32 "\n", dha->dha_version); + + field("Header size"); + printf("%" PRIu32 "\n", dha->dha_header_size); + } + + field("Num CPUs"); + printf("%" PRIu32 "\n", dha->dha_smp_num_cpus); + + field("Dumping CPU"); + printf("%" PRIu32 "\n", dha->dha_dumping_cpu); + + if (verbose) { + field("ESP register"); + printf(fmt, dha->dha_esp); + + field("EIP register"); + printf(fmt, dha->dha_eip); + + for (cpu=0; cpu<dha->dha_smp_num_cpus; cpu++) { + regs = &dha->dha_smp_regs[cpu]; + + field("CPU"); + printf("%d\n", cpu); + + arch_print_pt_regs(regs); + } + } + + return TRUE; +} + +#elif defined (CRASH_PPC64) + +void arch_print_pt_regs(struct target_pt_regs *regs) +{ + int i; + char buf[20]; + const char *fmt = "%#" PRIx64 "\n"; + + for (i=0; i<32; i++) { + sprintf(buf, "GPR[%d]", i); + field(buf); + printf(fmt, regs->gpr[i]); + } + field("NIP"); + printf(fmt, regs->nip); + field("MSR"); + printf(fmt, regs->msr); + field("Orig. GPR3"); + printf(fmt, regs->orig_gpr3); + field("CTR"); + printf(fmt, regs->ctr); + field("LINK"); + printf(fmt, regs->link); + field("XER"); + printf(fmt, regs->xer); + field("CCR"); + printf(fmt, regs->ccr); + field("SOFTE"); + printf(fmt, regs->softe); + field("TRAP"); + printf(fmt, regs->trap); + field("DAR"); + printf(fmt, regs->dar); + field("DSISR"); + printf(fmt, regs->dsisr); + field("RESULT"); + printf(fmt, regs->result); +} + +static int arch_print_asmheader_v8(dump_header_asm_t *dha) +{ + int cpu; + struct target_pt_regs *regs; + dump_header_t *dh; + dh = &dump_header_v8; + + if (strncasecmp(dh->dh_utsname_machine, "ppc64", 5)) { + corrupted("Unsupported architecture: %s", dh->dh_utsname_machine); + return FALSE; + } + + if (dha->dha_version != 0x5) { + corrupted("Unsupported ASM header version: %#" PRIx32, + dha->dha_version); + return FALSE; + } + + printf("\n"); + if (verbose) { + field("ASM Magic number"); + printf("%#" PRIx64 " ", dha->dha_magic_number); + if (dha->dha_magic_number == DUMP_ASM_MAGIC_NUMBER) + printf("(DUMP_ASM_MAGIC_NUMBER)\n"); + else + printf("(?)\n"); + + field("Version"); + printf("%#" PRIx32 "\n", dha->dha_version); + + field("Header size"); + printf("%" PRIu32 "\n", dha->dha_header_size); + } + + field("Num CPUs"); + printf("%" PRIu32 "\n", dha->dha_smp_num_cpus); + + field("Dumping CPU"); + printf("%" PRIu32 "\n", dha->dha_dumping_cpu); + + if (verbose) { + for (cpu=0; cpu<dha->dha_smp_num_cpus; cpu++) { + regs = &dha->dha_smp_regs[cpu]; + + field("CPU"); + printf("%d\n", cpu); + + arch_print_pt_regs(regs); + } + } + + return TRUE; +} + +#elif defined (CRASH_X86_64) + +void arch_print_pt_regs(struct target_pt_regs *regs) +{ + const char *fmt = "%#" PRIx64 "\n"; + + field("RAX"); + printf(fmt, regs->rax); + field("Orig. RAX"); + printf(fmt, regs->orig_rax); + field("RBX"); + printf(fmt, regs->rbx); + field("RCX"); + printf(fmt, regs->rcx); + field("RDX"); + printf(fmt, regs->rdx); + field("RSI"); + printf(fmt, regs->rsi); + field("RDI"); + printf(fmt, regs->rdi); + field("RBP"); + printf(fmt, regs->rbp); + field("RSP"); + printf(fmt, regs->rsp); + field("RIP"); + printf(fmt, regs->rip); + field("CS"); + printf(fmt, regs->cs); + field("SS"); + printf(fmt, regs->ss); + field("EFLAGS"); + printf(fmt, regs->eflags); + field("R8"); + printf(fmt, regs->r8); + field("R9"); + printf(fmt, regs->r9); + field("R10"); + printf(fmt, regs->r10); + field("R11"); + printf(fmt, regs->r11); + field("R12"); + printf(fmt, regs->r12); + field("R13"); + printf(fmt, regs->r13); + field("R14"); + printf(fmt, regs->r14); + field("R15"); + printf(fmt, regs->r15); +} + +static int arch_print_asmheader_v8(dump_header_asm_t *dha) +{ + int cpu; + struct target_pt_regs *regs; + dump_header_t *dh; + dh = &dump_header_v8; + + if (strcasecmp(dh->dh_utsname_machine, "x86_64")) { + corrupted("Unsupported architecture: %s", dh->dh_utsname_machine); + return FALSE; + } + + if (dha->dha_version != 0x2) { + corrupted("Unsupported ASM header version: %#" PRIx32, + dha->dha_version); + return FALSE; + } + + printf("\n"); + if (verbose) { + field("ASM Magic number"); + printf("%#" PRIx64 " ", dha->dha_magic_number); + if (dha->dha_magic_number == DUMP_ASM_MAGIC_NUMBER) + printf("(DUMP_ASM_MAGIC_NUMBER)\n"); + else + printf("(?)\n"); + + field("Version"); + printf("%#" PRIx32 "\n", dha->dha_version); + + field("Header size"); + printf("%" PRIu32 "\n", dha->dha_header_size); + } + + field("Num CPUs"); + printf("%" PRIu32 "\n", dha->dha_smp_num_cpus); + + field("Dumping CPU"); + printf("%" PRIu32 "\n", dha->dha_dumping_cpu); + + if (verbose) { + for (cpu=0; cpu<dha->dha_smp_num_cpus; cpu++) { + regs = &dha->dha_smp_regs[cpu]; + + field("CPU"); + printf("%d\n", cpu); + + arch_print_pt_regs(regs); + } + } + + return TRUE; +} + +#elif defined (CRASH_IA64) + +void arch_print_pt_regs(struct target_pt_regs *regs) +{ + const char *fmt = "%#" PRIx64 "\n"; + + field("CR_IPSR"); + printf(fmt, regs->cr_ipsr); + field("CR_IIP"); + printf(fmt, regs->cr_iip); + field("CR_IFS"); + printf(fmt, regs->cr_ifs); + field("AR_UNAT"); + printf(fmt, regs->ar_unat); + field("AR_PFS"); + printf(fmt, regs->ar_pfs); + field("AR_RSC"); + printf(fmt, regs->ar_rsc); + field("AR_RNAT"); + printf(fmt, regs->ar_rnat); + field("AR_BSPSTORE"); + printf(fmt, regs->ar_bspstore); + field("PR"); + printf(fmt, regs->pr); + field("B0"); + printf(fmt, regs->b0); + field("LOADRS"); + printf(fmt, regs->loadrs); + field("R1"); + printf(fmt, regs->r1); + field("R12"); + printf(fmt, regs->r12); + field("R13"); + printf(fmt, regs->r13); +} + +static int arch_print_asmheader_v8(dump_header_asm_t *dha) +{ + int cpu; + struct target_pt_regs *regs; + const char *fmt = "%#" PRIx64 "\n"; + dump_header_t *dh; + dh = &dump_header_v8; + + if (strcasecmp(dh->dh_utsname_machine, "ia64")) { + corrupted("Unsupported architecture: %s", dh->dh_utsname_machine); + return FALSE; + } + + if (dha->dha_version != 0x4) { + corrupted("Unsupported ASM header version: %#" PRIx32, + dha->dha_version); + return FALSE; + } + + printf("\n"); + if (verbose) { + field("ASM Magic number"); + printf("%#" PRIx64 " ", dha->dha_magic_number); + if (dha->dha_magic_number == DUMP_ASM_MAGIC_NUMBER) + printf("(DUMP_ASM_MAGIC_NUMBER)\n"); + else + printf("(?)\n"); + + field("Version"); + printf("%#" PRIx32 "\n", dha->dha_version); + + field("Header size"); + printf("%" PRIu32 "\n", dha->dha_header_size); + } + + field("Num CPUs"); + printf("%" PRIu32 "\n", dha->dha_smp_num_cpus); + + field("Dumping CPU"); + printf("%" PRIu32 "\n", dha->dha_dumping_cpu); + + if (verbose) { + field("Saved RNAT"); + printf(fmt, dha->dha_rnat); + + field("Saved PFS"); + printf(fmt, dha->dha_pfs); + + field("Saved BSPSTORE"); + printf(fmt, dha->dha_bspstore); + + for (cpu=0; cpu<dha->dha_smp_num_cpus; cpu++) { + regs = &dha->dha_smp_regs[cpu]; + + field("CPU"); + printf("%d\n", cpu); + + arch_print_pt_regs(regs); + } + } + + return TRUE; +} + +#else + +/* + * Arches other than x86, ppc, ppc64 and arm don't have lkcd support + */ + +void arch_print_pt_regs(struct target_pt_regs *regs) +{ +} + +static int arch_print_asmheader_v8(dump_header_asm_t *dha) +{ + printf("\n"); + field("ASM Magic number"); + printf("%#" PRIx64 "\n", dha->dha_magic_number); +/* + field("Dumping CPU"); + printf("%" PRIu32 "\n", dha->dha_dumping_cpu); +*/ + return TRUE; +} + +#endif /* if defined(CRASH_<ARCH>)*/ diff -urpN crash-3.10-11.orig/target_types.h crash-3.10-11.new/target_types.h --- crash-3.10-11.orig/target_types.h 2010-02-12 20:12:36.000000000 +0300 +++ crash-3.10-11.new/target_types.h 2010-03-03 22:07:19.000000000 +0300 @@ -250,6 +250,89 @@ typedef uint32_t target_uint; typedef uint16_t target_ushort; typedef uint64_t target_ptr; +struct ia64_fpreg { + union { + target_ulong bits[2]; + long double __dummy; /* force 16-byte alignment */ + } u; +}; + +struct target_pt_regs { + /* The following registers are saved by SAVE_MIN: */ + target_ulong b6; /* scratch */ + target_ulong b7; /* scratch */ + + target_ulong ar_csd; /* used by cmp8xchg16 (scratch) */ + target_ulong ar_ssd; /* reserved for future use (scratch) */ + + target_ulong r8; /* scratch (return value register 0) */ + target_ulong r9; /* scratch (return value register 1) */ + target_ulong r10; /* scratch (return value register 2) */ + target_ulong r11; /* scratch (return value register 3) */ + + target_ulong cr_ipsr; /* interrupted task's psr */ + target_ulong cr_iip; /* interrupted task's instruction pointer */ + /* + * interrupted task's function state; if bit 63 is cleared, it + * contains syscall's ar.pfs.pfm: + */ + target_ulong cr_ifs; + + target_ulong ar_unat; /* interrupted task's NaT register (preserved) */ + target_ulong ar_pfs; /* prev function state */ + target_ulong ar_rsc; /* RSE configuration */ + /* The following two are valid only if cr_ipsr.cpl > 0: */ + target_ulong ar_rnat; /* RSE NaT */ + target_ulong ar_bspstore; /* RSE bspstore */ + + target_ulong pr; /* 64 predicate registers (1 bit each) */ + target_ulong b0; /* return pointer (bp) */ + target_ulong loadrs; /* size of dirty partition << 16 */ + + target_ulong r1; /* the gp pointer */ + target_ulong r12; /* interrupted task's memory stack pointer */ + target_ulong r13; /* thread pointer */ + + target_ulong ar_fpsr; /* floating point status (preserved) */ + target_ulong r15; /* scratch */ + + /* The remaining registers are NOT saved for system calls. */ + + target_ulong r14; /* scratch */ + target_ulong r2; /* scratch */ + target_ulong r3; /* scratch */ + + /* The following registers are saved by SAVE_REST: */ + target_ulong r16; /* scratch */ + target_ulong r17; /* scratch */ + target_ulong r18; /* scratch */ + target_ulong r19; /* scratch */ + target_ulong r20; /* scratch */ + target_ulong r21; /* scratch */ + target_ulong r22; /* scratch */ + target_ulong r23; /* scratch */ + target_ulong r24; /* scratch */ + target_ulong r25; /* scratch */ + target_ulong r26; /* scratch */ + target_ulong r27; /* scratch */ + target_ulong r28; /* scratch */ + target_ulong r29; /* scratch */ + target_ulong r30; /* scratch */ + target_ulong r31; /* scratch */ + + target_ulong ar_ccv; /* compare/exchange value (scratch) */ + + /* + * Floating point registers that the kernel considers scratch: + */ + struct ia64_fpreg f6; /* scratch */ + struct ia64_fpreg f7; /* scratch */ + struct ia64_fpreg f8; /* scratch */ + struct ia64_fpreg f9; /* scratch */ + struct ia64_fpreg f10; /* scratch */ + struct ia64_fpreg f11; /* scratch */ +}; + #define CRASH_SA_INTERRUPT 0x20000000 #define CRASH_SA_PROBE 0x80000000 #define CRASH_SA_SAMPLE_RANDOM 0x10000000 @@ -271,30 +354,30 @@ typedef uint16_t target_ushort; typedef uint64_t target_ptr; struct target_pt_regs { - unsigned long r15; - unsigned long r14; - unsigned long r13; - unsigned long r12; - unsigned long rbp; - unsigned long rbx; + target_ulong r15; + target_ulong r14; + target_ulong r13; + target_ulong r12; + target_ulong rbp; + target_ulong rbx; /* arguments: non interrupts/non tracing syscalls only save upto here*/ - unsigned long r11; - unsigned long r10; - unsigned long r9; - unsigned long r8; - unsigned long rax; - unsigned long rcx; - unsigned long rdx; - unsigned long rsi; - unsigned long rdi; - unsigned long orig_rax; + target_ulong r11; + target_ulong r10; + target_ulong r9; + target_ulong r8; + target_ulong rax; + target_ulong rcx; + target_ulong rdx; + target_ulong rsi; + target_ulong rdi; + target_ulong orig_rax; /* end of arguments */ /* cpu exception frame or undefined */ - unsigned long rip; - unsigned long cs; - unsigned long eflags; - unsigned long rsp; - unsigned long ss; + target_ulong rip; + target_ulong cs; + target_ulong eflags; + target_ulong rsp; + target_ulong ss; /* top of stack page */ }; diff -urpN crash-3.10-11.orig/Makefile crash-3.10-11.new/Makefile --- crash-3.10-11.orig/Makefile 2010-02-12 22:16:52.000000000 +0300 +++ crash-3.10-11.new/Makefile 2010-03-12 22:51:38.000000000 +0300 @@ -80,6 +80,7 @@ REDHAT_HFILES=netdump.h diskdump.h LKCD_DUMP_HFILES=lkcd_vmdump_v1.h lkcd_vmdump_v2_v3.h lkcd_dump_v5.h \ lkcd_dump_v7.h lkcd_dump_v8.h lkcd_fix_mem.h LKCD_TRACE_HFILES=lkcd_x86_trace.h +LKCD_CHECK_HFILES=check_defs.h IBM_HFILES=ibm_common.h UNWIND_HFILES=unwind.h unwind_i.h rse.h @@ -91,9 +92,13 @@ CFILES=main.c tools.c global_data.c memo lkcd_fix_mem.c s390_dump.c s390x_dump.c lkcd_x86_trace.c \ netdump.c diskdump.c unwind.c unwind_decoder.c +LKCD_CHECK_CFILES=check.c check_tools.c \ + lkcd_v1_check.c lkcd_v3_check.c lkcd_v5_check.c lkcd_v8_check.c + SOURCE_FILES=${CFILES} ${GENERIC_HFILES} ${MCORE_HFILES} \ ${REDHAT_CFILES} ${REDHAT_HFILES} ${UNWIND_HFILES} \ - ${LKCD_DUMP_HFILES} ${LKCD_TRACE_HFILES} ${IBM_HFILES} + ${LKCD_DUMP_HFILES} ${LKCD_TRACE_HFILES} ${IBM_HFILES} \ + ${LKCD_CHECK_HFILES} ${LKCD_CHECK_CFILES} OBJECT_FILES=main.o tools.o global_data.o memory.o filesys.o help.o task.o \ build_data.o kernel.o test.o gdb_interface.o net.o dev.o \ @@ -103,6 +108,9 @@ OBJECT_FILES=main.o tools.o global_data. lkcd_fix_mem.o s390_dump.o s390x_dump.o netdump.o diskdump.o \ lkcd_x86_trace.o unwind_v1.o unwind_v2.o unwind_v3.o +LKCD_CHECK_OBJFILES=build_data.o check.o check_tools.o \ + lkcd_v1_check.o lkcd_v3_check.o lkcd_v5_check.o lkcd_v8_check.o + DAEMON_OBJECT_FILES=remote_daemon.o va_server.o va_server_v1.o \ lkcd_common.o lkcd_v1.o lkcd_v2_v3.o lkcd_v5.o lkcd_v7.o lkcd_v8.o \ s390_dump.o s390x_dump.o netdump_daemon.o @@ -220,6 +228,7 @@ REDHATFLAGS=-DREDHAT all: make_configure ./configure -p "RPMPKG=${RPMPKG}" -t ${FORCE_TARGET} -b make --no-print-directory gdb_merge + make --no-print-directory checklkcd gen_target_config: @echo "#ifndef ${TARGET}" >config_target.h @@ -420,6 +429,24 @@ unwind_v3.o: ${GENERIC_HFILES} ${UNWIND_ lkcd_fix_mem.o: ${GENERIC_HFILES} ${LKCD_HFILES} lkcd_fix_mem.c $(CC) -c ${CFLAGS} lkcd_fix_mem.c ${WARNING_OPTIONS} ${WARNING_ERROR} +check.o: ${LKCD_CHECK_HFILES} check.c + $(CC) -c ${CFLAGS} check.c ${WARNING_OPTIONS} ${WARNING_ERROR} + +check_tools.o: ${LKCD_CHECK_HFILES} check_tools.c + $(CC) -c ${CFLAGS} check_tools.c ${WARNING_OPTIONS} ${WARNING_ERROR} + +lkcd_v1_check.o: ${GENERIC_HFILES} ${LKCD_DUMP_HFILES} ${LKCD_CHECK_HFILES} lkcd_v1_check.c + $(CC) -c ${CFLAGS} -DMCLX lkcd_v1_check.c ${WARNING_OPTIONS} ${WARNING_ERROR} + +lkcd_v3_check.o: ${GENERIC_HFILES} ${LKCD_DUMP_HFILES} ${LKCD_CHECK_HFILES} lkcd_v3_check.c + $(CC) -c ${CFLAGS} -DMCLX lkcd_v3_check.c ${WARNING_OPTIONS} ${WARNING_ERROR} + +lkcd_v5_check.o: ${GENERIC_HFILES} ${LKCD_DUMP_HFILES} ${LKCD_CHECK_HFILES} lkcd_v5_check.c + $(CC) -c ${CFLAGS} -DMCLX lkcd_v5_check.c ${WARNING_OPTIONS} ${WARNING_ERROR} + +lkcd_v8_check.o: ${GENERIC_HFILES} ${LKCD_DUMP_HFILES} ${LKCD_CHECK_HFILES} lkcd_v8_check.c + $(CC) -c ${CFLAGS} -DMCLX lkcd_v8_check.c ${WARNING_OPTIONS} ${WARNING_ERROR} + ${PROGRAM}: force make --no-print-directory all @@ -436,6 +463,9 @@ ${PROGRAM}d: daemon_deprecated make_conf daemon: ${DAEMON_OBJECT_FILES} $(CC) ${LDFLAGS} -o ${PROGRAM}d ${DAEMON_OBJECT_FILES} build_data.o -lz +checklkcd: ${LKCD_CHECK_OBJFILES} + $(CC) ${LDFLAGS} -o $@ ${LKCD_CHECK_OBJFILES} + files: make_configure ./configure -q -b make --no-print-directory show_files
-- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility