diff --git a/.crash.metadata b/.crash.metadata new file mode 100644 index 0000000..c8dff53 --- /dev/null +++ b/.crash.metadata @@ -0,0 +1 @@ +2216841453fec77f7f964f9bcd211102ad465ff0 SOURCES/crash-7.0.2.tar.gz diff --git a/README.md b/README.md deleted file mode 100644 index 0e7897f..0000000 --- a/README.md +++ /dev/null @@ -1,5 +0,0 @@ -The master branch has no content - -Look at the c7 branch if you are working with CentOS-7, or the c4/c5/c6 branch for CentOS-4, 5 or 6 - -If you find this file in a distro specific branch, it means that no content has been checked in yet diff --git a/SOURCES/lzo_snappy.patch b/SOURCES/lzo_snappy.patch new file mode 100644 index 0000000..73d2a4f --- /dev/null +++ b/SOURCES/lzo_snappy.patch @@ -0,0 +1,22 @@ +--- crash-7.0.2/diskdump.c.orig ++++ crash-7.0.2/diskdump.c +@@ -23,6 +23,8 @@ + * GNU General Public License for more details. + */ + ++#define LZO ++#define SNAPPY + #include "defs.h" + #include "diskdump.h" + +--- crash-7.0.2/Makefile.orig ++++ crash-7.0.2/Makefile +@@ -223,7 +223,7 @@ all: make_configure + gdb_merge: force + @if [ ! -f ${GDB}/README ]; then \ + make --no-print-directory gdb_unzip; fi +- @echo "${LDFLAGS} -lz -ldl -rdynamic" > ${GDB}/gdb/mergelibs ++ @echo "${LDFLAGS} -lz -llzo2 -lsnappy -ldl -rdynamic" > ${GDB}/gdb/mergelibs + @echo "../../${PROGRAM} ../../${PROGRAM}lib.a" > ${GDB}/gdb/mergeobj + @rm -f ${PROGRAM} + @if [ ! -f ${GDB}/config.status ]; then \ diff --git a/SOURCES/rhel7.0_beta.patch b/SOURCES/rhel7.0_beta.patch new file mode 100644 index 0000000..f1b2239 --- /dev/null +++ b/SOURCES/rhel7.0_beta.patch @@ -0,0 +1,2425 @@ +--- crash-7.0.2/main.c 2013-10-25 15:28:55.938879568 -0400 ++++ crash-7.0.3/main.c 2013-10-15 15:55:10.136390264 -0400 +@@ -1335,6 +1335,8 @@ dump_program_context(void) + fprintf(fp, "%sGET_LOG", others++ ? "|" : ""); + if (pc->flags2 & VMCOREINFO) + fprintf(fp, "%sVMCOREINFO", others++ ? "|" : ""); ++ if (pc->flags2 & ALLOW_FP) ++ fprintf(fp, "%sALLOW_FP", others++ ? "|" : ""); + fprintf(fp, ")\n"); + + fprintf(fp, " namelist: %s\n", pc->namelist); +--- crash-7.0.2/tools.c 2013-10-25 15:28:55.922879569 -0400 ++++ crash-7.0.3/tools.c 2013-10-25 10:09:31.938757537 -0400 +@@ -989,7 +989,7 @@ dtoi(char *s, int flags, int *errptr) + if ((s[j] < '0' || s[j] > '9')) + break ; + +- if (s[j] != '\0' || (sscanf(s, "%d", &retval) != 1)) { ++ if (s[j] != '\0' || (sscanf(s, "%d", (int *)&retval) != 1)) { + if (!(flags & QUIET)) + error(INFO, "%s: \"%c\" is not a digit 0 - 9\n", + s, s[j]); +@@ -5489,6 +5489,19 @@ swap32(uint32_t val, int swap) + return val; + } + ++/* ++ * Get a sufficiently large buffer for cpumask. ++ * You should call FREEBUF() on the result when you no longer need it. ++ */ ++ulong * ++get_cpumask_buf(void) ++{ ++ int cpulen; ++ if ((cpulen = STRUCT_SIZE("cpumask_t")) < 0) ++ cpulen = DIV_ROUND_UP(kt->cpus, BITS_PER_LONG) * sizeof(ulong); ++ return (ulong *)GETBUF(cpulen); ++} ++ + int + make_cpumask(char *s, ulong *mask, int flags, int *errptr) + { +@@ -5505,14 +5518,20 @@ make_cpumask(char *s, ulong *mask, int f + p = strtok(s, ","); + while (p) { + s = strtok(NULL, ""); +- start = end = -1; +- q = strtok(p, "-"); +- start = dtoi(q, flags, errptr); +- if ((q = strtok(NULL, "-"))) +- end = dtoi(q, flags, errptr); + +- if (end == -1) +- end = start; ++ if (STREQ(p, "a") || STREQ(p, "all")) { ++ start = 0; ++ end = kt->cpus - 1; ++ } else { ++ start = end = -1; ++ q = strtok(p, "-"); ++ start = dtoi(q, flags, errptr); ++ if ((q = strtok(NULL, "-"))) ++ end = dtoi(q, flags, errptr); ++ ++ if (end == -1) ++ end = start; ++ } + + for (i = start; i <= end; i++) + SET_BIT(mask, i); +--- crash-7.0.2/memory.c 2013-10-25 15:28:55.934879568 -0400 ++++ crash-7.0.3/memory.c 2013-10-25 10:09:35.641757367 -0400 +@@ -134,6 +134,10 @@ static char *error_handle_string(ulong); + static void dump_mem_map(struct meminfo *); + static void dump_mem_map_SPARSEMEM(struct meminfo *); + static void fill_mem_map_cache(ulong, ulong, char *); ++static void page_flags_init(void); ++static int page_flags_init_from_pageflag_names(void); ++static int page_flags_init_from_pageflags_enum(void); ++static int translate_page_flags(char *, ulong); + static void dump_free_pages(struct meminfo *); + static int dump_zone_page_usage(void); + static void dump_multidimensional_free_pages(struct meminfo *); +@@ -613,6 +617,13 @@ vm_init(void) + MEMBER_OFFSET_INIT(kmem_list3_free_objects, + kmem_cache_node_struct, "free_objects"); + MEMBER_OFFSET_INIT(kmem_list3_shared, kmem_cache_node_struct, "shared"); ++ /* ++ * Common to slab/slub ++ */ ++ ANON_MEMBER_OFFSET_INIT(page_slab, "page", "slab_cache"); ++ ANON_MEMBER_OFFSET_INIT(page_slab_page, "page", "slab_page"); ++ ANON_MEMBER_OFFSET_INIT(page_first_page, "page", "first_page"); ++ + } else if (MEMBER_EXISTS("kmem_cache", "cpu_slab") && + STRUCT_EXISTS("kmem_cache_node")) { + vt->flags |= KMALLOC_SLUB; +@@ -642,6 +653,7 @@ vm_init(void) + ANON_MEMBER_OFFSET_INIT(page_slab, "page", "slab"); + if (INVALID_MEMBER(page_slab)) + ANON_MEMBER_OFFSET_INIT(page_slab, "page", "slab_cache"); ++ ANON_MEMBER_OFFSET_INIT(page_slab_page, "page", "slab_page"); + ANON_MEMBER_OFFSET_INIT(page_first_page, "page", "first_page"); + ANON_MEMBER_OFFSET_INIT(page_freelist, "page", "freelist"); + if (INVALID_MEMBER(kmem_cache_objects)) { +@@ -703,16 +715,16 @@ vm_init(void) + } + + if (!kt->kernel_NR_CPUS) { +- if (ARRAY_LENGTH(kmem_cache_s_cpudata)) ++ if (enumerator_value("WORK_CPU_UNBOUND", (long *)&value1)) ++ kt->kernel_NR_CPUS = (int)value1; ++ else if ((i = get_array_length("__per_cpu_offset", NULL, 0))) ++ kt->kernel_NR_CPUS = i; ++ else if (ARRAY_LENGTH(kmem_cache_s_cpudata)) + kt->kernel_NR_CPUS = ARRAY_LENGTH(kmem_cache_s_cpudata); + else if (ARRAY_LENGTH(kmem_cache_s_array)) + kt->kernel_NR_CPUS = ARRAY_LENGTH(kmem_cache_s_array); + else if (ARRAY_LENGTH(kmem_cache_cpu_slab)) + kt->kernel_NR_CPUS = ARRAY_LENGTH(kmem_cache_cpu_slab); +- else if (enumerator_value("WORK_CPU_UNBOUND", (long *)&value1)) +- kt->kernel_NR_CPUS = (int)value1; +- else if ((i = get_array_length("__per_cpu_offset", NULL, 0))) +- kt->kernel_NR_CPUS = i; + } + + if (CRASHDEBUG(1)) +@@ -1025,8 +1037,7 @@ vm_init(void) + + kmem_cache_init(); + +- PG_reserved_flag_init(); +- PG_slab_flag_init(); ++ page_flags_init(); + + vt->flags |= VM_INIT; + } +@@ -4533,15 +4544,37 @@ PG_slab_flag_init(void) + char buf[BUFSIZE]; /* safe for a page struct */ + + /* +- * Set the old defaults in case the search below fails. ++ * Set the old defaults in case all else fails. + */ +- if (VALID_MEMBER(page_pte)) { ++ if (enumerator_value("PG_slab", (long *)&flags)) { ++ vt->PG_slab = flags; ++ if (CRASHDEBUG(2)) ++ fprintf(fp, "PG_slab (enum): %lx\n", vt->PG_slab); ++ } else if (VALID_MEMBER(page_pte)) { + if (THIS_KERNEL_VERSION < LINUX(2,6,0)) + vt->PG_slab = 10; + else if (THIS_KERNEL_VERSION >= LINUX(2,6,0)) + vt->PG_slab = 7; +- } else if (THIS_KERNEL_VERSION >= LINUX(2,6,0)) +- vt->PG_slab = 7; ++ } else if (THIS_KERNEL_VERSION >= LINUX(2,6,0)) { ++ vt->PG_slab = 7; ++ } else { ++ if (try_get_symbol_data("vm_area_cachep", sizeof(void *), &vaddr) && ++ phys_to_page((physaddr_t)VTOP(vaddr), &pageptr) && ++ readmem(pageptr, KVADDR, buf, SIZE(page), ++ "vm_area_cachep page", RETURN_ON_ERROR|QUIET)) { ++ ++ flags = ULONG(buf + OFFSET(page_flags)); ++ ++ if ((bit = ffsl(flags))) { ++ vt->PG_slab = bit - 1; ++ ++ if (CRASHDEBUG(2)) ++ fprintf(fp, ++ "PG_slab bit: vaddr: %lx page: %lx flags: %lx => %ld\n", ++ vaddr, pageptr, flags, vt->PG_slab); ++ } ++ } ++ } + + if (vt->flags & KMALLOC_SLUB) { + /* +@@ -4561,34 +4594,20 @@ PG_slab_flag_init(void) + fprintf(fp, "PG_head_tail_mask: %lx\n", + vt->PG_head_tail_mask); + } +- +- return; +- } +- +- if (enumerator_value("PG_slab", (long *)&flags)) { +- vt->PG_slab = flags; +- if (CRASHDEBUG(2)) +- fprintf(fp, "PG_slab (enum): %lx\n", vt->PG_slab); +- return; +- } +- +- if (try_get_symbol_data("vm_area_cachep", sizeof(void *), &vaddr) && +- phys_to_page((physaddr_t)VTOP(vaddr), &pageptr) && +- readmem(pageptr, KVADDR, buf, SIZE(page), +- "vm_area_cachep page", RETURN_ON_ERROR|QUIET)) { +- +- flags = ULONG(buf + OFFSET(page_flags)); +- +- if ((bit = ffsl(flags))) { +- vt->PG_slab = bit - 1; +- +- if (CRASHDEBUG(2)) +- fprintf(fp, +- "PG_slab bit: vaddr: %lx page: %lx flags: %lx => %ld\n", +- vaddr, pageptr, flags, vt->PG_slab); +- ++ } else { ++ if (enumerator_value("PG_tail", (long *)&flags)) ++ vt->PG_head_tail_mask = (1L << flags); ++ else if (enumerator_value("PG_compound", (long *)&flags) && ++ enumerator_value("PG_reclaim", (long *)&flags2)) { ++ vt->PG_head_tail_mask = ((1L << flags) | (1L << flags2)); ++ if (CRASHDEBUG(2)) ++ fprintf(fp, "PG_head_tail_mask: %lx (PG_compound|PG_reclaim)\n", ++ vt->PG_head_tail_mask); + } + } ++ ++ if (!vt->PG_slab) ++ error(INFO, "cannot determine PG_slab bit value\n"); + } + + /* +@@ -5009,7 +5028,10 @@ dump_mem_map_SPARSEMEM(struct meminfo *m + bufferindex += sprintflag("%sreserved"); + bufferindex += sprintf(outputbuffer+bufferindex, "\n"); + } else if (THIS_KERNEL_VERSION > LINUX(2,4,9)) { +- bufferindex += sprintf(outputbuffer+bufferindex, "%lx\n", flags); ++ if (vt->flags & PAGEFLAGS) ++ bufferindex += translate_page_flags(outputbuffer+bufferindex, flags); ++ else ++ bufferindex += sprintf(outputbuffer+bufferindex, "%lx\n", flags); + } else { + + if ((flags >> v24_PG_locked) & 1) +@@ -5444,7 +5466,10 @@ dump_mem_map(struct meminfo *mi) + bufferindex += sprintflag("%sreserved"); + bufferindex += sprintf(outputbuffer+bufferindex, "\n"); + } else if (THIS_KERNEL_VERSION > LINUX(2,4,9)) { +- bufferindex += sprintf(outputbuffer+bufferindex, "%lx\n", flags); ++ if (vt->flags & PAGEFLAGS) ++ bufferindex += translate_page_flags(outputbuffer+bufferindex, flags); ++ else ++ bufferindex += sprintf(outputbuffer+bufferindex, "%lx\n", flags); + } else { + + if ((flags >> v24_PG_locked) & 1) +@@ -5591,6 +5616,196 @@ fill_mem_map_cache(ulong pp, ulong ppend + } + } + ++static void ++page_flags_init(void) ++{ ++ if (!page_flags_init_from_pageflag_names()) ++ page_flags_init_from_pageflags_enum(); ++ ++ PG_reserved_flag_init(); ++ PG_slab_flag_init(); ++} ++ ++static int ++page_flags_init_from_pageflag_names(void) ++{ ++ int i, len; ++ char *buffer, *nameptr; ++ char namebuf[BUFSIZE]; ++ ulong mask; ++ void *name; ++ ++ MEMBER_OFFSET_INIT(trace_print_flags_mask, "trace_print_flags", "mask"); ++ MEMBER_OFFSET_INIT(trace_print_flags_name, "trace_print_flags", "name"); ++ STRUCT_SIZE_INIT(trace_print_flags, "trace_print_flags"); ++ ++ if (INVALID_SIZE(trace_print_flags) || ++ INVALID_MEMBER(trace_print_flags_mask) || ++ INVALID_MEMBER(trace_print_flags_name) || ++ !kernel_symbol_exists("pageflag_names") || ++ !(len = get_array_length("pageflag_names", NULL, 0))) ++ return FALSE; ++ ++ buffer = GETBUF(SIZE(trace_print_flags) * len); ++ ++ if (!readmem(symbol_value("pageflag_names"), KVADDR, buffer, ++ SIZE(trace_print_flags) * len, "pageflag_names array", ++ RETURN_ON_ERROR)) { ++ FREEBUF(buffer); ++ return FALSE; ++ } ++ ++ if (!(vt->pageflags_data = (struct pageflags_data *) ++ malloc(sizeof(struct pageflags_data) * len))) { ++ error(INFO, "cannot malloc pageflags_data cache\n"); ++ FREEBUF(buffer); ++ return FALSE; ++ } ++ ++ if (CRASHDEBUG(1)) ++ fprintf(fp, "pageflags from pageflag_names: \n"); ++ ++ for (i = 0; i < len; i++) { ++ mask = ULONG(buffer + (SIZE(trace_print_flags)*i) + ++ OFFSET(trace_print_flags_mask)); ++ name = VOID_PTR(buffer + (SIZE(trace_print_flags)*i) + ++ OFFSET(trace_print_flags_name)); ++ ++ if ((mask == -1UL) && !name) { /* Linux 3.5 and earlier */ ++ len--; ++ break; ++ } ++ ++ if (!read_string((ulong)name, namebuf, BUFSIZE-1)) { ++ error(INFO, "failed to read pageflag_names entry\n", ++ i, name, mask); ++ goto pageflags_fail; ++ } ++ ++ if (!(nameptr = (char *)malloc(strlen(namebuf)+1))) { ++ error(INFO, "cannot malloc pageflag_names space\n"); ++ goto pageflags_fail; ++ } ++ strcpy(nameptr, namebuf); ++ ++ vt->pageflags_data[i].name = nameptr; ++ vt->pageflags_data[i].mask = mask; ++ ++ if (CRASHDEBUG(1)) { ++ fprintf(fp, " %08lx %s\n", ++ vt->pageflags_data[i].mask, ++ vt->pageflags_data[i].name); ++ } ++ } ++ ++ FREEBUF(buffer); ++ vt->nr_pageflags = len; ++ vt->flags |= PAGEFLAGS; ++ return TRUE; ++ ++pageflags_fail: ++ FREEBUF(buffer); ++ free(vt->pageflags_data); ++ vt->pageflags_data = NULL; ++ return FALSE; ++} ++ ++static int ++page_flags_init_from_pageflags_enum(void) ++{ ++ int c; ++ int p, len; ++ char *nameptr; ++ char buf[BUFSIZE]; ++ char *arglist[MAXARGS]; ++ ++ if (!(vt->pageflags_data = (struct pageflags_data *) ++ malloc(sizeof(struct pageflags_data) * 32))) { ++ error(INFO, "cannot malloc pageflags_data cache\n"); ++ return FALSE; ++ } ++ ++ p = 0; ++ pc->flags2 |= ALLOW_FP; ++ open_tmpfile(); ++ ++ if (dump_enumerator_list("pageflags")) { ++ rewind(pc->tmpfile); ++ while (fgets(buf, BUFSIZE, pc->tmpfile)) { ++ if (!strstr(buf, " = ")) ++ continue; ++ ++ c = parse_line(buf, arglist); ++ ++ if (strstr(arglist[0], "__NR_PAGEFLAGS")) { ++ len = atoi(arglist[2]); ++ if (!len || (len > 32)) ++ goto enum_fail; ++ vt->nr_pageflags = len; ++ break; ++ } ++ ++ if (!(nameptr = (char *)malloc(strlen(arglist[0])))) { ++ error(INFO, "cannot malloc pageflags name space\n"); ++ goto enum_fail; ++ } ++ strcpy(nameptr, arglist[0] + strlen("PG_")); ++ vt->pageflags_data[p].name = nameptr; ++ vt->pageflags_data[p].mask = 1 << atoi(arglist[2]); ++ ++ p++; ++ } ++ } else ++ goto enum_fail; ++ ++ close_tmpfile(); ++ pc->flags2 &= ~ALLOW_FP; ++ ++ if (CRASHDEBUG(1)) { ++ fprintf(fp, "pageflags from enum: \n"); ++ for (p = 0; p < vt->nr_pageflags; p++) ++ fprintf(fp, " %08lx %s\n", ++ vt->pageflags_data[p].mask, ++ vt->pageflags_data[p].name); ++ } ++ ++ vt->flags |= PAGEFLAGS; ++ return TRUE; ++ ++enum_fail: ++ close_tmpfile(); ++ pc->flags2 &= ~ALLOW_FP; ++ ++ for (c = 0; c < p; c++) ++ free(vt->pageflags_data[c].name); ++ free(vt->pageflags_data); ++ vt->pageflags_data = NULL; ++ vt->nr_pageflags = 0; ++ ++ return FALSE; ++} ++ ++static int ++translate_page_flags(char *buffer, ulong flags) ++{ ++ char buf[BUFSIZE]; ++ int i, others; ++ ++ sprintf(buf, "%lx", flags); ++ ++ if (flags) { ++ for (i = others = 0; i < vt->nr_pageflags; i++) { ++ if (flags & vt->pageflags_data[i].mask) ++ sprintf(&buf[strlen(buf)], "%s%s", ++ others++ ? "," : " ", ++ vt->pageflags_data[i].name); ++ } ++ } ++ strcat(buf, "\n"); ++ strcpy(buffer, buf); ++ ++ return(strlen(buf)); ++} + + /* + * dump_page_hash_table() displays the entries in each page_hash_table. +@@ -7240,7 +7455,8 @@ dump_kmeminfo(void) + page_cache_size = nr_file_pages - swapper_space_nrpages - + buffer_pages; + FREEBUF(swapper_space); +- } ++ } else ++ page_cache_size = 0; + + + pct = (page_cache_size * 100)/totalram_pages; +@@ -8085,7 +8301,9 @@ vaddr_to_kmem_cache(ulong vaddr, char *b + return NULL; + } + +- if (vt->flags & KMALLOC_SLUB) { ++ if ((vt->flags & KMALLOC_SLUB) || ++ ((vt->flags & KMALLOC_COMMON) && ++ VALID_MEMBER(page_slab) && VALID_MEMBER(page_first_page))) { + readmem(compound_head(page)+OFFSET(page_slab), + KVADDR, &cache, sizeof(void *), + "page.slab", FAULT_ON_ERROR); +@@ -8136,6 +8354,10 @@ vaddr_to_slab(ulong vaddr) + + if (vt->flags & KMALLOC_SLUB) + slab = compound_head(page); ++ else if ((vt->flags & KMALLOC_COMMON) && VALID_MEMBER(page_slab_page)) ++ readmem(page+OFFSET(page_slab_page), ++ KVADDR, &slab, sizeof(void *), ++ "page.slab_page", FAULT_ON_ERROR); + else if (VALID_MEMBER(page_prev)) + readmem(page+OFFSET(page_prev), + KVADDR, &slab, sizeof(void *), +@@ -8212,7 +8434,7 @@ kmem_cache_init(void) + OFFSET(kmem_cache_s_num) : OFFSET(kmem_cache_s_c_num); + next_offset = vt->flags & (PERCPU_KMALLOC_V1|PERCPU_KMALLOC_V2) ? + OFFSET(kmem_cache_s_next) : OFFSET(kmem_cache_s_c_nextp); +- max_cnum = max_limit = max_cpus = cache_count = 0; ++ max_cnum = max_limit = max_cpus = cache_count = tmp2 = 0; + + /* + * Pre-2.6 versions used the "cache_cache" as the head of the +@@ -8431,6 +8653,43 @@ kmem_cache_downsize(void) + FREEBUF(cache_buf); + } + ++/* ++ * Stash a list of presumably-corrupted slab cache addresses. ++ */ ++static void ++mark_bad_slab_cache(ulong cache) ++{ ++ size_t sz; ++ ++ if (vt->nr_bad_slab_caches) { ++ sz = sizeof(ulong) * (vt->nr_bad_slab_caches + 1); ++ if (!(vt->bad_slab_caches = realloc(vt->bad_slab_caches, sz))) { ++ error(INFO, "cannot realloc bad_slab_caches array\n"); ++ vt->nr_bad_slab_caches = 0; ++ return; ++ } ++ } else { ++ if (!(vt->bad_slab_caches = (ulong *)malloc(sizeof(ulong)))) { ++ error(INFO, "cannot malloc bad_slab_caches array\n"); ++ return; ++ } ++ } ++ ++ vt->bad_slab_caches[vt->nr_bad_slab_caches++] = cache; ++} ++ ++static int ++bad_slab_cache(ulong cache) ++{ ++ int i; ++ ++ for (i = 0; i < vt->nr_bad_slab_caches; i++) { ++ if (vt->bad_slab_caches[i] == cache) ++ return TRUE; ++ } ++ ++ return FALSE; ++} + + /* + * Determine the largest cpudata limit for a given cache. +@@ -8526,8 +8785,13 @@ kmem_cache_s_array_nodes: + for (i = max_limit = 0; (i < kt->cpus) && cpudata[i]; i++) { + if (!readmem(cpudata[i]+OFFSET(array_cache_limit), + KVADDR, &limit, sizeof(int), +- "array cache limit", RETURN_ON_ERROR)) +- goto bail_out; ++ "array cache limit", RETURN_ON_ERROR)) { ++ error(INFO, ++ "kmem_cache: %lx: invalid array_cache pointer: %lx\n", ++ cache, cpudata[i]); ++ mark_bad_slab_cache(cache); ++ return max_limit; ++ } + if (CRASHDEBUG(3)) + fprintf(fp, " array limit[%d]: %d\n", i, limit); + if (limit > max_limit) +@@ -9232,6 +9496,11 @@ dump_kmem_cache_percpu_v2(struct meminfo + goto next_cache; + } + ++ if (bad_slab_cache(si->cache)) { ++ fprintf(fp, "%lx %-18s [INVALID/CORRUPTED]\n", si->cache, buf); ++ goto next_cache; ++ } ++ + si->curname = buf; + + readmem(si->cache+OFFSET(kmem_cache_s_objsize), +@@ -9264,7 +9533,7 @@ dump_kmem_cache_percpu_v2(struct meminfo + "kmem_cache_s num", FAULT_ON_ERROR); + si->c_num = (ulong)tmp_val; + +- if( vt->flags & PERCPU_KMALLOC_V2_NODES ) ++ if (vt->flags & PERCPU_KMALLOC_V2_NODES) + do_slab_chain_percpu_v2_nodes(SLAB_GET_COUNTS, si); + else + do_slab_chain_percpu_v2(SLAB_GET_COUNTS, si); +@@ -10160,22 +10429,22 @@ do_slab_chain_percpu_v2_nodes(long cmd, + if (!slab_chains[s]) + continue; + +- if (!specified_slab) { +- if (!readmem(slab_chains[s], +- KVADDR, &si->slab, sizeof(ulong), +- "slabs", QUIET|RETURN_ON_ERROR)) { +- error(INFO, +- "%s: %s list: bad slab pointer: %lx\n", +- si->curname, +- slab_chain_name_v2[s], +- slab_chains[s]); +- list_borked = 1; +- continue; ++ if (!specified_slab) { ++ if (!readmem(slab_chains[s], ++ KVADDR, &si->slab, sizeof(ulong), ++ "slabs", QUIET|RETURN_ON_ERROR)) { ++ error(INFO, "%s: %s list: " ++ "bad slab pointer: %lx\n", ++ si->curname, ++ slab_chain_name_v2[s], ++ slab_chains[s]); ++ list_borked = 1; ++ continue; + } + last = slab_chains[s]; + } else + last = 0; +- ++ + if (si->slab == slab_chains[s]) + continue; + +@@ -11709,6 +11978,8 @@ dump_vm_table(int verbose) + fprintf(fp, "%sVM_EVENT", others++ ? "|" : "");\ + if (vt->flags & PGCNT_ADJ) + fprintf(fp, "%sPGCNT_ADJ", others++ ? "|" : "");\ ++ if (vt->flags & PAGEFLAGS) ++ fprintf(fp, "%sPAGEFLAGS", others++ ? "|" : "");\ + if (vt->flags & SWAPINFO_V1) + fprintf(fp, "%sSWAPINFO_V1", others++ ? "|" : "");\ + if (vt->flags & SWAPINFO_V2) +@@ -11747,10 +12018,15 @@ dump_vm_table(int verbose) + fprintf(fp, " kmem_cache_count: %ld\n", vt->kmem_cache_count); + fprintf(fp, " kmem_cache_namelen: %d\n", vt->kmem_cache_namelen); + fprintf(fp, "kmem_cache_len_nodes: %ld\n", vt->kmem_cache_len_nodes); +- fprintf(fp, " PG_reserved: %lx\n", vt->PG_reserved); +- fprintf(fp, " PG_slab: %ld (%lx)\n", vt->PG_slab, +- (ulong)1 << vt->PG_slab); +- fprintf(fp, " PG_head_tail_mask: %lx\n", vt->PG_head_tail_mask); ++ fprintf(fp, " nr_bad_slab_caches: %d\n", vt->nr_bad_slab_caches); ++ if (!vt->nr_bad_slab_caches) ++ fprintf(fp, " bad_slab_caches: (unused)\n"); ++ else { ++ for (i = 0; i < vt->nr_bad_slab_caches; i++) { ++ fprintf(fp, " bad_slab_caches[%d]: %lx\n", ++ i, vt->bad_slab_caches[i]); ++ } ++ } + fprintf(fp, " paddr_prlen: %d\n", vt->paddr_prlen); + fprintf(fp, " numnodes: %d\n", vt->numnodes); + fprintf(fp, " nr_zones: %d\n", vt->nr_zones); +@@ -11824,6 +12100,21 @@ dump_vm_table(int verbose) + for (i = 0; i < vt->nr_vm_event_items; i++) + fprintf(fp, " [%d] %s\n", i, vt->vm_event_items[i]); + ++ fprintf(fp, " PG_reserved: %lx\n", vt->PG_reserved); ++ fprintf(fp, " PG_slab: %ld (%lx)\n", vt->PG_slab, ++ (ulong)1 << vt->PG_slab); ++ fprintf(fp, " PG_head_tail_mask: %lx\n", vt->PG_head_tail_mask); ++ ++ fprintf(fp, " nr_pageflags: %d\n", vt->nr_pageflags); ++ fprintf(fp, " pageflags_data: %s\n", ++ vt->nr_pageflags ? "" : "(not used)"); ++ for (i = 0; i < vt->nr_pageflags; i++) { ++ fprintf(fp, " %s[%d] %08lx: %s\n", ++ i < 10 ? " " : "", i, ++ vt->pageflags_data[i].mask, ++ vt->pageflags_data[i].name); ++ } ++ + dump_vma_cache(VERBOSE); + } + +--- crash-7.0.2/filesys.c 2013-10-25 15:28:55.920879569 -0400 ++++ crash-7.0.3/filesys.c 2013-10-25 10:09:39.568757187 -0400 +@@ -727,8 +727,10 @@ get_proc_version(void) + return FALSE; + + if (fread(&kt->proc_version, sizeof(char), +- BUFSIZE-1, version) <= 0) ++ BUFSIZE-1, version) <= 0) { ++ fclose(version); + return FALSE; ++ } + + fclose(version); + +--- crash-7.0.2/help.c 2013-10-25 15:28:55.954879567 -0400 ++++ crash-7.0.3/help.c 2013-10-24 15:32:58.495826737 -0400 +@@ -1083,10 +1083,16 @@ NULL + char *help_p[] = { + "p", + "print the value of an expression", +-"[-x|-d][-u] expression", ++"[-x|-d][-u] [expression | symbol[:cpuspec]]", + " This command passes its arguments on to gdb \"print\" command for evaluation.", + "", +-" expression The expression to be evaluated.", ++" expression an expression to be evaluated.", ++" symbol a kernel symbol.", ++" :cpuspec CPU specification for a per-cpu symbol:", ++" : CPU of the currently selected task.", ++" :a[ll] all CPUs.", ++" :#[-#][,...] CPU list(s), e.g. \"1,3,5\", \"1-3\",", ++" or \"1,3,5-7,10\".", + " -x override default output format with hexadecimal format.", + " -d override default output format with decimal format.", + " -u the expression evaluates to a user address reference.", +@@ -1144,6 +1150,39 @@ char *help_p[] = { + " swap_address = 0x0, ", + " segments = 0x0", + " }", ++"", ++" If a per-cpu symbol is entered as a argument, its data type", ++" and all of its per-cpu addresses are displayed:", ++" ", ++" %s> p irq_stat", ++" PER-CPU DATA TYPE:", ++" irq_cpustat_t irq_stat;", ++" PER-CPU ADDRESSES:", ++" [0]: ffff88021e211540", ++" [1]: ffff88021e251540", ++" [2]: ffff88021e291540", ++" [3]: ffff88021e2d1540", ++" ", ++" To display the contents a per-cpu symbol for CPU 1, append", ++" a cpu-specifier:", ++" ", ++" %s> p irq_stat:1", ++" per_cpu(irq_stat, 1) = $29 = {", ++" __softirq_pending = 0, ", ++" __nmi_count = 209034, ", ++" apic_timer_irqs = 597509876, ", ++" irq_spurious_count = 0, ", ++" icr_read_retry_count = 2, ", ++" x86_platform_ipis = 0, ", ++" apic_perf_irqs = 209034, ", ++" apic_irq_work_irqs = 0, ", ++" irq_resched_count = 264922233, ", ++" irq_call_count = 7036692, ", ++" irq_tlb_count = 4750442, ", ++" irq_thermal_count = 0, ", ++" irq_threshold_count = 0", ++" }", ++" ", + NULL + }; + +@@ -2841,7 +2880,7 @@ char *help_irq[] = { + " irq stats of all cpus will be displayed.", + " -c cpu only usable with the -s option, dump the irq stats of the ", + " specified cpu[s]; cpu can be specified as \"1,3,5\", \"1-3\",", +-" or \"1,3,5-7,10\".", ++" \"1,3,5-7,10\", \"all\", or \"a\" (shortcut for \"all\").", + "\nEXAMPLES", + " Display the relevant data for IRQ 18 from a pre-2.6.37 kernel:\n", + " %s> irq 18", +@@ -4092,8 +4131,8 @@ NULL + char *help_struct[] = { + "struct", + "structure contents", +-"struct_name[.member[,member]][-o][-l offset][-rfuxdp][address | symbol]\n" +-" [count | -c count]", ++"struct_name[.member[,member]][-o][-l offset][-rfuxdp]\n" ++" [address | symbol][:cpuspec] [count | -c count]", + " This command displays either a structure definition, or a formatted display", + " of the contents of a structure at a specified address. When no address is", + " specified, the structure definition is shown along with the structure size.", +@@ -4127,6 +4166,11 @@ char *help_struct[] = { + " to an embedded list_head structure contained within the", + " target data structure, then the \"-l\" option must be used.", + " symbol symbolic reference to the address of a structure.", ++" :cpuspec CPU specification for a per-cpu address or symbol:", ++" : CPU of the currently selected task.", ++" :a[ll] all CPUs.", ++" :#[-#][,...] CPU list(s), e.g. \"1,3,5\", \"1-3\",", ++" or \"1,3,5-7,10\".", + " count count of structures to dump from an array of structures;", + " if used, this must be the last argument entered.", + " -c count \"-c\" is only required if \"count\" is not the last argument", +@@ -4363,6 +4407,59 @@ char *help_struct[] = { + " [ffff8100145d20b8] struct list_head run_list;", + " [ffff8100145d20c8] struct prio_array *array;", + " ...", ++" ", ++" For an example of displaying per-cpu variables, consider the", ++" struct hd_struct.dkstats member, which is a percpu pointer to", ++" a disk_stats structure:", ++"", ++" %s> struct hd_struct.dkstats ", ++" struct hd_struct {", ++" [1232] struct disk_stats *dkstats;", ++" }", ++"", ++" Taking an hd_struct at address ffff8802450e2848, display all", ++" of the per-cpu disk_stats structures that it references:", ++" ", ++" %s> struct hd_struct.dkstats ffff8802450e2848", ++" dkstats = 0x60fdb48026c8", ++" %s> struct disk_stats 0x60fdb48026c8:a", ++" [0]: ffffe8fefe6026c8", ++" struct disk_stats {", ++" sectors = {451376, 80468}, ", ++" ios = {6041, 971}, ", ++" merges = {386, 390}, ", ++" ticks = {194877, 56131}, ", ++" io_ticks = 12371, ", ++" time_in_queue = 309163", ++" }", ++" [1]: ffffe8fefe8026c8", ++" struct disk_stats {", ++" sectors = {0, 0}, ", ++" ios = {0, 0}, ", ++" merges = {7, 242}, ", ++" ticks = {0, 0}, ", ++" io_ticks = 23, ", ++" time_in_queue = 581", ++" }", ++" [2]: ffffe8fefea026c8", ++" struct disk_stats {", ++" sectors = {0, 0}, ", ++" ios = {0, 0}, ", ++" merges = {4, 112}, ", ++" ticks = {0, 0}, ", ++" io_ticks = 11, ", ++" time_in_queue = 305", ++" }", ++" [3]: ffffe8fefec026c8", ++" struct disk_stats {", ++" sectors = {0, 0}, ", ++" ios = {0, 0}, ", ++" merges = {5, 54}, ", ++" ticks = {0, 0}, ", ++" io_ticks = 17, ", ++" time_in_queue = 41", ++" }", ++" ", + "\nNOTE", + " If the structure name does not conflict with any %s command name, the", + " \"struct\" command may be dropped. Accordingly, the examples above could", +@@ -4382,8 +4479,8 @@ NULL + char *help_union[] = { + "union", + "union contents", +-"union_name[.member[,member]] [-o][-l offset][-rfuxdp] [address | symbol]\n" +-" [count | -c count]", ++"union_name[.member[,member]] [-o][-l offset][-rfuxdp]\n" ++" [address | symbol][:cpuspec] [count | -c count]", + " This command displays either a union definition, or a formatted display", + " of the contents of a union at a specified address. When no address is", + " specified, the union definition is shown along with the union size.", +@@ -4418,6 +4515,11 @@ char *help_union[] = { + " to an embedded list_head structure contained within the", + " target union structure, then the \"-l\" option must be used.", + " symbol symbolic reference to the address of a union.", ++" :cpuspec CPU specification for a per-cpu address or symbol:", ++" : CPU of the currently selected task.", ++" :a[ll] all CPUs.", ++" :#[-#][,...] CPU list(s), e.g. \"1,3,5\", \"1-3\",", ++" or \"1,3,5-7,10\".", + " count count of unions to dump from an array of unions; if used,", + " this must be the last argument entered.", + " -c count \"-c\" is only required if \"count\" is not the last argument", +@@ -5433,30 +5535,26 @@ char *help_kmem[] = { + " ", + " Dump the mem_map[] array:\n", + " %s> kmem -p", +-" PAGE PHYSICAL MAPPING INDEX CNT FLAGS", +-" ffffea0000000000 0 0 0 0 0", +-" ffffea0000000038 1000 0 0 1 400", +-" ffffea0000000070 2000 0 0 1 400", +-" ffffea00000000a8 3000 0 0 1 400", +-" ffffea00000000e0 4000 0 0 1 400", +-" ffffea0000000118 5000 0 0 1 400", +-" ffffea0000000150 6000 0 0 1 400", +-" ffffea0000000188 7000 0 0 1 80", +-" ffffea00000001c0 8000 0 0 1 400", +-" ffffea00000001f8 9000 0 0 1 80", +-" ffffea0000000230 a000 0 0 1 80", +-" ffffea0000000268 b000 ffff880012d9bd68 695b 1 2002c", +-" ffffea00000002a0 c000 0 0 1 80", +-" ffffea00000002d8 d000 ffff88002a9ee210 9 1 2002c", +-" ffffea0000000310 e000 ffff880010b265d8 33c 1 2002c", +-" ffffea0000000348 f000 ffff88001404dd68 2d1 2 868", +-" ffffea0000000380 10000 ffff88001404dd68 2d6 2 868", +-" ffffea00000003b8 11000 ffff88001404dd68 2d7 2 868", +-" ffffea00000003f0 12000 ffff88001404dd68 2d8 2 868", +-" ffffea0000000428 13000 ffff88001404dd68 2d9 2 868", +-" ffffea0000000460 14000 ffff88001404dd68 2da 2 868", +-" ffffea0000000498 15000 ffff88001404dd68 2db 2 868", +-" ffffea00000004d0 16000 ffff88001404dd68 2dc 2 868", ++" PAGE PHYSICAL MAPPING INDEX CNT FLAGS", ++" f5c51200 10000 0 0 1 80 slab", ++" f5c51220 11000 0 0 1 80 slab", ++" f5c51240 12000 0 0 1 80 slab", ++" f5c51260 13000 0 0 1 80 slab", ++" f5c51280 14000 0 0 1 80 slab", ++" f5c512a0 15000 0 0 1 80 slab", ++" f5c512c0 16000 0 0 1 80 slab", ++" f5c512e0 17000 0 0 1 80 slab", ++" f5c51300 18000 0 0 1 80 slab", ++" f5c51320 19000 0 0 1 80 slab", ++" f5c51340 1a000 0 0 1 80 slab", ++" f5c51360 1b000 0 0 1 80 slab", ++" f5c51380 1c000 e6c6a754 13b67 2 868 uptodate,lru,active,private", ++" f5c513a0 1d000 0 0 1 80 slab", ++" f5c513c0 1e000 0 0 1 80 slab", ++" f5c513e0 1f000 0 0 1 80 slab", ++" f5c51400 20000 e6c6a754 13bbb 2 868 uptodate,lru,active,private", ++" f5c51420 21000 0 0 1 80 slab", ++" f5c51440 22000 0 0 1 80 slab", + " ...", + " ", + " Use the commands above with a page pointer or a physical address argument:\n", +@@ -5469,12 +5567,14 @@ char *help_kmem[] = { + " 2 16k c02eb01c ", + " c40425b0 (c40425b0 is 1st of 4 pages) ", + " ", +-" %s> kmem -p c035de00", +-" PAGE PHYSICAL INODE OFFSET CNT FLAGS", +-" c035de00 50c0000 0 129000 0 uptodate\n", +-" %s> kmem -p 50c0000", +-" PAGE PHYSICAL INODE OFFSET CNT FLAGS", +-" c035de00 50c0000 0 129000 0 uptodate\n", ++" %s> kmem -p c25a9c00", ++" PAGE PHYSICAL MAPPING INDEX CNT FLAGS", ++" c25a9c00 1fe0000 f429d2e4 21fe3eb 2 800828 uptodate,lru,private", ++" ", ++" %s> kmem -p 1fe0000", ++" PAGE PHYSICAL MAPPING INDEX CNT FLAGS", ++" c25a9c00 1fe0000 f429d2e4 21fe3eb 2 800828 uptodate,lru,private", ++" ", + " Display the mapped memory regions allocated by vmalloc():\n", + " %s> kmem -v", + " VMAP_AREA VM_STRUCT ADDRESS RANGE SIZE", +--- crash-7.0.2/task.c 2013-10-25 15:28:55.949879567 -0400 ++++ crash-7.0.3/task.c 2013-10-17 14:42:50.532672513 -0400 +@@ -474,7 +474,7 @@ task_init(void) + tt->this_task = pid_to_task(active_pid); + } + else { +- if (KDUMP_DUMPFILE()) ++ if (KDUMP_DUMPFILE() && !(pc->flags2 & QEMU_MEM_DUMP)) + map_cpus_to_prstatus(); + else if (ELF_NOTES_VALID() && DISKDUMP_DUMPFILE()) + map_cpus_to_prstatus_kdump_cmprs(); +@@ -4873,10 +4873,10 @@ task_mm(ulong task, int fill) + char * + task_cpu(int processor, char *buf, int verbose) + { +- if (processor < NO_PROC_ID) ++ if (processor < NR_CPUS) + sprintf(buf, "%d", processor); +- if (processor == NO_PROC_ID) +- sprintf(buf, verbose ? "NO_PROC_ID" : "-"); ++ else ++ sprintf(buf, verbose ? "(unknown)" : "?"); + + return buf; + } +--- crash-7.0.2/kernel.c 2013-10-25 15:28:55.958879567 -0400 ++++ crash-7.0.3/kernel.c 2013-10-25 10:13:04.143747815 -0400 +@@ -5377,7 +5377,6 @@ cmd_irq(void) + int i, c; + int nr_irqs; + ulong *cpus; +- int len; + int show_intr, choose_cpu; + char buf[10]; + char arg_buf[BUFSIZE]; +@@ -5485,9 +5484,7 @@ cmd_irq(void) + error(FATAL, "cannot determine number of IRQs\n"); + + if (show_intr) { +- if ((len = STRUCT_SIZE("cpumask_t")) < 0) +- len = DIV_ROUND_UP(kt->cpus, BITS_PER_LONG) * sizeof(ulong); +- cpus = (ulong *)GETBUF(len); ++ cpus = get_cpumask_buf(); + + if (choose_cpu) { + make_cpumask(arg_buf, cpus, FAULT_ON_ERROR, NULL); +@@ -5648,6 +5645,7 @@ generic_dump_irq(int irq) + ulong tmp1, tmp2; + + handler = UNINITIALIZED; ++ action = 0; + + irq_desc_addr = get_irq_desc_addr(irq); + if (!irq_desc_addr && symbol_exists("irq_desc_ptrs")) { +@@ -8398,6 +8396,7 @@ static void add_ikconfig_entry(char *lin + static int setup_ikconfig(char *config) + { + char *ent, *tokptr; ++ struct ikconfig_list *new; + + ikconfig_all = calloc(1, sizeof(struct ikconfig_list) * IKCONFIG_MAX); + if (!ikconfig_all) { +@@ -8424,8 +8423,9 @@ static int setup_ikconfig(char *config) + free(ikconfig_all); + return 0; + } +- ikconfig_all = realloc(ikconfig_all, +- sizeof(struct ikconfig_list) * kt->ikconfig_ents); ++ if ((new = realloc(ikconfig_all, ++ sizeof(struct ikconfig_list) * kt->ikconfig_ents))) ++ ikconfig_all = new; + + return 1; + } +--- crash-7.0.2/gdb_interface.c 2013-10-25 15:28:55.936879568 -0400 ++++ crash-7.0.3/gdb_interface.c 2013-10-15 15:55:20.440389792 -0400 +@@ -357,8 +357,8 @@ gdb_interface(struct gnu_request *req) + restart(0); + + if (!req->fp) { +- req->fp = pc->flags & RUNTIME ? fp : +- CRASHDEBUG(1) ? fp : pc->nullfp; ++ req->fp = ((pc->flags & RUNTIME) || (pc->flags2 & ALLOW_FP)) ? ++ fp : CRASHDEBUG(1) ? fp : pc->nullfp; + } + + pc->cur_req = req; +--- crash-7.0.2/configure.c 2013-10-25 15:28:55.956879567 -0400 ++++ crash-7.0.3/configure.c 2013-10-25 10:09:47.567756821 -0400 +@@ -790,7 +790,7 @@ make_rh_rpm_package(char *package, int r + break; + } + } +- fclose(fp); ++ pclose(fp); + + if (!cur) { + fprintf(stderr, "cannot get version from \"crash -v\"\n"); +--- crash-7.0.2/net.c 2013-10-25 15:28:55.923879569 -0400 ++++ crash-7.0.3/net.c 2013-10-22 09:42:52.103705675 -0400 +@@ -1,8 +1,8 @@ + /* net.c - core analysis suite + * + * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc. +- * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 David Anderson +- * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Red Hat, Inc. All rights reserved. ++ * Copyright (C) 2002-2013 David Anderson ++ * Copyright (C) 2002-2013 Red Hat, Inc. All rights reserved. + * + * 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 +@@ -231,10 +231,22 @@ net_init(void) + } else if ((MEMBER_OFFSET("inet_sock", "sk") == 0) && + (MEMBER_OFFSET("sock", "__sk_common") == 0)) { + MEMBER_OFFSET_INIT(inet_opt_daddr, "sock_common", "skc_daddr"); ++ if (INVALID_MEMBER(inet_opt_daddr)) ++ ANON_MEMBER_OFFSET_INIT(inet_opt_daddr, "sock_common", ++ "skc_daddr"); + MEMBER_OFFSET_INIT(inet_opt_rcv_saddr, "sock_common", "skc_rcv_saddr"); ++ if (INVALID_MEMBER(inet_opt_rcv_saddr)) ++ ANON_MEMBER_OFFSET_INIT(inet_opt_rcv_saddr, "sock_common", ++ "skc_rcv_saddr"); + MEMBER_OFFSET_INIT(inet_opt_dport, "inet_sock", "inet_dport"); ++ if (INVALID_MEMBER(inet_opt_dport)) ++ ANON_MEMBER_OFFSET_INIT(inet_opt_dport, "sock_common", ++ "skc_dport"); + MEMBER_OFFSET_INIT(inet_opt_sport, "inet_sock", "inet_sport"); + MEMBER_OFFSET_INIT(inet_opt_num, "inet_sock", "inet_num"); ++ if (INVALID_MEMBER(inet_opt_num)) ++ ANON_MEMBER_OFFSET_INIT(inet_opt_num, "sock_common", ++ "skc_num"); + } + } + +--- crash-7.0.2/s390x.c 2013-10-25 15:28:55.928879568 -0400 ++++ crash-7.0.3/s390x.c 2013-10-10 14:57:54.080339089 -0400 +@@ -590,9 +590,12 @@ static int swap_entry(ulong entry) + if (THIS_KERNEL_VERSION < LINUX(2,6,19)) { + if ((entry & 0x601ULL) == 0x600ULL) + return 1; +- } else { ++ } if (THIS_KERNEL_VERSION < LINUX(3,12,0)) { + if ((entry & 0x403ULL) == 0x403ULL) + return 1; ++ } else { ++ if ((entry & 0x603ULL) == 0x402ULL) ++ return 1; + } + return 0; + } +--- crash-7.0.2/x86_64.c 2013-10-25 15:28:55.928879568 -0400 ++++ crash-7.0.3/x86_64.c 2013-10-17 09:25:14.265545546 -0400 +@@ -7251,6 +7251,9 @@ x86_64_get_framesize(struct bt_info *bt, + } + } + ++ if ((sp->value >= kt->init_begin) && (sp->value < kt->init_end)) ++ return 0; ++ + framesize = max = 0; + max_instructions = textaddr - sp->value; + instr = arg = -1; +--- crash-7.0.2/remote.c 2013-10-25 15:28:55.935879568 -0400 ++++ crash-7.0.3/remote.c 2013-10-25 10:09:51.680756632 -0400 +@@ -1116,8 +1116,10 @@ daemon_proc_version(char *buf) + return FALSE; + + if (fread(buf, sizeof(char), +- BUFSIZE-1, pipe) <= 0) ++ BUFSIZE-1, pipe) <= 0) { ++ pclose(pipe); + return FALSE; ++ } + + pclose(pipe); + +--- crash-7.0.2/va_server.c 2013-10-25 15:28:55.939879568 -0400 ++++ crash-7.0.3/va_server.c 2013-10-25 10:09:58.528756319 -0400 +@@ -313,6 +313,7 @@ int read_map(char *crash_file) + ret = fseek(vas_file_p, (long)0, SEEK_SET); + if(ret == -1) { + printf("va_server: unable to fseek, err = %d\n", ferror(vas_file_p)); ++ free(disk_hdr); + return -1; + } + items = fread((void *)disk_hdr, 1, Page_Size, vas_file_p); +--- crash-7.0.2/va_server_v1.c 2013-10-25 15:28:55.935879568 -0400 ++++ crash-7.0.3/va_server_v1.c 2013-10-25 10:10:02.032756158 -0400 +@@ -308,6 +308,7 @@ int read_map_v1(int blk_pos) + ret = fseek(vas_file_p, (long)(blk_pos*Page_Size), SEEK_SET); + if(ret == -1) { + console("va_server: unable to fseek, err = %d\n", ferror(vas_file_p)); ++ free(disk_hdr); + return -1; + } + items = fread((void *)disk_hdr, 1, Page_Size, vas_file_p); +--- crash-7.0.2/symbols.c 2013-10-25 15:28:55.956879567 -0400 ++++ crash-7.0.3/symbols.c 2013-10-24 15:33:12.359826102 -0400 +@@ -72,7 +72,10 @@ struct elf_common; + static void Elf32_Sym_to_common(Elf32_Sym *, struct elf_common *); + static void Elf64_Sym_to_common(Elf64_Sym *, struct elf_common *); + static void cmd_datatype_common(ulong); +-static int display_per_cpu_info(struct syment *); ++static void do_datatype_addr(struct datatype_member *, ulong, int, ++ ulong, char **, int); ++static void process_gdb_output(char *, unsigned, const char *, int); ++static int display_per_cpu_info(struct syment *, int, char *); + static struct load_module *get_module_percpu_sym_owner(struct syment *); + static int is_percpu_symbol(struct syment *); + static void dump_percpu_symbols(struct load_module *); +@@ -116,6 +119,8 @@ static int show_member_offset(FILE *, st + #define IN_STRUCT (0x40000) + #define DATATYPE_QUERY (0x80000) + #define ANON_MEMBER_QUERY (0x100000) ++#define SHOW_RAW_DATA (0x200000) ++#define DEREF_POINTERS (0x400000) + + #define INTEGER_TYPE (UINT8|INT8|UINT16|INT16|UINT32|INT32|UINT64|INT64) + +@@ -132,6 +137,7 @@ static void dump_datatype_flags(ulong, F + static long anon_member_offset(char *, char *); + static int gdb_whatis(char *); + static void do_datatype_declaration(struct datatype_member *, ulong); ++static int member_to_datatype(char *, struct datatype_member *, ulong); + + #define DEBUGINFO_ERROR_MESSAGE1 \ + "the use of a System.map file requires that the accompanying namelist\nargument is a kernel file built with the -g CFLAG. The namelist argument\nsupplied in this case is a debuginfo file, which must be accompanied by the\nkernel file from which it was derived.\n" +@@ -5704,13 +5710,13 @@ dereference_pointer(ulong addr, struct d + static void + cmd_datatype_common(ulong flags) + { +- int i, c; ++ int c; + ulong addr, aflag; ++ char *cpuspec; ++ ulong *cpus; + struct syment *sp; +- int rawdata; +- long len; + ulong list_head_offset; +- int count, pflag; ++ int count; + int argc_members; + int optind_save; + unsigned int radix, restore_radix; +@@ -5721,19 +5727,19 @@ cmd_datatype_common(ulong flags) + + dm = &datatype_member; + count = 0xdeadbeef; +- rawdata = 0; + aflag = addr = 0; + list_head_offset = 0; + argc_members = 0; + radix = restore_radix = 0; + separator = members = NULL; +- pflag = 0; ++ cpuspec = NULL; ++ cpus = NULL; + + while ((c = getopt(argcnt, args, "pxdhfuc:rvol:")) != EOF) { + switch (c) + { + case 'p': +- pflag++; ++ flags |= DEREF_POINTERS; + break; + + case 'd': +@@ -5756,7 +5762,7 @@ cmd_datatype_common(ulong flags) + break; + + case 'r': +- rawdata = 1; ++ flags |= SHOW_RAW_DATA; + break; + + case 'v': +@@ -5816,11 +5822,22 @@ cmd_datatype_common(ulong flags) + if (aflag && (count != 0xdeadbeef)) + error(FATAL, "too many arguments!\n"); + ++ if (!aflag) { ++ cpuspec = strchr(args[optind], ':'); ++ if (cpuspec) ++ *cpuspec++ = NULLCHAR; ++ } ++ + if (clean_arg() && IS_A_NUMBER(args[optind])) { + if (aflag) + count = stol(args[optind], + FAULT_ON_ERROR, NULL); +- else { ++ else if (cpuspec) { ++ if (pc->curcmd_flags & MEMTYPE_FILEADDR) ++ error(FATAL, "-f option cannot be used with percpu\n"); ++ addr = htol(args[optind], FAULT_ON_ERROR, NULL); ++ aflag++; ++ } else { + if (pc->curcmd_flags & MEMTYPE_FILEADDR) + pc->curcmd_private = stoll(args[optind], + FAULT_ON_ERROR, NULL); +@@ -5835,6 +5852,12 @@ cmd_datatype_common(ulong flags) + aflag++; + } + } else if ((sp = symbol_search(args[optind]))) { ++ if (cpuspec && !is_percpu_symbol(sp)) { ++ error(WARNING, ++ "%s is not percpu; cpuspec ignored.\n", ++ sp->name); ++ cpuspec = NULL; ++ } + addr = sp->value; + aflag++; + } else { +@@ -5846,6 +5869,14 @@ cmd_datatype_common(ulong flags) + } + } + ++ if (cpuspec) { ++ cpus = get_cpumask_buf(); ++ if (STREQ(cpuspec, "")) ++ SET_BIT(cpus, CURRENT_CONTEXT()->processor); ++ else ++ make_cpumask(cpuspec, cpus, FAULT_ON_ERROR, NULL); ++ } ++ + optind = optind_save; + + if (count == 0xdeadbeef) +@@ -5853,7 +5884,7 @@ cmd_datatype_common(ulong flags) + else if (!aflag) + error(FATAL, "no kernel virtual address argument entered\n"); + +- if (pflag && !aflag) ++ if ((flags & DEREF_POINTERS) && !aflag) + error(FATAL, "-p option requires address argument\n"); + + if (list_head_offset) +@@ -5878,6 +5909,15 @@ cmd_datatype_common(ulong flags) + DATATYPE_QUERY|ANON_MEMBER_QUERY|RETURN_ON_ERROR) < 1)) + error(FATAL, "invalid data structure reference: %s\n", structname); + ++ if (! (flags & (STRUCT_REQUEST|UNION_REQUEST)) ) { ++ flags |= dm->type; ++ if (!(flags & (UNION_REQUEST|STRUCT_REQUEST))) ++ error(FATAL, "invalid argument"); ++ } else if ( (flags &(STRUCT_REQUEST|UNION_REQUEST)) != dm->type) { ++ error(FATAL, "data type mismatch: %s is not a %s\n", ++ dm->name, flags & UNION_REQUEST ? "union" : "struct"); ++ } ++ + if ((argc_members > 1) && !aflag) { + error(INFO, flags & SHOW_OFFSET ? + "-o option not valid with multiple member format\n" : +@@ -5891,7 +5931,52 @@ cmd_datatype_common(ulong flags) + error(FATAL, + "-o option not valid with multiple member format\n"); + +- len = dm->size; ++ set_temporary_radix(radix, &restore_radix); ++ ++ /* ++ * No address was passed -- dump the structure/member declaration. ++ */ ++ if (!aflag) { ++ if (argc_members && ++ !member_to_datatype(memberlist[0], dm, ++ ANON_MEMBER_QUERY)) ++ error(FATAL, "invalid data structure reference: %s.%s\n", ++ dm->name, memberlist[0]); ++ do_datatype_declaration(dm, flags | (dm->flags & TYPEDEF)); ++ } else if (cpus) { ++ for (c = 0; c < kt->cpus; c++) { ++ ulong cpuaddr; ++ ++ if (!NUM_IN_BITMAP(cpus, c)) ++ continue; ++ ++ cpuaddr = addr + kt->__per_cpu_offset[c]; ++ fprintf(fp, "[%d]: %lx\n", c, cpuaddr); ++ do_datatype_addr(dm, cpuaddr , count, ++ flags, memberlist, argc_members); ++ } ++ } else ++ do_datatype_addr(dm, addr, count, flags, ++ memberlist, argc_members); ++ ++ restore_current_radix(restore_radix); ++ ++freebuf: ++ if (argc_members) { ++ FREEBUF(structname); ++ FREEBUF(members); ++ } ++ ++ if (cpus) ++ FREEBUF(cpus); ++} ++ ++static void ++do_datatype_addr(struct datatype_member *dm, ulong addr, int count, ++ ulong flags, char **memberlist, int argc_members) ++{ ++ int i, c; ++ long len = dm->size; + + if (count < 0) { + addr -= len * abs(count); +@@ -5908,83 +5993,44 @@ cmd_datatype_common(ulong flags) + i = 0; + do { + if (argc_members) { +- *separator = '.'; +- strcpy(separator+1, memberlist[i]); +- } +- +- switch (arg_to_datatype(structname, dm, +- ANON_MEMBER_QUERY|RETURN_ON_ERROR)) +- { +- case 0: error(FATAL, "invalid data structure reference: %s\n", +- structname); +- break; +- case 1: break; +- case 2: if (rawdata) ++ if (!member_to_datatype(memberlist[i], dm, ++ ANON_MEMBER_QUERY)) ++ error(FATAL, "invalid data structure reference: %s.%s\n", ++ dm->name, memberlist[i]); ++ if (flags & SHOW_RAW_DATA) + error(FATAL, +- "member-specific output not allowed with -r\n"); +- break; ++ "member-specific output not allowed with -r\n"); + } + +- if (!(dm->flags & TYPEDEF)) { +- if (flags &(STRUCT_REQUEST|UNION_REQUEST) ) { +- if ((flags & (STRUCT_REQUEST|UNION_REQUEST)) != dm->type) +- goto freebuf; +- } else +- flags |= dm->type; +- } +- +- /* +- * No address was passed -- dump the structure/member declaration. +- */ +- if (!aflag || (aflag && (flags & SHOW_OFFSET))) { +- if (aflag) +- dm->vaddr = addr; +- set_temporary_radix(radix, &restore_radix); +- do_datatype_declaration(dm, flags | (dm->flags & TYPEDEF)); +- restore_current_radix(restore_radix); +- goto freebuf; +- } +- +- if (!(flags & (UNION_REQUEST|STRUCT_REQUEST))) +- error(FATAL, "invalid argument"); +- + /* +- * Display data. ++ * Display member addresses or data + */ +- if (rawdata) ++ if (flags & SHOW_OFFSET) { ++ dm->vaddr = addr; ++ do_datatype_declaration(dm, flags | (dm->flags & TYPEDEF)); ++ } else if (flags & SHOW_RAW_DATA) + raw_data_dump(addr, len, flags & STRUCT_VERBOSE); +- else if (pflag && !dm->member) { +- set_temporary_radix(radix, &restore_radix); ++ else if ((flags & DEREF_POINTERS) && !dm->member) { + print_struct_with_dereference(addr, dm, flags); +- restore_current_radix(restore_radix); + } else { + if (dm->member) + open_tmpfile(); + +- set_temporary_radix(radix, &restore_radix); +- + if (flags & UNION_REQUEST) + print_union(dm->name, addr); + else if (flags & STRUCT_REQUEST) + print_struct(dm->name, addr); + + if (dm->member) { +- if (!(pflag && ++ if (!((flags & DEREF_POINTERS) && + dereference_pointer(addr, dm, flags))) + parse_for_member(dm, PARSE_FOR_DATA); + close_tmpfile(); + } + +- restore_current_radix(restore_radix); + } + } while (++i < argc_members); + } +- +-freebuf: +- if (argc_members) { +- FREEBUF(structname); +- FREEBUF(members); +- } + } + + +@@ -6108,13 +6154,7 @@ arg_to_datatype(char *s, struct datatype + if (!both) + return 1; + +- dm->member = p1+1; +- +- if ((dm->member_offset = MEMBER_OFFSET(dm->name, dm->member)) >= 0) +- return 2; +- +- if ((flags & ANON_MEMBER_QUERY) && +- ((dm->member_offset = ANON_MEMBER_OFFSET(dm->name, dm->member)) >= 0)) ++ if (member_to_datatype(p1 + 1, dm, flags)) + return 2; + + datatype_member_fatal: +@@ -6137,6 +6177,21 @@ datatype_member_fatal: + return (error(FATAL, "invalid argument: %s\n", s)); + } + ++static int ++member_to_datatype(char *s, struct datatype_member *dm, ulong flags) ++{ ++ dm->member = s; ++ ++ if ((dm->member_offset = MEMBER_OFFSET(dm->name, s)) >= 0) ++ return TRUE; ++ ++ if ((flags & ANON_MEMBER_QUERY) && ++ ((dm->member_offset = ANON_MEMBER_OFFSET(dm->name, s)) >= 0)) ++ return TRUE; ++ ++ return FALSE; ++} ++ + /* + * debug routine -- not called on purpose by anybody. + */ +@@ -6388,13 +6443,12 @@ cmd_p(void) + { + int c; + struct syment *sp, *percpu_sp; +- unsigned radix, restore_radix; +- int leader, do_load_module_filter, success; ++ unsigned radix; ++ int do_load_module_filter; + char buf1[BUFSIZE]; +- char buf2[BUFSIZE]; +- char *p1; ++ char *cpuspec; + +- leader = do_load_module_filter = radix = restore_radix = 0; ++ do_load_module_filter = radix = 0; + + while ((c = getopt(argcnt, args, "dhxu")) != EOF) { + switch(c) +@@ -6427,33 +6481,57 @@ cmd_p(void) + if (argerrs || !args[optind]) + cmd_usage(pc->curcmd, SYNOPSIS); + ++ cpuspec = strrchr(args[optind], ':'); ++ if (cpuspec) ++ *cpuspec++ = NULLCHAR; ++ ++ sp = NULL; + if ((sp = symbol_search(args[optind])) && !args[optind+1]) { + if ((percpu_sp = per_cpu_symbol_search(args[optind])) && +- display_per_cpu_info(percpu_sp)) ++ display_per_cpu_info(percpu_sp, radix, cpuspec)) + return; +- sprintf(buf2, "%s = ", args[optind]); +- leader = strlen(buf2); + if (module_symbol(sp->value, NULL, NULL, NULL, *gdb_output_radix)) + do_load_module_filter = TRUE; + } else if ((percpu_sp = per_cpu_symbol_search(args[optind])) && +- display_per_cpu_info(percpu_sp)) ++ display_per_cpu_info(percpu_sp, radix, cpuspec)) + return; + else if (st->flags & LOAD_MODULE_SYMS) + do_load_module_filter = TRUE; + ++ if (cpuspec) { ++ if (sp) ++ error(WARNING, "%s is not percpu; cpuspec ignored.\n", ++ sp->name); ++ else ++ /* maybe a valid C expression (e.g. ':') */ ++ *(cpuspec-1) = ':'; ++ } ++ ++ process_gdb_output(concat_args(buf1, 0, TRUE), radix, ++ sp ? sp->name : NULL, do_load_module_filter); ++} ++ ++static void ++process_gdb_output(char *gdb_request, unsigned radix, ++ const char *leader, int do_load_module_filter) ++{ ++ unsigned restore_radix; ++ int success; ++ char buf1[BUFSIZE]; ++ char *p1; ++ + if (leader || do_load_module_filter) + open_tmpfile(); + + set_temporary_radix(radix, &restore_radix); + +- success = gdb_pass_through(concat_args(buf1, 0, TRUE), NULL, +- GNU_RETURN_ON_ERROR); ++ success = gdb_pass_through(gdb_request, NULL, GNU_RETURN_ON_ERROR); + + if (success && (leader || do_load_module_filter)) { + int firstline; + + if (leader) { +- fprintf(pc->saved_fp, "%s", buf2); ++ fprintf(pc->saved_fp, "%s = ", leader); + fflush(pc->saved_fp); + } + +@@ -6482,8 +6560,41 @@ cmd_p(void) + restore_current_radix(restore_radix); + + if (!success) +- error(FATAL, "gdb request failed: %s\n", +- concat_args(buf1, 0, TRUE)); ++ error(FATAL, "gdb request failed: %s\n", gdb_request); ++} ++ ++/* ++ * Get the type of an expression using gdb's "whatis" command. ++ * The returned string is dynamically allocated, and it should ++ * be passed to FREEBUF() when no longer needed. ++ * Return NULL if the type cannot be determined. ++ */ ++static char * ++expr_type_name(const char *expr) ++{ ++ char buf[BUFSIZE], *p; ++ ++ open_tmpfile(); ++ sprintf(buf, "whatis %s", expr); ++ if (!gdb_pass_through(buf, fp, GNU_RETURN_ON_ERROR)) { ++ close_tmpfile(); ++ return NULL; ++ } ++ ++ rewind(pc->tmpfile); ++ while (fgets(buf, BUFSIZE, pc->tmpfile) && !STRNEQ(buf, "type = ")) ++ ; ++ p = feof(pc->tmpfile) ? NULL : buf + strlen("type = "); ++ close_tmpfile(); ++ ++ if (p) { ++ size_t len = strlen(clean_line(p)); ++ /* GDB reports unknown types as <...descriptive text...> */ ++ if (p[0] == '<' && p[len-1] == '>') ++ return NULL; ++ return strcpy(GETBUF(len + 1), p); ++ } ++ return NULL; + } + + /* +@@ -6491,30 +6602,73 @@ cmd_p(void) + * the addresses of each its per-cpu instances. + */ + static int +-display_per_cpu_info(struct syment *sp) ++display_per_cpu_info(struct syment *sp, int radix, char *cpuspec) + { ++ ulong *cpus; + int c; + ulong addr; + char buf[BUFSIZE]; ++ char leader[sizeof("&per_cpu(") + strlen(sp->name) + ++ sizeof(", " STR(UINT_MAX) ")")]; ++ char *typename; ++ int do_load_module_filter; + + if (((kt->flags & (SMP|PER_CPU_OFF)) != (SMP|PER_CPU_OFF)) || + (!is_percpu_symbol(sp)) || + !((sp->type == 'd') || (sp->type == 'D') || (sp->type == 'V'))) + return FALSE; + +- fprintf(fp, "PER-CPU DATA TYPE:\n "); +- sprintf(buf, "whatis %s", sp->name); +- if (!gdb_pass_through(buf, pc->nullfp, GNU_RETURN_ON_ERROR)) +- fprintf(fp, "[undetermined type] %s;\n", sp->name); +- else +- whatis_variable(sp); ++ if (cpuspec) { ++ cpus = get_cpumask_buf(); ++ if (STREQ(cpuspec, "")) ++ SET_BIT(cpus, CURRENT_CONTEXT()->processor); ++ else ++ make_cpumask(cpuspec, cpus, FAULT_ON_ERROR, NULL); ++ } else ++ cpus = NULL; ++ ++ typename = expr_type_name(sp->name); ++ ++ if (!cpus) { ++ fprintf(fp, "PER-CPU DATA TYPE:\n "); ++ if (!typename) ++ fprintf(fp, "[undetermined type] %s;\n", sp->name); ++ else ++ whatis_variable(sp); ++ ++ fprintf(fp, "PER-CPU ADDRESSES:\n"); ++ } ++ ++ do_load_module_filter = ++ module_symbol(sp->value, NULL, NULL, NULL, *gdb_output_radix); + +- fprintf(fp, "PER-CPU ADDRESSES:\n"); + for (c = 0; c < kt->cpus; c++) { ++ if (cpus && !NUM_IN_BITMAP(cpus, c)) ++ continue; + addr = sp->value + kt->__per_cpu_offset[c]; +- fprintf(fp, " [%d]: %lx\n", c, addr); ++ if (!cpus) ++ fprintf(fp, " [%d]: %lx\n", c, addr); ++ else if (typename) { ++ snprintf(buf, sizeof buf, "p *(%s*) 0x%lx", ++ typename, addr); ++ sprintf(leader, "per_cpu(%s, %u)", ++ sp->name, c); ++ process_gdb_output(buf, radix, leader, ++ do_load_module_filter); ++ } else { ++ snprintf(buf, sizeof buf, "p (void*) 0x%lx", addr); ++ sprintf(leader, "&per_cpu(%s, %u)", ++ sp->name, c); ++ process_gdb_output(buf, radix, leader, ++ do_load_module_filter); ++ } + } + ++ if (typename) ++ FREEBUF(typename); ++ if (cpus) ++ FREEBUF(cpus); ++ + return TRUE; + } + +@@ -6859,6 +7013,10 @@ dump_datatype_flags(ulong flags, FILE *o + fprintf(ofp, "%sDATATYPE_QUERY", others++ ? "|" : ""); + if (flags & ANON_MEMBER_QUERY) + fprintf(ofp, "%sANON_MEMBER_QUERY", others++ ? "|" : ""); ++ if (flags & SHOW_RAW_DATA) ++ fprintf(ofp, "%sSHOW_RAW_DATA", others++ ? "|" : ""); ++ if (flags & DEREF_POINTERS) ++ fprintf(ofp, "%sDEREF_POINTERS", others++ ? "|" : ""); + fprintf(ofp, ")\n"); + } + +@@ -7890,11 +8048,18 @@ dump_offset_table(char *spec, ulong make + OFFSET(page_objects)); + fprintf(fp, " page_slab: %ld\n", + OFFSET(page_slab)); ++ fprintf(fp, " page_slab_page: %ld\n", ++ OFFSET(page_slab_page)); + fprintf(fp, " page_first_page: %ld\n", + OFFSET(page_first_page)); + fprintf(fp, " page_freelist: %ld\n", + OFFSET(page_freelist)); + ++ fprintf(fp, " trace_print_flags_mask: %ld\n", ++ OFFSET(trace_print_flags_mask)); ++ fprintf(fp, " trace_print_flags_name: %ld\n", ++ OFFSET(trace_print_flags_name)); ++ + fprintf(fp, " swap_info_struct_swap_file: %ld\n", + OFFSET(swap_info_struct_swap_file)); + fprintf(fp, " swap_info_struct_swap_vfsmnt: %ld\n", +@@ -9021,6 +9186,7 @@ dump_offset_table(char *spec, ulong make + fprintf(fp, "\n size_table:\n"); + fprintf(fp, " page: %ld\n", SIZE(page)); + fprintf(fp, " page_flags: %ld\n", SIZE(page_flags)); ++ fprintf(fp, " trace_print_flags: %ld\n", SIZE(trace_print_flags)); + fprintf(fp, " free_area_struct: %ld\n", + SIZE(free_area_struct)); + fprintf(fp, " free_area: %ld\n", +--- crash-7.0.2/diskdump.c 2013-10-25 15:28:55.941879568 -0400 ++++ crash-7.0.3/diskdump.c 2013-10-23 09:12:15.913831516 -0400 +@@ -40,11 +40,13 @@ struct diskdump_data { + struct disk_dump_sub_header *sub_header; + struct kdump_sub_header *sub_header_kdump; + ++ unsigned long long max_mapnr; /* 64bit max_mapnr */ ++ + size_t data_offset; + int block_size; + int block_shift; + char *bitmap; +- int bitmap_len; ++ off_t bitmap_len; + char *dumpable_bitmap; + int byte, bit; + char *compressed_page; /* copy of compressed page data */ +@@ -170,9 +172,9 @@ add_diskdump_data(char* name) + dd->filename = name; + + if (CRASHDEBUG(1)) +- fprintf(fp, "%s: start_pfn=%lu, end_pfn=%lu\n", name, +- dd->sub_header_kdump->start_pfn, +- dd->sub_header_kdump->end_pfn); ++ fprintf(fp, "%s: start_pfn=%llu, end_pfn=%llu\n", name, ++ dd->sub_header_kdump->start_pfn_64, ++ dd->sub_header_kdump->end_pfn_64); + } + + static void +@@ -199,13 +201,13 @@ get_bit(char *map, int byte, int bit) + } + + static inline int +-page_is_ram(unsigned int nr) ++page_is_ram(unsigned long nr) + { + return get_bit(dd->bitmap, nr >> 3, nr & 7); + } + + static inline int +-page_is_dumpable(unsigned int nr) ++page_is_dumpable(unsigned long nr) + { + return dd->dumpable_bitmap[nr>>3] & (1 << (nr & 7)); + } +@@ -214,7 +216,7 @@ static inline int + dump_is_partial(const struct disk_dump_header *header) + { + return header->bitmap_blocks >= +- divideup(divideup(header->max_mapnr, 8), dd->block_size) * 2; ++ divideup(divideup(dd->max_mapnr, 8), dd->block_size) * 2; + } + + static int +@@ -321,6 +323,9 @@ x86_process_elf_notes(void *note_ptr, un + * [40] unsigned long size_note; / header_version 4 and later / + * [44] off_t offset_eraseinfo; / header_version 5 and later / + * [52] unsigned long size_eraseinfo; / header_version 5 and later / ++ * [56] unsigned long long start_pfn_64; / header_version 6 and later / ++ * [64] unsigned long long end_pfn_64; / header_version 6 and later / ++ * [72] unsigned long long max_mapnr_64; / header_version 6 and later / + * }; + * + * But when compiled on an ARM processor, each 64-bit "off_t" would be pushed +@@ -337,7 +342,10 @@ x86_process_elf_notes(void *note_ptr, un + * [40] off_t offset_note; / header_version 4 and later / + * [48] unsigned long size_note; / header_version 4 and later / + * [56] off_t offset_eraseinfo; / header_version 5 and later / +- * [62] unsigned long size_eraseinfo; / header_version 5 and later / ++ * [64] unsigned long size_eraseinfo; / header_version 5 and later / ++ * [72] unsigned long long start_pfn_64; / header_version 6 and later / ++ * [80] unsigned long long end_pfn_64; / header_version 6 and later / ++ * [88] unsigned long long max_mapnr_64; / header_version 6 and later / + * }; + * + */ +@@ -357,6 +365,10 @@ struct kdump_sub_header_ARM_target { + int pad3; + off_t offset_eraseinfo; /* header_version 5 and later */ + unsigned long size_eraseinfo; /* header_version 5 and later */ ++ int pad4; ++ unsigned long long start_pfn_64; /* header_version 6 and later */ ++ unsigned long long end_pfn_64; /* header_version 6 and later */ ++ unsigned long long max_mapnr_64; /* header_version 6 and later */ + }; + + static void +@@ -380,6 +392,15 @@ arm_kdump_header_adjust(int header_versi + kdsh->offset_eraseinfo = kdsh_ARM_target->offset_eraseinfo; + kdsh->size_eraseinfo = kdsh_ARM_target->size_eraseinfo; + } ++ if (header_version >= 6) { ++ kdsh->start_pfn_64 = kdsh_ARM_target->start_pfn_64; ++ kdsh->end_pfn_64 = kdsh_ARM_target->end_pfn_64; ++ kdsh->max_mapnr_64 = kdsh_ARM_target->max_mapnr_64; ++ } else { ++ kdsh->start_pfn_64 = kdsh_ARM_target->start_pfn; ++ kdsh->end_pfn_64 = kdsh_ARM_target->end_pfn; ++ kdsh->max_mapnr_64 = dd->max_mapnr; ++ } + } + #endif /* __i386__ && ARM */ + +@@ -390,7 +411,10 @@ read_dump_header(char *file) + struct disk_dump_sub_header *sub_header = NULL; + struct kdump_sub_header *sub_header_kdump = NULL; + size_t size; +- int bitmap_len; ++ off_t bitmap_len; ++ char *bufptr; ++ size_t len; ++ ssize_t bytes_read; + int block_size = (int)sysconf(_SC_PAGESIZE); + off_t offset; + const off_t failed = (off_t)-1; +@@ -516,6 +540,13 @@ restart: + } + } + dd->sub_header = sub_header; ++ ++ /* the 64bit max_mapnr only exists in sub-header of compressed ++ * kdump file, if it's not a compressed kdump file, we have to ++ * use the old 32bit max_mapnr in dumpfile header. ++ * max_mapnr may be truncated here. ++ */ ++ dd->max_mapnr = header->max_mapnr; + } else if (KDUMP_CMPRS_VALID()) { + if ((sub_header_kdump = malloc(block_size)) == NULL) + error(FATAL, "compressed kdump: cannot malloc sub_header_kdump buffer\n"); +@@ -540,8 +571,20 @@ restart: + #if defined(__i386__) && defined(ARM) + arm_kdump_header_adjust(header->header_version); + #endif ++ /* use 64bit max_mapnr in compressed kdump file sub-header */ ++ if (header->header_version >= 6) ++ dd->max_mapnr = dd->sub_header_kdump->max_mapnr_64; ++ else { ++ dd->sub_header_kdump->start_pfn_64 ++ = dd->sub_header_kdump->start_pfn; ++ dd->sub_header_kdump->end_pfn_64 ++ = dd->sub_header_kdump->end_pfn; ++ } + } + ++ if (header->header_version < 6) ++ dd->max_mapnr = header->max_mapnr; ++ + /* read memory bitmap */ + bitmap_len = block_size * header->bitmap_blocks; + dd->bitmap_len = bitmap_len; +@@ -571,10 +614,18 @@ restart: + DISKDUMP_VALID() ? "diskdump" : "compressed kdump"); + goto err; + } +- if (read(dd->dfd, dd->bitmap, bitmap_len) < bitmap_len) { +- error(INFO, "%s: cannot read memory bitmap\n", +- DISKDUMP_VALID() ? "diskdump" : "compressed kdump"); +- goto err; ++ bufptr = dd->bitmap; ++ len = bitmap_len; ++ while (len) { ++ bytes_read = read(dd->dfd, bufptr, len); ++ if (bytes_read < 0) { ++ error(INFO, "%s: cannot read memory bitmap\n", ++ DISKDUMP_VALID() ? "diskdump" ++ : "compressed kdump"); ++ goto err; ++ } ++ len -= bytes_read; ++ bufptr += bytes_read; + } + } + +@@ -679,13 +730,13 @@ restart: + } + + if (!is_split) { +- max_sect_len = divideup(header->max_mapnr, BITMAP_SECT_LEN); ++ max_sect_len = divideup(dd->max_mapnr, BITMAP_SECT_LEN); + pfn = 0; + dd->filename = file; + } + else { +- ulong start = sub_header_kdump->start_pfn; +- ulong end = sub_header_kdump->end_pfn; ++ unsigned long long start = sub_header_kdump->start_pfn_64; ++ unsigned long long end = sub_header_kdump->end_pfn_64; + max_sect_len = divideup(end - start + 1, BITMAP_SECT_LEN); + pfn = start; + } +@@ -727,8 +778,9 @@ pfn_to_pos(ulong pfn) + ulong p1, p2; + + if (KDUMP_SPLIT()) { +- p1 = pfn - dd->sub_header_kdump->start_pfn; +- p2 = round(p1, BITMAP_SECT_LEN) + dd->sub_header_kdump->start_pfn; ++ p1 = pfn - dd->sub_header_kdump->start_pfn_64; ++ p2 = round(p1, BITMAP_SECT_LEN) ++ + dd->sub_header_kdump->start_pfn_64; + } + else { + p1 = pfn; +@@ -1034,12 +1086,12 @@ read_diskdump(int fd, void *bufptr, int + if (KDUMP_SPLIT()) { + /* Find proper dd */ + int i; +- unsigned long start_pfn; +- unsigned long end_pfn; ++ unsigned long long start_pfn; ++ unsigned long long end_pfn; + + for (i=0; isub_header_kdump->start_pfn; +- end_pfn = dd_list[i]->sub_header_kdump->end_pfn; ++ start_pfn = dd_list[i]->sub_header_kdump->start_pfn_64; ++ end_pfn = dd_list[i]->sub_header_kdump->end_pfn_64; + if ((pfn >= start_pfn) && (pfn <= end_pfn)) { + dd = dd_list[i]; + break; +@@ -1058,14 +1110,14 @@ read_diskdump(int fd, void *bufptr, int + curpaddr = paddr & ~((physaddr_t)(dd->block_size-1)); + page_offset = paddr & ((physaddr_t)(dd->block_size-1)); + +- if ((pfn >= dd->header->max_mapnr) || !page_is_ram(pfn)) { ++ if ((pfn >= dd->max_mapnr) || !page_is_ram(pfn)) { + if (CRASHDEBUG(8)) { + fprintf(fp, "read_diskdump: SEEK_ERROR: " + "paddr/pfn: %llx/%lx ", + (ulonglong)paddr, pfn); +- if (pfn >= dd->header->max_mapnr) +- fprintf(fp, "max_mapnr: %x\n", +- dd->header->max_mapnr); ++ if (pfn >= dd->max_mapnr) ++ fprintf(fp, "max_mapnr: %llx\n", ++ dd->max_mapnr); + else + fprintf(fp, "!page_is_ram\n"); + } +@@ -1507,12 +1559,31 @@ __diskdump_memory_dump(FILE *fp) + fprintf(fp, " tv_usec: %lx\n", dh->timestamp.tv_usec); + fprintf(fp, " status: %x (", dh->status); + others = 0; +- if (dh->status & DUMP_HEADER_COMPLETED) +- fprintf(fp, "%sDUMP_HEADER_COMPLETED", others++ ? "|" : ""); +- if (dh->status & DUMP_HEADER_INCOMPLETED) +- fprintf(fp, "%sDUMP_HEADER_INCOMPLETED", others++ ? "|" : ""); +- if (dh->status & DUMP_HEADER_COMPRESSED) +- fprintf(fp, "%sDUMP_HEADER_COMPRESSED", others++ ? "|" : ""); ++ switch (dd->flags & (DISKDUMP_LOCAL|KDUMP_CMPRS_LOCAL)) ++ { ++ case DISKDUMP_LOCAL: ++ if (dh->status == DUMP_HEADER_COMPLETED) ++ fprintf(fp, "%sDUMP_HEADER_COMPLETED", ++ others++ ? "|" : ""); ++ else if (dh->status == DUMP_HEADER_INCOMPLETED) ++ fprintf(fp, "%sDUMP_HEADER_INCOMPLETED", ++ others++ ? "|" : ""); ++ else if (dh->status == DUMP_HEADER_COMPRESSED) ++ fprintf(fp, "%sDUMP_HEADER_COMPRESSED", ++ others++ ? "|" : ""); ++ break; ++ case KDUMP_CMPRS_LOCAL: ++ if (dh->status & DUMP_DH_COMPRESSED_ZLIB) ++ fprintf(fp, "%sDUMP_DH_COMPRESSED_ZLIB", ++ others++ ? "|" : ""); ++ if (dh->status & DUMP_DH_COMPRESSED_LZO) ++ fprintf(fp, "%sDUMP_DH_COMPRESSED_LZO", ++ others++ ? "|" : ""); ++ if (dh->status & DUMP_DH_COMPRESSED_SNAPPY) ++ fprintf(fp, "%sDUMP_DH_COMPRESSED_SNAPPY", ++ others++ ? "|" : ""); ++ break; ++ } + fprintf(fp, ")\n"); + fprintf(fp, " block_size: %d\n", dh->block_size); + fprintf(fp, " sub_hdr_size: %d\n", dh->sub_hdr_size); +@@ -1662,6 +1733,23 @@ __diskdump_memory_dump(FILE *fp) + dump_eraseinfo(fp); + } + } ++ if (dh->header_version >= 6) { ++ fprintf(fp, " start_pfn_64: "); ++ if (KDUMP_SPLIT()) ++ fprintf(fp, "%lld (0x%llx)\n", ++ kdsh->start_pfn_64, kdsh->start_pfn_64); ++ else ++ fprintf(fp, "(unused)\n"); ++ fprintf(fp, " end_pfn_64: "); ++ if (KDUMP_SPLIT()) ++ fprintf(fp, "%lld (0x%llx)\n", ++ kdsh->end_pfn_64, kdsh->end_pfn_64); ++ else ++ fprintf(fp, "(unused)\n"); ++ ++ fprintf(fp, " max_mapnr_64: %llu (0x%llx)\n", ++ kdsh->max_mapnr_64, kdsh->max_mapnr_64); ++ } + fprintf(fp, "\n"); + } else + fprintf(fp, "(n/a)\n\n"); +@@ -1670,7 +1758,8 @@ __diskdump_memory_dump(FILE *fp) + fprintf(fp, " block_size: %d\n", dd->block_size); + fprintf(fp, " block_shift: %d\n", dd->block_shift); + fprintf(fp, " bitmap: %lx\n", (ulong)dd->bitmap); +- fprintf(fp, " bitmap_len: %d\n", dd->bitmap_len); ++ fprintf(fp, " bitmap_len: %lld\n", (ulonglong)dd->bitmap_len); ++ fprintf(fp, " max_mapnr: %lld (0x%llx)\n", dd->max_mapnr, dd->max_mapnr); + fprintf(fp, " dumpable_bitmap: %lx\n", (ulong)dd->dumpable_bitmap); + fprintf(fp, " byte: %d\n", dd->byte); + fprintf(fp, " bit: %d\n", dd->bit); +--- crash-7.0.2/makedumpfile.c 2013-10-25 15:28:55.951879567 -0400 ++++ crash-7.0.3/makedumpfile.c 2013-10-25 10:10:07.615755902 -0400 +@@ -59,7 +59,7 @@ store_flat_data_array(char *file, struct + unsigned long long num_allocated = 0; + unsigned long long num_stored = 0; + unsigned long long size_allocated; +- struct flat_data *ptr = NULL, *cur; ++ struct flat_data *ptr = NULL, *cur, *new; + struct makedumpfile_data_header fdh; + + fd = open(file, O_RDONLY); +@@ -77,12 +77,13 @@ store_flat_data_array(char *file, struct + num_allocated += 100; + size_allocated = sizeof(struct flat_data) + * num_allocated; +- ptr = realloc(ptr, size_allocated); +- if (ptr == NULL) { ++ new = realloc(ptr, size_allocated); ++ if (new == NULL) { + error(INFO, + "unable to realloc flat_data structures\n"); + break; + } ++ ptr = new; + } + offset_fdh = lseek(fd, 0x0, SEEK_CUR); + +--- crash-7.0.2/unwind_arm.c 2013-10-25 15:28:55.938879568 -0400 ++++ crash-7.0.3/unwind_arm.c 2013-09-06 15:03:40.804904775 -0400 +@@ -325,7 +325,8 @@ init_module_unwind_tables(void) + hq_open(); + cnt = do_list(&ld); + if (cnt == -1) { +- error(WARNING, "UNWIND: failed to gather unwind_table list"); ++ error(WARNING, "UNWIND: failed to gather unwind_table list\n"); ++ hq_close(); + return FALSE; + } + table_list = (ulong *)GETBUF(cnt * sizeof(ulong)); +--- crash-7.0.2/sadump.c 2013-10-25 15:28:55.941879568 -0400 ++++ crash-7.0.3/sadump.c 2013-10-25 10:10:13.104755651 -0400 +@@ -18,6 +18,7 @@ + + #include "defs.h" + #include "sadump.h" ++#include /* htonl, htons */ + #include + + enum { +@@ -118,7 +119,7 @@ read_dump_header(char *file) + { + struct sadump_part_header *sph = NULL; + struct sadump_header *sh = NULL; +- struct sadump_disk_set_header *sdh = NULL; ++ struct sadump_disk_set_header *new, *sdh = NULL; + struct sadump_media_header *smh = NULL; + struct sadump_diskset_data *sd_list_len_0 = NULL; + size_t block_size = SADUMP_DEFAULT_BLOCK_SIZE; +@@ -127,7 +128,8 @@ read_dump_header(char *file) + uint32_t smram_cpu_state_size = 0; + ulong bitmap_len, dumpable_bitmap_len; + char *bitmap = NULL, *dumpable_bitmap = NULL, *page_buf = NULL; +- char guid1[33], guid2[33]; ++ char guid1[SADUMP_EFI_GUID_TEXT_REPR_LEN+1]; ++ char guid2[SADUMP_EFI_GUID_TEXT_REPR_LEN+1]; + + sph = malloc(block_size); + if (!sph) { +@@ -226,12 +228,13 @@ restart: + header_size = header_blocks * block_size; + + if (header_size > block_size) { +- sdh = realloc(sdh, header_size); +- if (!sdh) { ++ new = realloc(sdh, header_size); ++ if (!new) { + error(INFO, "sadump: cannot re-allocate disk " + "set buffer\n"); + goto err; + } ++ sdh = new; + } + + if (!read_device(sdh, header_size, &offset)) { +@@ -468,7 +471,8 @@ add_disk(char *file) + struct sadump_part_header *ph; + struct sadump_diskset_data *this_disk; + int diskid; +- char guid1[33], guid2[33]; ++ char guid1[SADUMP_EFI_GUID_TEXT_REPR_LEN+1]; ++ char guid2[SADUMP_EFI_GUID_TEXT_REPR_LEN+1]; + + diskid = sd->sd_list_len - 1; + this_disk = sd->sd_list[diskid]; +@@ -863,7 +867,7 @@ guid_to_str(efi_guid_t *guid, char *buf, + { + snprintf(buf, buflen, + "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", +- guid->data1, guid->data2, guid->data3, ++ htonl(guid->data1), htons(guid->data2), htons(guid->data3), + guid->data4[0], guid->data4[1], guid->data4[2], + guid->data4[3], guid->data4[4], guid->data4[5], + guid->data4[6], guid->data4[7]); +@@ -905,7 +909,7 @@ int sadump_memory_dump(FILE *fp) + struct sadump_header *sh; + struct sadump_media_header *smh; + int i, others; +- char guid[33]; ++ char guid[SADUMP_EFI_GUID_TEXT_REPR_LEN+1]; + + fprintf(fp, "sadump_data: \n"); + fprintf(fp, " filename: %s\n", sd->filename); +--- crash-7.0.2/defs.h 2013-10-25 15:28:55.937879568 -0400 ++++ crash-7.0.3/defs.h 2013-10-25 11:49:58.544481437 -0400 +@@ -59,7 +59,7 @@ + #define ATTRIBUTE_UNUSED __attribute__ ((__unused__)) + #endif + +-#define BASELEVEL_REVISION "7.0.2" ++#define BASELEVEL_REVISION "7.0.3" + + #undef TRUE + #undef FALSE +@@ -503,6 +503,7 @@ struct program_context { + #define QEMU_MEM_DUMP (0x100ULL) + #define GET_LOG (0x200ULL) + #define VMCOREINFO (0x400ULL) ++#define ALLOW_FP (0x800ULL) + char *cleanup; + char *namelist_orig; + char *namelist_debug_orig; +@@ -1876,6 +1877,9 @@ struct offset_table { + long task_struct_thread_context_fp; + long task_struct_thread_context_sp; + long task_struct_thread_context_pc; ++ long page_slab_page; ++ long trace_print_flags_mask; ++ long trace_print_flags_name; + }; + + struct size_table { /* stash of commonly-used sizes */ +@@ -2016,6 +2020,7 @@ struct size_table { /* stash of + long hrtimer_clock_base; + long hrtimer_base; + long tnt; ++ long trace_print_flags; + }; + + struct array_table { +@@ -2183,6 +2188,13 @@ struct vm_table { /* kern + int cpu_slab_type; + int nr_vm_event_items; + char **vm_event_items; ++ int nr_bad_slab_caches; ++ ulong *bad_slab_caches; ++ int nr_pageflags; ++ struct pageflags_data { ++ ulong mask; ++ char *name; ++ } *pageflags_data; + }; + + #define NODES (0x1) +@@ -2211,6 +2223,7 @@ struct vm_table { /* kern + #define NODELISTS_IS_PTR (0x800000) + #define KMALLOC_COMMON (0x1000000) + #define USE_VMAP_AREA (0x2000000) ++#define PAGEFLAGS (0x4000000) + + #define IS_FLATMEM() (vt->flags & FLATMEM) + #define IS_DISCONTIGMEM() (vt->flags & DISCONTIGMEM) +@@ -4321,6 +4334,7 @@ int calculate(char *, ulong *, ulonglong + int endian_mismatch(char *, char, ulong); + uint16_t swap16(uint16_t, int); + uint32_t swap32(uint32_t, int); ++ulong *get_cpumask_buf(void); + int make_cpumask(char *, ulong *, int, int *); + size_t strlcpy(char *, char *, size_t); + struct rb_node *rb_first(struct rb_root *); +--- crash-7.0.2/diskdump.h 2013-10-25 15:28:56.133879559 -0400 ++++ crash-7.0.3/diskdump.h 2013-10-18 11:11:20.610295600 -0400 +@@ -42,7 +42,9 @@ struct disk_dump_header { + header in blocks */ + unsigned int bitmap_blocks; /* Size of Memory bitmap in + block */ +- unsigned int max_mapnr; /* = max_mapnr */ ++ unsigned int max_mapnr; /* = max_mapnr, OBSOLETE! ++ 32bit only, full 64bit ++ in sub header. */ + unsigned int total_ram_blocks;/* Number of blocks should be + written */ + unsigned int device_blocks; /* Number of total blocks in +@@ -61,14 +63,21 @@ struct kdump_sub_header { + unsigned long phys_base; + int dump_level; /* header_version 1 and later */ + int split; /* header_version 2 and later */ +- unsigned long start_pfn; /* header_version 2 and later */ +- unsigned long end_pfn; /* header_version 2 and later */ ++ unsigned long start_pfn; /* header_version 2 and later, ++ OBSOLETE! 32bit only, full 64bit ++ in start_pfn_64. */ ++ unsigned long end_pfn; /* header_version 2 and later, ++ OBSOLETE! 32bit only, full 64bit ++ in end_pfn_64. */ + off_t offset_vmcoreinfo; /* header_version 3 and later */ + unsigned long size_vmcoreinfo; /* header_version 3 and later */ + off_t offset_note; /* header_version 4 and later */ + unsigned long size_note; /* header_version 4 and later */ + off_t offset_eraseinfo; /* header_version 5 and later */ + unsigned long size_eraseinfo; /* header_version 5 and later */ ++ unsigned long long start_pfn_64; /* header_version 6 and later */ ++ unsigned long long end_pfn_64; /* header_version 6 and later */ ++ unsigned long long max_mapnr_64; /* header_version 6 and later */ + }; + + /* page flags */ +--- crash-7.0.2/lkcd_vmdump_v1.h 2013-10-25 15:28:55.935879568 -0400 ++++ crash-7.0.3/lkcd_vmdump_v1.h 2013-10-24 09:06:51.222888110 -0400 +@@ -117,10 +117,12 @@ typedef struct _dump_header_s { + #ifndef IA64 + #ifndef S390 + #ifndef S390X ++#ifndef ARM64 + struct pt_regs dh_regs; + #endif + #endif + #endif ++#endif + + /* the address of the current task */ + struct task_struct *dh_current_task; +--- crash-7.0.2/lkcd_vmdump_v2_v3.h 2013-10-25 15:28:55.938879568 -0400 ++++ crash-7.0.3/lkcd_vmdump_v2_v3.h 2013-10-24 09:13:13.588870592 -0400 +@@ -84,9 +84,11 @@ typedef struct _dump_header_asm_s { + /* the dump registers */ + #ifndef S390 + #ifndef S390X ++#ifndef ARM64 + struct pt_regs dha_regs; + #endif + #endif ++#endif + + } dump_header_asm_t; + +--- crash-7.0.2/sadump.h 2013-10-25 15:28:55.939879568 -0400 ++++ crash-7.0.3/sadump.h 2013-09-13 08:48:05.576229221 -0400 +@@ -41,6 +41,8 @@ typedef struct { + uint8_t data4[8]; + } efi_guid_t; + ++#define SADUMP_EFI_GUID_TEXT_REPR_LEN 36 ++ + struct sadump_part_header { + #define SADUMP_SIGNATURE1 0x75646173 + #define SADUMP_SIGNATURE2 0x0000706d +--- crash-7.0.2/extensions/snap.c 2013-10-25 15:28:55.943879568 -0400 ++++ crash-7.0.3/extensions/snap.c 2013-10-25 10:10:39.188754456 -0400 +@@ -416,7 +416,8 @@ generate_elf_header(int type, int fd, ch + } else if (machine_type("PPC64")) { + e_machine = EM_PPC64; + prstatus_len = sizeof(prstatus.ppc64); +- } ++ } else ++ return NULL; + + /* should be enought for the notes + roundup + two blocks */ + buffer = (char *)GETBUF(sizeof(Elf64_Ehdr) + +@@ -538,7 +539,7 @@ generate_elf_header(int type, int fd, ch + break; + } + +- l_offset += load[i].p_filesz; ++// l_offset += load[i].p_filesz; + offset += sizeof(Elf64_Phdr); + ptr += sizeof(Elf64_Phdr); + } +--- crash-7.0.2/extensions/trace.c 2013-10-25 15:28:55.944879568 -0400 ++++ crash-7.0.3/extensions/trace.c 2013-10-25 10:10:44.031754234 -0400 +@@ -1453,6 +1453,7 @@ static void ftrace_show(int argc, char * + if ((file = popen(trace_cmd, "r"))) { + ret = fread(buf, 1, sizeof(buf), file); + buf[ret] = 0; ++ pclose(file); + } + if (!strstr(buf, "trace-cmd version")) { + if (env_trace_cmd) +--- crash-7.0.3/defs.h.orig ++++ crash-7.0.3/defs.h +@@ -1880,6 +1880,8 @@ struct offset_table { + long page_slab_page; + long trace_print_flags_mask; + long trace_print_flags_name; ++ long task_struct_rss_stat; ++ long task_rss_stat_count; + }; + + struct size_table { /* stash of commonly-used sizes */ +--- crash-7.0.3/symbols.c.orig ++++ crash-7.0.3/symbols.c +@@ -7643,6 +7643,10 @@ dump_offset_table(char *spec, ulong make + OFFSET(task_struct_tgid)); + fprintf(fp, " task_struct_namespace: %ld\n", + OFFSET(task_struct_namespace)); ++ fprintf(fp, " task_struct_rss_stat: %ld\n", ++ OFFSET(task_struct_rss_stat)); ++ fprintf(fp, " task_rss_stat_count: %ld\n", ++ OFFSET(task_rss_stat_count)); + fprintf(fp, " task_struct_pids: %ld\n", + OFFSET(task_struct_pids)); + fprintf(fp, " task_struct_last_run: %ld\n", +--- crash-7.0.3/memory.c.orig ++++ crash-7.0.3/memory.c +@@ -4003,6 +4003,7 @@ void + get_task_mem_usage(ulong task, struct task_mem_usage *tm) + { + struct task_context *tc; ++ long rss = 0; + + BZERO(tm, sizeof(struct task_mem_usage)); + +@@ -4036,22 +4037,65 @@ get_task_mem_usage(ulong task, struct ta + filepages = 0; + anonpages = 1; + } +- tm->rss += ULONG(tt->mm_struct + ++ rss += LONG(tt->mm_struct + + OFFSET(mm_struct_rss_stat) + + OFFSET(mm_rss_stat_count) + +- (filepages * sizeof(ulong))); +- tm->rss += ULONG(tt->mm_struct + ++ (filepages * sizeof(long))); ++ rss += LONG(tt->mm_struct + + OFFSET(mm_struct_rss_stat) + + OFFSET(mm_rss_stat_count) + +- (anonpages * sizeof(ulong))); ++ (anonpages * sizeof(long))); + } ++ ++ /* Check whether SPLIT_RSS_COUNTING is enabled */ ++ if (VALID_MEMBER(task_struct_rss_stat)) { ++ int i, sync_rss; ++ ulong tgid; ++ struct task_context *tc1; ++ ++ tgid = task_tgid(task); ++ ++ tc1 = FIRST_CONTEXT(); ++ for (i = 0; i < RUNNING_TASKS(); i++, tc1++) { ++ if (task_tgid(tc1->task) != tgid) ++ continue; ++ ++ /* count 0 -> filepages */ ++ if (!readmem(tc1->task + ++ OFFSET(task_struct_rss_stat) + ++ OFFSET(task_rss_stat_count), KVADDR, ++ &sync_rss, ++ sizeof(int), ++ "task_struct rss_stat MM_FILEPAGES", ++ RETURN_ON_ERROR)) ++ continue; ++ ++ rss += sync_rss; ++ ++ /* count 1 -> anonpages */ ++ if (!readmem(tc1->task + ++ OFFSET(task_struct_rss_stat) + ++ OFFSET(task_rss_stat_count) + ++ sizeof(int), ++ KVADDR, &sync_rss, ++ sizeof(int), ++ "task_struct rss_stat MM_ANONPAGES", ++ RETURN_ON_ERROR)) ++ continue; ++ ++ rss += sync_rss; ++ } ++ } ++ + /* + * mm_struct._anon_rss and mm_struct._file_rss should exist. + */ + if (VALID_MEMBER(mm_struct_anon_rss)) +- tm->rss += ULONG(tt->mm_struct + OFFSET(mm_struct_anon_rss)); ++ rss += LONG(tt->mm_struct + OFFSET(mm_struct_anon_rss)); + if (VALID_MEMBER(mm_struct_file_rss)) +- tm->rss += ULONG(tt->mm_struct + OFFSET(mm_struct_file_rss)); ++ rss += LONG(tt->mm_struct + OFFSET(mm_struct_file_rss)); ++ ++ tm->rss = (unsigned long)rss; + } + tm->total_vm = ULONG(tt->mm_struct + OFFSET(mm_struct_total_vm)); + tm->pgd_addr = ULONG(tt->mm_struct + OFFSET(mm_struct_pgd)); +--- crash-7.0.3/task.c.orig ++++ crash-7.0.3/task.c +@@ -349,6 +349,11 @@ task_init(void) + MEMBER_OFFSET_INIT(task_struct_run_list, "task_struct", + "run_list"); + ++ MEMBER_OFFSET_INIT(task_struct_rss_stat, "task_struct", ++ "rss_stat"); ++ MEMBER_OFFSET_INIT(task_rss_stat_count, "task_rss_stat", ++ "count"); ++ + if ((tt->task_struct = (char *)malloc(SIZE(task_struct))) == NULL) + error(FATAL, "cannot malloc task_struct space."); + diff --git a/SPECS/crash.spec b/SPECS/crash.spec new file mode 100644 index 0000000..223f899 --- /dev/null +++ b/SPECS/crash.spec @@ -0,0 +1,339 @@ +# +# crash core analysis suite +# +Summary: Kernel analysis utility for live systems, netdump, diskdump, kdump, LKCD or mcore dumpfiles +Name: crash +Version: 7.0.2 +Release: 2%{?dist} +License: GPLv3 +Group: Development/Debuggers +Source: http://people.redhat.com/anderson/crash-%{version}.tar.gz +URL: http://people.redhat.com/anderson +ExclusiveOS: Linux +ExclusiveArch: %{ix86} ia64 x86_64 ppc ppc64 s390 s390x %{arm} aarch64 +Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot-%(%{__id_u} -n) +BuildRequires: ncurses-devel zlib-devel lzo-devel bison snappy-devel +Requires: binutils +Patch0: lzo_snappy.patch +Patch1: rhel7.0_beta.patch + +%description +The core analysis suite is a self-contained tool that can be used to +investigate either live systems, kernel core dumps created from the +netdump, diskdump and kdump packages from Red Hat Linux, the mcore kernel patch +offered by Mission Critical Linux, or the LKCD kernel patch. + +%package devel +Requires: %{name} = %{version}, zlib-devel lzo-devel snappy-devel +Summary: kernel crash analysis utility for live systems, netdump, diskdump, kdump, LKCD or mcore dumpfiles +Group: Development/Debuggers + +%description devel +The core analysis suite is a self-contained tool that can be used to +investigate either live systems, kernel core dumps created from the +netdump, diskdump and kdump packages from Red Hat Linux, the mcore kernel patch +offered by Mission Critical Linux, or the LKCD kernel patch. + +%prep +%setup -n %{name}-%{version} -q +%patch0 -p1 -b lzo_snappy.patch +%patch1 -p1 -b rhel7.0_beta.patch + +%build +make RPMPKG="%{version}-%{release}" CFLAGS="%{optflags}" + +%install +rm -rf %{buildroot} +mkdir -p %{buildroot}%{_bindir} +make DESTDIR=%{buildroot} install +mkdir -p %{buildroot}%{_mandir}/man8 +cp -p crash.8 %{buildroot}%{_mandir}/man8/crash.8 +mkdir -p %{buildroot}%{_includedir}/crash +chmod 0644 defs.h +cp -p defs.h %{buildroot}%{_includedir}/crash + +%clean +rm -rf %{buildroot} + +%files +%defattr(-,root,root,-) +%{_bindir}/crash +%{_mandir}/man8/crash.8* +%doc README COPYING3 + +%files devel +%defattr(-,root,root,-) +%{_includedir}/* + +%changelog +* Tue Oct 29 2013 Dave Anderson - 7.0.2-2 +- Compressed kdump 46-bit physical memory support + Resolves: rhbz#1015250 +- Fix incorrect backtrace for dumps taken with "virsh dump --memory-only" + Resolves: rhbz#1020469 +- Fix cpu number display on systems with more than 254 cpus + Resolves: rhbz#1020536 + +* Wed Sep 04 2013 Dave Anderson - 7.0.2-1 +- Update to latest upstream release +- Fix for ppc64 embedded gdb NULL pointer translation sigsegv +- Fix for bt -F failure + +* Fri Jul 26 2013 Dave Anderson - 7.0.1-4 +- Add lzo-devel and snappy-devel to crash-devel Requires line + +* Tue Jul 23 2013 Dave Anderson - 7.0.1-3 +- Build with snappy compression support + +* Tue Jul 9 2013 Dave Anderson - 7.0.1-2 +- Fix for ppc64 Linux 3.10 vmalloc/user-space virtual address translation + +* Tue Jun 18 2013 Dave Anderson - 7.0.1-1 +- Update to latest upstream release +- Build with LZO support + +* Tue Apr 9 2013 Dave Anderson - 6.1.6-1 +- Update to latest upstream release + +* Tue Feb 19 2013 Dave Anderson - 6.1.4-1 +- Update to latest upstream release + +* Wed Feb 13 2013 Fedora Release Engineering - 6.1.2-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild + +* Wed Jan 9 2013 Dave Anderson - 6.1.2-1 +- Update to latest upstream release + +* Tue Nov 27 2012 Dave Anderson - 6.1.1-1 +- Update to latest upstream release + +* Mon Sep 1 2012 Dave Anderson - 6.1.0-1 +- Add ppc to ExclusiveArch list +- Update to latest upstream release + +* Tue Aug 21 2012 Dave Anderson - 6.0.9-1 +- Update to latest upstream release + +* Wed Jul 18 2012 Fedora Release Engineering - 6.0.8-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Mon Jul 1 2012 Dave Anderson - 6.0.8-1 +- Update to latest upstream release. +- Replace usage of "struct siginfo" with "siginfo_t". + +* Mon Apr 30 2012 Dave Anderson - 6.0.6-1 +- Update to latest upstream release + +* Mon Mar 26 2012 Dave Anderson - 6.0.5-1 +- Update to latest upstream release + +* Wed Jan 4 2012 Dave Anderson - 6.0.2-1 +- Update to latest upstream release + +* Wed Oct 26 2011 Dave Anderson - 6.0.0-1 +- Update to latest upstream release + +* Tue Sep 20 2011 Dave Anderson - 5.1.8-1 +- Update to latest upstream release +- Additional fixes for gcc-4.6 -Werror compile failures for ARM architecture. + +* Thu Sep 1 2011 Dave Anderson - 5.1.7-2 +- Fixes for gcc-4.6 -Werror compile failures for ARM architecture. + +* Wed Aug 17 2011 Dave Anderson - 5.1.7-1 +- Update to latest upstream release +- Fixes for gcc-4.6 -Werror compile failures for ppc64/ppc. + +* Tue May 31 2011 Peter Robinson - 5.1.5-1 +- Update to latest upstream release +- Add ARM to the Exclusive arch + +* Wed Feb 25 2011 Dave Anderson - 5.1.2-2 +- Fixes for gcc-4.6 -Werror compile failures in gdb module. + +* Wed Feb 23 2011 Dave Anderson - 5.1.2-1 +- Upstream version. + +* Tue Feb 08 2011 Fedora Release Engineering - 5.0.6-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Tue Jul 20 2010 Dave Anderson - 5.0.6-2 +- Bump version. + +* Tue Jul 20 2010 Dave Anderson - 5.0.6-1 +- Update to upstream version. + +* Fri Sep 11 2009 Dave Anderson - 4.0.9-2 + Bump version. + +* Fri Sep 11 2009 Dave Anderson - 4.0.9-1 +- Update to upstream release, which allows the removal of the + Revision tag workaround, the crash-4.0-8.11-dwarf3.patch and + the crash-4.0-8.11-optflags.patch + +* Sun Aug 05 2009 Lubomir Rintel - 4.0.8.11-2 +- Fix reading of dwarf 3 DW_AT_data_member_location +- Use proper compiler flags + +* Wed Aug 05 2009 Lubomir Rintel - 4.0.8.11-1 +- Update to later upstream release +- Fix abuse of Revision tag + +- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild +* Fri Jul 24 2009 Fedora Release Engineering - 4.0-9.7.2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild + +* Tue Feb 24 2009 Fedora Release Engineering - 4.0-8.7.2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild + +* Thu Feb 19 2009 Dave Anderson - 4.0-7.7.2 +- Replace exclusive arch i386 with ix86. + +* Thu Feb 19 2009 Dave Anderson - 4.0-7.7.1 +- Updates to this file per crash merge review +- Update to upstream version 4.0-7.7. Full changelog viewable in: + http://people.redhat.com/anderson/crash.changelog.html + +* Tue Jul 15 2008 Tom "spot" Callaway 4.0-7 +- fix license tag + +* Tue Apr 29 2008 Dave Anderson - 4.0-6.3 +- Added crash-devel subpackage +- Updated crash.patch to match upstream version 4.0-6.3 + +* Wed Feb 20 2008 Dave Anderson - 4.0-6.0.5 +- Second attempt at addressing the GCC 4.3 build, which failed due + to additional ptrace.h includes in the lkcd vmdump header files. + +* Wed Feb 20 2008 Dave Anderson - 4.0-6.0.4 +- First attempt at addressing the GCC 4.3 build, which failed on x86_64 + because ptrace-abi.h (included by ptrace.h) uses the "u32" typedef, + which relies on , and include/asm-x86_64/types.h + does not not typedef u32 as done in include/asm-x86/types.h. + +* Mon Feb 18 2008 Fedora Release Engineering - 4.0-6.0.3 +- Autorebuild for GCC 4.3 + +* Wed Jan 23 2008 Dave Anderson - 4.0-5.0.3 +- Updated crash.patch to match upstream version 4.0-5.0. + +* Wed Aug 29 2007 Dave Anderson - 4.0-4.6.2 +- Updated crash.patch to match upstream version 4.0-4.6. + +* Wed Sep 13 2006 Dave Anderson - 4.0-3.3 +- Updated crash.patch to match upstream version 4.0-3.3. +- Support for x86_64 relocatable kernels. BZ #204557 + +* Mon Aug 7 2006 Dave Anderson - 4.0-3.1 +- Updated crash.patch to match upstream version 4.0-3.1. +- Added kdump reference to description. +- Added s390 and s390x to ExclusiveArch list. BZ #199125 +- Removed LKCD v1 pt_regs references for s390/s390x build. +- Removed LKCD v2_v3 pt_regs references for for s390/s390x build. + +* Fri Jul 14 2006 Jesse Keating - 4.0-3 +- rebuild + +* Mon May 15 2006 Dave Anderson - 4.0-2.26.4 +- Updated crash.patch such that is not #include'd + by s390_dump.c; IBM did not make the file s390[s] only; BZ #192719 + +* Mon May 15 2006 Dave Anderson - 4.0-2.26.3 +- Updated crash.patch such that is not #include'd + by vas_crash.h; only ia64 build complained; BZ #191719 + +* Mon May 15 2006 Dave Anderson - 4.0-2.26.2 +- Updated crash.patch such that is not #include'd + by lkcd_x86_trace.c; also for BZ #191719 + +* Mon May 15 2006 Dave Anderson - 4.0-2.26.1 +- Updated crash.patch to bring it up to 4.0-2.26, which should + address BZ #191719 - "crash fails to build in mock" + +* Tue Feb 07 2006 Jesse Keating - 4.0-2.18.1 +- rebuilt for new gcc4.1 snapshot and glibc changes + +* Wed Jan 04 2006 Dave Anderson 4.0-2.18 +- Updated source package to crash-4.0.tar.gz, and crash.patch + to bring it up to 4.0-2.18. + +* Fri Dec 09 2005 Jesse Keating +- rebuilt + +* Thu Mar 03 2005 Dave Anderson 3.10-13 +- Compiler error- and warning-related fixes for gcc 4 build. +- Update to enhance x86 and x86_64 gdb disassembly output so as to + symbolically display call targets from kernel module text without + requiring module debuginfo data. +- Fix hole where an ia64 vmcore could be mistakenly accepted as a + usable dumpfile on an x86_64 machine, leading eventually to a + non-related error message. +* Wed Mar 02 2005 Dave Anderson 3.10-12 +- rebuild (gcc 4) +* Thu Feb 10 2005 Dave Anderson 3.10-9 +- Updated source package to crash-3.10.tar.gz, containing + IBM's final ppc64 processor support for RHEL4 +- Fixes potential "bt -a" hang on dumpfile where netdump IPI interrupted + an x86 process while executing the instructions just after it had entered + the kernel for a syscall, but before calling the handler. BZ #139437 +- Update to handle backtraces in dumpfiles generated on IA64 with the + INIT switch (functionality intro'd in RHEL3-U5 kernel). BZ #139429 +- Fix for handling ia64 and x86_64 machines booted with maxcpus=1 on + an SMP kernel. BZ #139435 +- Update to handle backtraces in dumpfiles generated on x86_64 from the + NMI exception stack (functionality intro'd in RHEL3-U5 kernel). +- "kmem -[sS]" beefed up to more accurately verify slab cache chains + and report errors found. +- Fix for ia64 INIT switch-generated backtrace handling when + init_handler_platform() is inlined into ia64_init_handler(); + properly handles both RHEL3 and RHEL4 kernel patches. + BZ #138350 +- Update to enhance ia64 gdb disassembly output so as to + symbolically display call targets from kernel module + text without requiring module debuginfo data. + +* Wed Jul 14 2004 Dave Anderson 3.8-5 +- bump release for fc3 + +* Tue Jul 13 2004 Dave Anderson 3.8-4 +- Fix for gcc 3.4.x/gdb issue where vmlinux was mistakenly presumed non-debug + +* Fri Jun 25 2004 Dave Anderson 3.8-3 +- remove (harmless) error message during ia64 diskdump invocation when + an SMP system gets booted with maxcpus=1 +- several 2.6 kernel specific updates + +* Thu Jun 17 2004 Dave Anderson 3.8-2 +- updated source package to crash-3.8.tar.gz +- diskdump support +- x86_64 processor support + +* Mon Sep 22 2003 Dave Anderson 3.7-5 +- make bt recovery code start fix-up only upon reaching first faulting frame + +* Fri Sep 19 2003 Dave Anderson 3.7-4 +- fix "bt -e" and bt recovery code to recognize new __KERNEL_CS and DS + +* Wed Sep 10 2003 Dave Anderson 3.7-3 +- patch to recognize per-cpu GDT changes that redefine __KERNEL_CS and DS + +* Wed Sep 10 2003 Dave Anderson 3.7-2 +- patches for netdump active_set determination and slab info gathering + +* Wed Aug 20 2003 Dave Anderson 3.7-1 +- updated source package to crash-3.7.tar.gz + +* Wed Jul 23 2003 Dave Anderson 3.6-1 +- removed Packager, Distribution, and Vendor tags +- updated source package to crash-3.6.tar.gz + +* Fri Jul 18 2003 Jay Fenlason 3.5-2 +- remove ppc from arch list, since it doesn't work with ppc64 kernels +- remove alpha from the arch list since we don't build it any more + +* Fri Jul 18 2003 Matt Wilson 3.5-1 +- use %%defattr(-,root,root) + +* Tue Jul 15 2003 Jay Fenlason +- Updated spec file as first step in turning this into a real RPM for taroon. +- Wrote man page.