Blame SOURCES/rhel7.0_beta.patch

aec172
--- crash-7.0.2/main.c	2013-10-25 15:28:55.938879568 -0400
aec172
+++ crash-7.0.3/main.c	2013-10-15 15:55:10.136390264 -0400
aec172
@@ -1335,6 +1335,8 @@ dump_program_context(void)
aec172
 		fprintf(fp, "%sGET_LOG", others++ ? "|" : "");
aec172
 	if (pc->flags2 & VMCOREINFO)
aec172
 		fprintf(fp, "%sVMCOREINFO", others++ ? "|" : "");
aec172
+	if (pc->flags2 & ALLOW_FP)
aec172
+		fprintf(fp, "%sALLOW_FP", others++ ? "|" : "");
aec172
 	fprintf(fp, ")\n");
aec172
 
aec172
 	fprintf(fp, "         namelist: %s\n", pc->namelist);
aec172
--- crash-7.0.2/tools.c	2013-10-25 15:28:55.922879569 -0400
aec172
+++ crash-7.0.3/tools.c	2013-10-25 10:09:31.938757537 -0400
aec172
@@ -989,7 +989,7 @@ dtoi(char *s, int flags, int *errptr)
aec172
                 if ((s[j] < '0' || s[j] > '9'))
aec172
                         break ;
aec172
 
aec172
-        if (s[j] != '\0' || (sscanf(s, "%d", &retval) != 1)) {
aec172
+        if (s[j] != '\0' || (sscanf(s, "%d", (int *)&retval) != 1)) {
aec172
 		if (!(flags & QUIET))
aec172
                 	error(INFO, "%s: \"%c\" is not a digit 0 - 9\n", 
aec172
 				s, s[j]);
aec172
@@ -5489,6 +5489,19 @@ swap32(uint32_t val, int swap)
aec172
 		return val;
aec172
 }
aec172
 
aec172
+/*
aec172
+ *  Get a sufficiently large buffer for cpumask.
aec172
+ *  You should call FREEBUF() on the result when you no longer need it.
aec172
+ */
aec172
+ulong *
aec172
+get_cpumask_buf(void)
aec172
+{
aec172
+	int cpulen;
aec172
+	if ((cpulen = STRUCT_SIZE("cpumask_t")) < 0)
aec172
+		cpulen = DIV_ROUND_UP(kt->cpus, BITS_PER_LONG) * sizeof(ulong);
aec172
+	return (ulong *)GETBUF(cpulen);
aec172
+}
aec172
+
aec172
 int
aec172
 make_cpumask(char *s, ulong *mask, int flags, int *errptr)
aec172
 {
aec172
@@ -5505,14 +5518,20 @@ make_cpumask(char *s, ulong *mask, int f
aec172
 	p = strtok(s, ",");
aec172
 	while (p) {
aec172
 		s = strtok(NULL, "");
aec172
-		start = end = -1;
aec172
-		q = strtok(p, "-");
aec172
-		start = dtoi(q, flags, errptr);
aec172
-		if ((q = strtok(NULL, "-")))
aec172
-			end = dtoi(q, flags, errptr);
aec172
 
aec172
-		if (end == -1)
aec172
-			end = start;
aec172
+		if (STREQ(p, "a") || STREQ(p, "all")) {
aec172
+			start = 0;
aec172
+			end = kt->cpus - 1;
aec172
+		} else {
aec172
+			start = end = -1;
aec172
+			q = strtok(p, "-");
aec172
+			start = dtoi(q, flags, errptr);
aec172
+			if ((q = strtok(NULL, "-")))
aec172
+				end = dtoi(q, flags, errptr);
aec172
+
aec172
+			if (end == -1)
aec172
+				end = start;
aec172
+		}
aec172
 
aec172
 		for (i = start; i <= end; i++)
aec172
 			SET_BIT(mask, i);
aec172
--- crash-7.0.2/memory.c	2013-10-25 15:28:55.934879568 -0400
aec172
+++ crash-7.0.3/memory.c	2013-10-25 10:09:35.641757367 -0400
aec172
@@ -134,6 +134,10 @@ static char *error_handle_string(ulong);
aec172
 static void dump_mem_map(struct meminfo *);
aec172
 static void dump_mem_map_SPARSEMEM(struct meminfo *);
aec172
 static void fill_mem_map_cache(ulong, ulong, char *);
aec172
+static void page_flags_init(void);
aec172
+static int page_flags_init_from_pageflag_names(void);
aec172
+static int page_flags_init_from_pageflags_enum(void);
aec172
+static int translate_page_flags(char *, ulong);
aec172
 static void dump_free_pages(struct meminfo *);
aec172
 static int dump_zone_page_usage(void);
aec172
 static void dump_multidimensional_free_pages(struct meminfo *);
aec172
@@ -613,6 +617,13 @@ vm_init(void)
aec172
 		MEMBER_OFFSET_INIT(kmem_list3_free_objects, 
aec172
 			kmem_cache_node_struct, "free_objects");
aec172
 		MEMBER_OFFSET_INIT(kmem_list3_shared, kmem_cache_node_struct, "shared");
aec172
+		/*
aec172
+		 *  Common to slab/slub
aec172
+		 */
aec172
+		ANON_MEMBER_OFFSET_INIT(page_slab, "page", "slab_cache");
aec172
+		ANON_MEMBER_OFFSET_INIT(page_slab_page, "page", "slab_page");
aec172
+		ANON_MEMBER_OFFSET_INIT(page_first_page, "page", "first_page");
aec172
+
aec172
 	} else if (MEMBER_EXISTS("kmem_cache", "cpu_slab") &&
aec172
 		STRUCT_EXISTS("kmem_cache_node")) {
aec172
 		vt->flags |= KMALLOC_SLUB;
aec172
@@ -642,6 +653,7 @@ vm_init(void)
aec172
 		ANON_MEMBER_OFFSET_INIT(page_slab, "page", "slab");
aec172
 		if (INVALID_MEMBER(page_slab))
aec172
 			ANON_MEMBER_OFFSET_INIT(page_slab, "page", "slab_cache");
aec172
+		ANON_MEMBER_OFFSET_INIT(page_slab_page, "page", "slab_page");
aec172
 		ANON_MEMBER_OFFSET_INIT(page_first_page, "page", "first_page");
aec172
 		ANON_MEMBER_OFFSET_INIT(page_freelist, "page", "freelist");
aec172
 		if (INVALID_MEMBER(kmem_cache_objects)) {
aec172
@@ -703,16 +715,16 @@ vm_init(void)
aec172
 	}
aec172
 
aec172
 	if (!kt->kernel_NR_CPUS) {
aec172
-		if (ARRAY_LENGTH(kmem_cache_s_cpudata))
aec172
+		if (enumerator_value("WORK_CPU_UNBOUND", (long *)&value1))
aec172
+			kt->kernel_NR_CPUS = (int)value1;
aec172
+		else if ((i = get_array_length("__per_cpu_offset", NULL, 0)))
aec172
+			kt->kernel_NR_CPUS = i;
aec172
+		else if (ARRAY_LENGTH(kmem_cache_s_cpudata))
aec172
 			kt->kernel_NR_CPUS = ARRAY_LENGTH(kmem_cache_s_cpudata);
aec172
 		else if (ARRAY_LENGTH(kmem_cache_s_array))
aec172
 			kt->kernel_NR_CPUS = ARRAY_LENGTH(kmem_cache_s_array);
aec172
 		else if (ARRAY_LENGTH(kmem_cache_cpu_slab))
aec172
 			kt->kernel_NR_CPUS = ARRAY_LENGTH(kmem_cache_cpu_slab);
aec172
-		else if (enumerator_value("WORK_CPU_UNBOUND", (long *)&value1))
aec172
-			kt->kernel_NR_CPUS = (int)value1;
aec172
-		else if ((i = get_array_length("__per_cpu_offset", NULL, 0)))
aec172
-			kt->kernel_NR_CPUS = i;
aec172
 	}
aec172
 
aec172
 	if (CRASHDEBUG(1))
aec172
@@ -1025,8 +1037,7 @@ vm_init(void)
aec172
 
aec172
 	kmem_cache_init();
aec172
 
aec172
-	PG_reserved_flag_init();
aec172
-	PG_slab_flag_init();
aec172
+	page_flags_init();
aec172
 
aec172
 	vt->flags |= VM_INIT;
aec172
 }
aec172
@@ -4533,15 +4544,37 @@ PG_slab_flag_init(void)
aec172
         char buf[BUFSIZE];  /* safe for a page struct */
aec172
 
aec172
 	/*
aec172
-	 *  Set the old defaults in case the search below fails.
aec172
+	 *  Set the old defaults in case all else fails.
aec172
 	 */
aec172
-        if (VALID_MEMBER(page_pte)) {
aec172
+	if (enumerator_value("PG_slab", (long *)&flags)) {
aec172
+		vt->PG_slab = flags;
aec172
+		if (CRASHDEBUG(2))
aec172
+			fprintf(fp, "PG_slab (enum): %lx\n", vt->PG_slab);
aec172
+	} else if (VALID_MEMBER(page_pte)) {
aec172
                 if (THIS_KERNEL_VERSION < LINUX(2,6,0))
aec172
                         vt->PG_slab = 10;
aec172
                 else if (THIS_KERNEL_VERSION >= LINUX(2,6,0))
aec172
                         vt->PG_slab = 7;
aec172
-        } else if (THIS_KERNEL_VERSION >= LINUX(2,6,0))
aec172
-                vt->PG_slab = 7;
aec172
+        } else if (THIS_KERNEL_VERSION >= LINUX(2,6,0)) {
aec172
+		vt->PG_slab = 7;
aec172
+	} else {
aec172
+		if (try_get_symbol_data("vm_area_cachep", sizeof(void *), &vaddr) &&
aec172
+            	    phys_to_page((physaddr_t)VTOP(vaddr), &pageptr) &&
aec172
+                    readmem(pageptr, KVADDR, buf, SIZE(page),
aec172
+		    "vm_area_cachep page", RETURN_ON_ERROR|QUIET)) {
aec172
+
aec172
+			flags = ULONG(buf + OFFSET(page_flags));
aec172
+
aec172
+			if ((bit = ffsl(flags))) {
aec172
+				vt->PG_slab = bit - 1;
aec172
+	
aec172
+				if (CRASHDEBUG(2))
aec172
+					fprintf(fp,
aec172
+			"PG_slab bit: vaddr: %lx page: %lx flags: %lx => %ld\n",
aec172
+					vaddr, pageptr, flags, vt->PG_slab);
aec172
+			}
aec172
+		}
aec172
+	}
aec172
 
aec172
 	if (vt->flags & KMALLOC_SLUB) {
aec172
 		/* 
aec172
@@ -4561,34 +4594,20 @@ PG_slab_flag_init(void)
aec172
 				fprintf(fp, "PG_head_tail_mask: %lx\n", 
aec172
 					vt->PG_head_tail_mask);
aec172
 		}
aec172
-
aec172
-		return;
aec172
-	}
aec172
-
aec172
-	if (enumerator_value("PG_slab", (long *)&flags)) {
aec172
-		vt->PG_slab = flags;
aec172
-	       	if (CRASHDEBUG(2))
aec172
-			fprintf(fp, "PG_slab (enum): %lx\n", vt->PG_slab);
aec172
-		return;
aec172
-	}
aec172
-
aec172
-       	if (try_get_symbol_data("vm_area_cachep", sizeof(void *), &vaddr) &&
aec172
-            phys_to_page((physaddr_t)VTOP(vaddr), &pageptr) &&
aec172
-            readmem(pageptr, KVADDR, buf, SIZE(page),
aec172
-            "vm_area_cachep page", RETURN_ON_ERROR|QUIET)) {
aec172
-
aec172
-        	flags = ULONG(buf + OFFSET(page_flags));
aec172
-
aec172
-	        if ((bit = ffsl(flags))) {
aec172
-	                vt->PG_slab = bit - 1;
aec172
-	
aec172
-	        	if (CRASHDEBUG(2))
aec172
-	                	fprintf(fp,
aec172
-	                    "PG_slab bit: vaddr: %lx page: %lx flags: %lx => %ld\n",
aec172
-	                        vaddr, pageptr, flags, vt->PG_slab);
aec172
-	
aec172
+	} else {
aec172
+		if (enumerator_value("PG_tail", (long *)&flags))
aec172
+			vt->PG_head_tail_mask = (1L << flags);
aec172
+		else if (enumerator_value("PG_compound", (long *)&flags) &&
aec172
+		    enumerator_value("PG_reclaim", (long *)&flags2)) {
aec172
+			vt->PG_head_tail_mask = ((1L << flags) | (1L << flags2));
aec172
+	       		if (CRASHDEBUG(2))
aec172
+				fprintf(fp, "PG_head_tail_mask: %lx (PG_compound|PG_reclaim)\n", 
aec172
+					vt->PG_head_tail_mask);
aec172
 		}
aec172
 	}
aec172
+
aec172
+	if (!vt->PG_slab)
aec172
+		error(INFO, "cannot determine PG_slab bit value\n");	
aec172
 }
aec172
 
aec172
 /*
aec172
@@ -5009,7 +5028,10 @@ dump_mem_map_SPARSEMEM(struct meminfo *m
aec172
 					bufferindex += sprintflag("%sreserved");
aec172
 				bufferindex += sprintf(outputbuffer+bufferindex, "\n");
aec172
 			} else if (THIS_KERNEL_VERSION > LINUX(2,4,9)) {
aec172
-				bufferindex += sprintf(outputbuffer+bufferindex, "%lx\n", flags);
aec172
+				if (vt->flags & PAGEFLAGS)
aec172
+					bufferindex += translate_page_flags(outputbuffer+bufferindex, flags);
aec172
+				else
aec172
+					bufferindex += sprintf(outputbuffer+bufferindex, "%lx\n", flags);
aec172
 			} else {
aec172
 	
aec172
 		                if ((flags >> v24_PG_locked) & 1)
aec172
@@ -5444,7 +5466,10 @@ dump_mem_map(struct meminfo *mi)
aec172
 					bufferindex += sprintflag("%sreserved");
aec172
 				bufferindex += sprintf(outputbuffer+bufferindex, "\n");
aec172
 			} else if (THIS_KERNEL_VERSION > LINUX(2,4,9)) {
aec172
-				bufferindex += sprintf(outputbuffer+bufferindex, "%lx\n", flags);
aec172
+				if (vt->flags & PAGEFLAGS)
aec172
+					bufferindex += translate_page_flags(outputbuffer+bufferindex, flags);
aec172
+				else
aec172
+					bufferindex += sprintf(outputbuffer+bufferindex, "%lx\n", flags);
aec172
 			} else {
aec172
 	
aec172
 		                if ((flags >> v24_PG_locked) & 1)
aec172
@@ -5591,6 +5616,196 @@ fill_mem_map_cache(ulong pp, ulong ppend
aec172
         }
aec172
 }
aec172
 
aec172
+static void
aec172
+page_flags_init(void)
aec172
+{
aec172
+	if (!page_flags_init_from_pageflag_names())
aec172
+		page_flags_init_from_pageflags_enum();
aec172
+
aec172
+	PG_reserved_flag_init();
aec172
+	PG_slab_flag_init();
aec172
+}
aec172
+
aec172
+static int
aec172
+page_flags_init_from_pageflag_names(void)
aec172
+{
aec172
+	int i, len;
aec172
+	char *buffer, *nameptr;
aec172
+	char namebuf[BUFSIZE];
aec172
+	ulong mask;
aec172
+	void *name;
aec172
+
aec172
+	MEMBER_OFFSET_INIT(trace_print_flags_mask, "trace_print_flags", "mask");
aec172
+	MEMBER_OFFSET_INIT(trace_print_flags_name, "trace_print_flags", "name");
aec172
+	STRUCT_SIZE_INIT(trace_print_flags, "trace_print_flags");
aec172
+
aec172
+	if (INVALID_SIZE(trace_print_flags) ||
aec172
+	    INVALID_MEMBER(trace_print_flags_mask) || 
aec172
+	    INVALID_MEMBER(trace_print_flags_name) ||
aec172
+	    !kernel_symbol_exists("pageflag_names") ||
aec172
+	    !(len = get_array_length("pageflag_names", NULL, 0)))
aec172
+		return FALSE;
aec172
+
aec172
+	buffer = GETBUF(SIZE(trace_print_flags) * len);
aec172
+
aec172
+	if (!readmem(symbol_value("pageflag_names"), KVADDR, buffer,
aec172
+	    SIZE(trace_print_flags) * len, "pageflag_names array",
aec172
+	    RETURN_ON_ERROR)) {
aec172
+		FREEBUF(buffer);
aec172
+		return FALSE;
aec172
+	}
aec172
+
aec172
+	if (!(vt->pageflags_data = (struct pageflags_data *)
aec172
+	    malloc(sizeof(struct pageflags_data) * len))) {
aec172
+		error(INFO, "cannot malloc pageflags_data cache\n");
aec172
+		FREEBUF(buffer);
aec172
+		return FALSE;
aec172
+	}
aec172
+
aec172
+	if (CRASHDEBUG(1))
aec172
+		fprintf(fp, "pageflags from pageflag_names: \n");
aec172
+
aec172
+	for (i = 0; i < len; i++) {
aec172
+		mask = ULONG(buffer + (SIZE(trace_print_flags)*i) + 
aec172
+			OFFSET(trace_print_flags_mask));		
aec172
+		name = VOID_PTR(buffer + (SIZE(trace_print_flags)*i) + 
aec172
+			OFFSET(trace_print_flags_name));		
aec172
+
aec172
+		if ((mask == -1UL) && !name) {   /* Linux 3.5 and earlier */
aec172
+			len--;
aec172
+			break;
aec172
+		}
aec172
+
aec172
+		if (!read_string((ulong)name, namebuf, BUFSIZE-1)) {
aec172
+			error(INFO, "failed to read pageflag_names entry\n",
aec172
+				i, name, mask);
aec172
+			goto pageflags_fail;
aec172
+		}
aec172
+
aec172
+		if (!(nameptr = (char *)malloc(strlen(namebuf)+1))) {
aec172
+			error(INFO, "cannot malloc pageflag_names space\n");
aec172
+			goto pageflags_fail;
aec172
+		}
aec172
+		strcpy(nameptr, namebuf);
aec172
+
aec172
+		vt->pageflags_data[i].name = nameptr;
aec172
+		vt->pageflags_data[i].mask = mask;
aec172
+
aec172
+		if (CRASHDEBUG(1)) {
aec172
+			fprintf(fp, "  %08lx %s\n", 
aec172
+				vt->pageflags_data[i].mask,
aec172
+				vt->pageflags_data[i].name);
aec172
+		}
aec172
+	}
aec172
+
aec172
+	FREEBUF(buffer);
aec172
+	vt->nr_pageflags = len;
aec172
+	vt->flags |= PAGEFLAGS;
aec172
+	return TRUE;
aec172
+
aec172
+pageflags_fail:
aec172
+	FREEBUF(buffer);
aec172
+	free(vt->pageflags_data);
aec172
+	vt->pageflags_data = NULL;
aec172
+	return FALSE;
aec172
+}
aec172
+
aec172
+static int
aec172
+page_flags_init_from_pageflags_enum(void)
aec172
+{
aec172
+	int c;
aec172
+	int p, len;
aec172
+	char *nameptr;
aec172
+	char buf[BUFSIZE];
aec172
+	char *arglist[MAXARGS];
aec172
+
aec172
+	if (!(vt->pageflags_data = (struct pageflags_data *)
aec172
+	    malloc(sizeof(struct pageflags_data) * 32))) {
aec172
+		error(INFO, "cannot malloc pageflags_data cache\n");
aec172
+		return FALSE;
aec172
+        }
aec172
+
aec172
+	p = 0;
aec172
+	pc->flags2 |= ALLOW_FP;
aec172
+	open_tmpfile();
aec172
+
aec172
+	if (dump_enumerator_list("pageflags")) {
aec172
+		rewind(pc->tmpfile);
aec172
+		while (fgets(buf, BUFSIZE, pc->tmpfile)) {
aec172
+			if (!strstr(buf, " = "))
aec172
+				continue;
aec172
+
aec172
+			c = parse_line(buf, arglist);
aec172
+
aec172
+			if (strstr(arglist[0], "__NR_PAGEFLAGS")) {
aec172
+				len = atoi(arglist[2]);
aec172
+				if (!len || (len > 32))
aec172
+					goto enum_fail;
aec172
+				vt->nr_pageflags = len;
aec172
+				break;
aec172
+			}
aec172
+
aec172
+			if (!(nameptr = (char *)malloc(strlen(arglist[0])))) {
aec172
+				error(INFO, "cannot malloc pageflags name space\n");
aec172
+				goto enum_fail;
aec172
+			}
aec172
+			strcpy(nameptr, arglist[0] + strlen("PG_"));
aec172
+			vt->pageflags_data[p].name = nameptr;
aec172
+			vt->pageflags_data[p].mask = 1 << atoi(arglist[2]); 
aec172
+
aec172
+			p++;
aec172
+		}
aec172
+	} else 
aec172
+		goto enum_fail;
aec172
+
aec172
+	close_tmpfile();
aec172
+	pc->flags2 &= ~ALLOW_FP;
aec172
+
aec172
+	if (CRASHDEBUG(1)) {
aec172
+		fprintf(fp, "pageflags from enum: \n");
aec172
+		for (p = 0; p < vt->nr_pageflags; p++)
aec172
+			fprintf(fp, "  %08lx %s\n", 
aec172
+				vt->pageflags_data[p].mask,
aec172
+				vt->pageflags_data[p].name);
aec172
+	}
aec172
+
aec172
+	vt->flags |= PAGEFLAGS;
aec172
+	return TRUE;
aec172
+
aec172
+enum_fail:
aec172
+	close_tmpfile();
aec172
+	pc->flags2 &= ~ALLOW_FP;
aec172
+
aec172
+	for (c = 0; c < p; c++)
aec172
+		free(vt->pageflags_data[c].name);
aec172
+	free(vt->pageflags_data);
aec172
+	vt->pageflags_data = NULL;
aec172
+	vt->nr_pageflags = 0;
aec172
+
aec172
+	return FALSE;
aec172
+}
aec172
+
aec172
+static int
aec172
+translate_page_flags(char *buffer, ulong flags)
aec172
+{
aec172
+	char buf[BUFSIZE];
aec172
+	int i, others;
aec172
+
aec172
+	sprintf(buf, "%lx", flags);
aec172
+
aec172
+	if (flags) {
aec172
+		for (i = others = 0; i < vt->nr_pageflags; i++) {
aec172
+			if (flags & vt->pageflags_data[i].mask)
aec172
+				sprintf(&buf[strlen(buf)], "%s%s",
aec172
+					others++ ? "," : " ",
aec172
+					vt->pageflags_data[i].name);
aec172
+		}
aec172
+	}
aec172
+	strcat(buf, "\n");
aec172
+	strcpy(buffer, buf);
aec172
+
aec172
+	return(strlen(buf));
aec172
+}
aec172
 
aec172
 /*
aec172
  *  dump_page_hash_table() displays the entries in each page_hash_table.
aec172
@@ -7240,7 +7455,8 @@ dump_kmeminfo(void)
aec172
 		page_cache_size = nr_file_pages - swapper_space_nrpages -
aec172
 			buffer_pages;
aec172
 		FREEBUF(swapper_space);
aec172
-	}
aec172
+	} else
aec172
+		page_cache_size = 0;
aec172
 
aec172
 
aec172
         pct = (page_cache_size * 100)/totalram_pages;
aec172
@@ -8085,7 +8301,9 @@ vaddr_to_kmem_cache(ulong vaddr, char *b
aec172
 		return NULL;
aec172
 	}
aec172
 
aec172
-	if (vt->flags & KMALLOC_SLUB) {
aec172
+	if ((vt->flags & KMALLOC_SLUB) ||
aec172
+	    ((vt->flags & KMALLOC_COMMON) && 
aec172
+	     VALID_MEMBER(page_slab) && VALID_MEMBER(page_first_page))) {
aec172
                 readmem(compound_head(page)+OFFSET(page_slab),
aec172
                         KVADDR, &cache, sizeof(void *),
aec172
                         "page.slab", FAULT_ON_ERROR);
aec172
@@ -8136,6 +8354,10 @@ vaddr_to_slab(ulong vaddr)
aec172
 
aec172
         if (vt->flags & KMALLOC_SLUB)
aec172
 		slab = compound_head(page);
aec172
+        else if ((vt->flags & KMALLOC_COMMON) && VALID_MEMBER(page_slab_page))
aec172
+                readmem(page+OFFSET(page_slab_page),
aec172
+                        KVADDR, &slab, sizeof(void *),
aec172
+                        "page.slab_page", FAULT_ON_ERROR);
aec172
         else if (VALID_MEMBER(page_prev))
aec172
                 readmem(page+OFFSET(page_prev),
aec172
                         KVADDR, &slab, sizeof(void *),
aec172
@@ -8212,7 +8434,7 @@ kmem_cache_init(void)
aec172
 		OFFSET(kmem_cache_s_num) : OFFSET(kmem_cache_s_c_num);
aec172
 	next_offset = vt->flags & (PERCPU_KMALLOC_V1|PERCPU_KMALLOC_V2) ?
aec172
 		OFFSET(kmem_cache_s_next) : OFFSET(kmem_cache_s_c_nextp);
aec172
-        max_cnum = max_limit = max_cpus = cache_count = 0;
aec172
+        max_cnum = max_limit = max_cpus = cache_count = tmp2 = 0;
aec172
 
aec172
 	/*
aec172
 	 *  Pre-2.6 versions used the "cache_cache" as the head of the
aec172
@@ -8431,6 +8653,43 @@ kmem_cache_downsize(void)
aec172
 	FREEBUF(cache_buf);
aec172
 }
aec172
 
aec172
+/*
aec172
+ *  Stash a list of presumably-corrupted slab cache addresses.
aec172
+ */
aec172
+static void
aec172
+mark_bad_slab_cache(ulong cache) 
aec172
+{
aec172
+	size_t sz;
aec172
+
aec172
+	if (vt->nr_bad_slab_caches) {
aec172
+		sz = sizeof(ulong) * (vt->nr_bad_slab_caches + 1);
aec172
+		if (!(vt->bad_slab_caches = realloc(vt->bad_slab_caches, sz))) {
aec172
+                	error(INFO, "cannot realloc bad_slab_caches array\n");
aec172
+			vt->nr_bad_slab_caches = 0;
aec172
+			return;
aec172
+		}
aec172
+	} else {
aec172
+		if (!(vt->bad_slab_caches = (ulong *)malloc(sizeof(ulong)))) {
aec172
+			error(INFO, "cannot malloc bad_slab_caches array\n");
aec172
+			return;
aec172
+		}
aec172
+	}
aec172
+
aec172
+	vt->bad_slab_caches[vt->nr_bad_slab_caches++] = cache;
aec172
+}
aec172
+
aec172
+static int
aec172
+bad_slab_cache(ulong cache) 
aec172
+{
aec172
+	int i;
aec172
+
aec172
+	for (i = 0; i < vt->nr_bad_slab_caches; i++) {
aec172
+		if (vt->bad_slab_caches[i] == cache)
aec172
+			return TRUE;
aec172
+	}
aec172
+
aec172
+       return FALSE;
aec172
+}
aec172
 
aec172
 /*
aec172
  *  Determine the largest cpudata limit for a given cache.
aec172
@@ -8526,8 +8785,13 @@ kmem_cache_s_array_nodes:
aec172
 	for (i = max_limit = 0; (i < kt->cpus) && cpudata[i]; i++) {
aec172
                 if (!readmem(cpudata[i]+OFFSET(array_cache_limit),
aec172
                     KVADDR, &limit, sizeof(int),
aec172
-                    "array cache limit", RETURN_ON_ERROR))
aec172
-			goto bail_out;
aec172
+                    "array cache limit", RETURN_ON_ERROR)) {
aec172
+			error(INFO, 
aec172
+			    "kmem_cache: %lx: invalid array_cache pointer: %lx\n",
aec172
+				cache, cpudata[i]);
aec172
+			mark_bad_slab_cache(cache);
aec172
+			return max_limit;
aec172
+		}
aec172
 		if (CRASHDEBUG(3))
aec172
 			fprintf(fp, "  array limit[%d]: %d\n", i, limit);
aec172
                 if (limit > max_limit)
aec172
@@ -9232,6 +9496,11 @@ dump_kmem_cache_percpu_v2(struct meminfo
aec172
                         goto next_cache;
aec172
                 }
aec172
 
aec172
+		if (bad_slab_cache(si->cache)) {
aec172
+                        fprintf(fp, "%lx %-18s [INVALID/CORRUPTED]\n", si->cache, buf);
aec172
+                        goto next_cache;
aec172
+		}
aec172
+
aec172
 		si->curname = buf;
aec172
 
aec172
 	        readmem(si->cache+OFFSET(kmem_cache_s_objsize),
aec172
@@ -9264,7 +9533,7 @@ dump_kmem_cache_percpu_v2(struct meminfo
aec172
                 	"kmem_cache_s num", FAULT_ON_ERROR);
aec172
 		si->c_num = (ulong)tmp_val;
aec172
 
aec172
-		if( vt->flags & PERCPU_KMALLOC_V2_NODES )
aec172
+		if (vt->flags & PERCPU_KMALLOC_V2_NODES)
aec172
 			do_slab_chain_percpu_v2_nodes(SLAB_GET_COUNTS, si);
aec172
 		else
aec172
 			do_slab_chain_percpu_v2(SLAB_GET_COUNTS, si);
aec172
@@ -10160,22 +10429,22 @@ do_slab_chain_percpu_v2_nodes(long cmd,
aec172
 				if (!slab_chains[s])
aec172
 					continue;
aec172
 
aec172
-	        	if (!specified_slab) {
aec172
-	                	if (!readmem(slab_chains[s],
aec172
-	       	                    KVADDR, &si->slab, sizeof(ulong),
aec172
-	               	            "slabs", QUIET|RETURN_ON_ERROR)) {
aec172
-                               	        error(INFO,
aec172
-	                                        "%s: %s list: bad slab pointer: %lx\n",
aec172
-                                                si->curname,
aec172
-						slab_chain_name_v2[s],
aec172
-                       	                        slab_chains[s]);
aec172
-						list_borked = 1;
aec172
-						continue;
aec172
+				if (!specified_slab) {
aec172
+					if (!readmem(slab_chains[s],
aec172
+					    KVADDR, &si->slab, sizeof(ulong),
aec172
+					    "slabs", QUIET|RETURN_ON_ERROR)) {
aec172
+						error(INFO, "%s: %s list: "
aec172
+						    "bad slab pointer: %lx\n",
aec172
+							si->curname,
aec172
+							slab_chain_name_v2[s],
aec172
+							slab_chains[s]);
aec172
+							list_borked = 1;
aec172
+							continue;
aec172
 					}
aec172
 					last = slab_chains[s];
aec172
 				} else
aec172
 					last = 0;
aec172
-			
aec172
+
aec172
 				if (si->slab == slab_chains[s])
aec172
 					continue;
aec172
 				
aec172
@@ -11709,6 +11978,8 @@ dump_vm_table(int verbose)
aec172
 		fprintf(fp, "%sVM_EVENT", others++ ? "|" : "");\
aec172
 	if (vt->flags & PGCNT_ADJ)
aec172
 		fprintf(fp, "%sPGCNT_ADJ", others++ ? "|" : "");\
aec172
+	if (vt->flags & PAGEFLAGS)
aec172
+		fprintf(fp, "%sPAGEFLAGS", others++ ? "|" : "");\
aec172
 	if (vt->flags & SWAPINFO_V1)
aec172
 		fprintf(fp, "%sSWAPINFO_V1", others++ ? "|" : "");\
aec172
 	if (vt->flags & SWAPINFO_V2)
aec172
@@ -11747,10 +12018,15 @@ dump_vm_table(int verbose)
aec172
 	fprintf(fp, "   kmem_cache_count: %ld\n", vt->kmem_cache_count);
aec172
 	fprintf(fp, " kmem_cache_namelen: %d\n", vt->kmem_cache_namelen);
aec172
 	fprintf(fp, "kmem_cache_len_nodes: %ld\n", vt->kmem_cache_len_nodes);
aec172
-	fprintf(fp, "        PG_reserved: %lx\n", vt->PG_reserved);
aec172
-	fprintf(fp, "            PG_slab: %ld (%lx)\n", vt->PG_slab, 
aec172
-		(ulong)1 << vt->PG_slab);
aec172
-	fprintf(fp, "  PG_head_tail_mask: %lx\n", vt->PG_head_tail_mask);
aec172
+	fprintf(fp, " nr_bad_slab_caches: %d\n", vt->nr_bad_slab_caches);
aec172
+	if (!vt->nr_bad_slab_caches)
aec172
+		fprintf(fp, "    bad_slab_caches: (unused)\n");
aec172
+	else {
aec172
+		for (i = 0; i < vt->nr_bad_slab_caches; i++) {
aec172
+			fprintf(fp, " bad_slab_caches[%d]: %lx\n", 
aec172
+				i, vt->bad_slab_caches[i]);
aec172
+		}
aec172
+	}
aec172
 	fprintf(fp, "        paddr_prlen: %d\n", vt->paddr_prlen);
aec172
 	fprintf(fp, "           numnodes: %d\n", vt->numnodes);
aec172
 	fprintf(fp, "           nr_zones: %d\n", vt->nr_zones);
aec172
@@ -11824,6 +12100,21 @@ dump_vm_table(int verbose)
aec172
 	for (i = 0; i < vt->nr_vm_event_items; i++)
aec172
 		fprintf(fp, "        [%d] %s\n", i, vt->vm_event_items[i]);
aec172
 
aec172
+        fprintf(fp, "        PG_reserved: %lx\n", vt->PG_reserved);
aec172
+        fprintf(fp, "            PG_slab: %ld (%lx)\n", vt->PG_slab,
aec172
+                (ulong)1 << vt->PG_slab);
aec172
+        fprintf(fp, "  PG_head_tail_mask: %lx\n", vt->PG_head_tail_mask);
aec172
+
aec172
+	fprintf(fp, "       nr_pageflags: %d\n", vt->nr_pageflags);
aec172
+	fprintf(fp, "     pageflags_data: %s\n",
aec172
+		vt->nr_pageflags ? "" : "(not used)");
aec172
+	for (i = 0; i < vt->nr_pageflags; i++) {
aec172
+		fprintf(fp, "        %s[%d] %08lx: %s\n", 
aec172
+			i < 10 ? " " : "", i, 
aec172
+			vt->pageflags_data[i].mask,
aec172
+			vt->pageflags_data[i].name);
aec172
+	}
aec172
+
aec172
 	dump_vma_cache(VERBOSE);
aec172
 }
aec172
 
aec172
--- crash-7.0.2/filesys.c	2013-10-25 15:28:55.920879569 -0400
aec172
+++ crash-7.0.3/filesys.c	2013-10-25 10:09:39.568757187 -0400
aec172
@@ -727,8 +727,10 @@ get_proc_version(void)
aec172
                 return FALSE;
aec172
 
aec172
         if (fread(&kt->proc_version, sizeof(char), 
aec172
-	    	BUFSIZE-1, version) <= 0) 
aec172
+	    	BUFSIZE-1, version) <= 0) {
aec172
+		fclose(version);
aec172
                 return FALSE;
aec172
+	}
aec172
         
aec172
         fclose(version);
aec172
 
aec172
--- crash-7.0.2/help.c	2013-10-25 15:28:55.954879567 -0400
aec172
+++ crash-7.0.3/help.c	2013-10-24 15:32:58.495826737 -0400
aec172
@@ -1083,10 +1083,16 @@ NULL
aec172
 char *help_p[] = {
aec172
 "p",
aec172
 "print the value of an expression",
aec172
-"[-x|-d][-u] expression",
aec172
+"[-x|-d][-u] [expression | symbol[:cpuspec]]",
aec172
 "  This command passes its arguments on to gdb \"print\" command for evaluation.",
aec172
 "",
aec172
-"    expression   The expression to be evaluated.",
aec172
+"    expression  an expression to be evaluated.",
aec172
+"        symbol  a kernel symbol.",
aec172
+"      :cpuspec  CPU specification for a per-cpu symbol:",
aec172
+"                  :             CPU of the currently selected task.",
aec172
+"                  :a[ll]        all CPUs.",
aec172
+"                  :#[-#][,...]  CPU list(s), e.g. \"1,3,5\", \"1-3\",",
aec172
+"                                or \"1,3,5-7,10\".",
aec172
 "            -x  override default output format with hexadecimal format.",
aec172
 "            -d  override default output format with decimal format.",
aec172
 "            -u  the expression evaluates to a user address reference.", 
aec172
@@ -1144,6 +1150,39 @@ char *help_p[] = {
aec172
 "      swap_address = 0x0, ",
aec172
 "      segments = 0x0",
aec172
 "    }",
aec172
+"",
aec172
+"  If a per-cpu symbol is entered as a argument, its data type",
aec172
+"  and all of its per-cpu addresses are displayed:",
aec172
+" ",
aec172
+"    %s> p irq_stat",
aec172
+"    PER-CPU DATA TYPE:",
aec172
+"      irq_cpustat_t irq_stat;",
aec172
+"    PER-CPU ADDRESSES:",
aec172
+"      [0]: ffff88021e211540",
aec172
+"      [1]: ffff88021e251540",
aec172
+"      [2]: ffff88021e291540",
aec172
+"      [3]: ffff88021e2d1540",
aec172
+" ",
aec172
+"  To display the contents a per-cpu symbol for CPU 1, append",
aec172
+"  a cpu-specifier:",
aec172
+" ",
aec172
+"    %s> p irq_stat:1",
aec172
+"    per_cpu(irq_stat, 1) = $29 = {",
aec172
+"      __softirq_pending = 0, ",
aec172
+"      __nmi_count = 209034, ",
aec172
+"      apic_timer_irqs = 597509876, ",
aec172
+"      irq_spurious_count = 0, ",
aec172
+"      icr_read_retry_count = 2, ",
aec172
+"      x86_platform_ipis = 0, ",
aec172
+"      apic_perf_irqs = 209034, ",
aec172
+"      apic_irq_work_irqs = 0, ",
aec172
+"      irq_resched_count = 264922233, ",
aec172
+"      irq_call_count = 7036692, ",
aec172
+"      irq_tlb_count = 4750442, ",
aec172
+"      irq_thermal_count = 0, ",
aec172
+"      irq_threshold_count = 0",
aec172
+"    }",
aec172
+" ",
aec172
 NULL               
aec172
 };
aec172
 
aec172
@@ -2841,7 +2880,7 @@ char *help_irq[] = {
aec172
 "            irq stats of all cpus will be displayed.",
aec172
 "   -c cpu   only usable with the -s option, dump the irq stats of the ",
aec172
 "            specified cpu[s]; cpu can be specified as \"1,3,5\", \"1-3\",",
aec172
-"            or \"1,3,5-7,10\".",
aec172
+"            \"1,3,5-7,10\", \"all\", or \"a\" (shortcut for \"all\").",
aec172
 "\nEXAMPLES",
aec172
 "  Display the relevant data for IRQ 18 from a pre-2.6.37 kernel:\n", 
aec172
 "    %s> irq 18",
aec172
@@ -4092,8 +4131,8 @@ NULL
aec172
 char *help_struct[] = {
aec172
 "struct",
aec172
 "structure contents",
aec172
-"struct_name[.member[,member]][-o][-l offset][-rfuxdp][address | symbol]\n"
aec172
-"         [count | -c count]",
aec172
+"struct_name[.member[,member]][-o][-l offset][-rfuxdp]\n"
aec172
+"         [address | symbol][:cpuspec] [count | -c count]",
aec172
 "  This command displays either a structure definition, or a formatted display",
aec172
 "  of the contents of a structure at a specified address.  When no address is",
aec172
 "  specified, the structure definition is shown along with the structure size.",
aec172
@@ -4127,6 +4166,11 @@ char *help_struct[] = {
aec172
 "                 to an embedded list_head structure contained within the",
aec172
 "                 target data structure, then the \"-l\" option must be used.",
aec172
 "         symbol  symbolic reference to the address of a structure.",
aec172
+"       :cpuspec  CPU specification for a per-cpu address or symbol:",
aec172
+"                   :             CPU of the currently selected task.",
aec172
+"                   :a[ll]        all CPUs.",
aec172
+"                   :#[-#][,...]  CPU list(s), e.g. \"1,3,5\", \"1-3\",",
aec172
+"                                 or \"1,3,5-7,10\".",
aec172
 "          count  count of structures to dump from an array of structures;",
aec172
 "                 if used, this must be the last argument entered.",
aec172
 "       -c count  \"-c\" is only required if \"count\" is not the last argument",
aec172
@@ -4363,6 +4407,59 @@ char *help_struct[] = {
aec172
 "      [ffff8100145d20b8] struct list_head run_list;",
aec172
 "      [ffff8100145d20c8] struct prio_array *array;",
aec172
 "    ...",
aec172
+" ",
aec172
+"  For an example of displaying per-cpu variables, consider the",
aec172
+"  struct hd_struct.dkstats member, which is a percpu pointer to",
aec172
+"  a disk_stats structure:",
aec172
+"",
aec172
+"    %s> struct hd_struct.dkstats ",
aec172
+"    struct hd_struct {",
aec172
+"      [1232] struct disk_stats *dkstats;",
aec172
+"    }",
aec172
+"",
aec172
+" Taking an hd_struct at address ffff8802450e2848, display all",
aec172
+" of the per-cpu disk_stats structures that it references:",
aec172
+" ",
aec172
+"    %s> struct hd_struct.dkstats ffff8802450e2848",
aec172
+"      dkstats = 0x60fdb48026c8",
aec172
+"    %s> struct disk_stats 0x60fdb48026c8:a",
aec172
+"    [0]: ffffe8fefe6026c8",
aec172
+"    struct disk_stats {",
aec172
+"      sectors = {451376, 80468}, ",
aec172
+"      ios = {6041, 971}, ",
aec172
+"      merges = {386, 390}, ",
aec172
+"      ticks = {194877, 56131}, ",
aec172
+"      io_ticks = 12371, ",
aec172
+"      time_in_queue = 309163",
aec172
+"    }",
aec172
+"    [1]: ffffe8fefe8026c8",
aec172
+"    struct disk_stats {",
aec172
+"      sectors = {0, 0}, ",
aec172
+"      ios = {0, 0}, ",
aec172
+"      merges = {7, 242}, ",
aec172
+"      ticks = {0, 0}, ",
aec172
+"      io_ticks = 23, ",
aec172
+"      time_in_queue = 581",
aec172
+"    }",
aec172
+"    [2]: ffffe8fefea026c8",
aec172
+"    struct disk_stats {",
aec172
+"      sectors = {0, 0}, ",
aec172
+"      ios = {0, 0}, ",
aec172
+"      merges = {4, 112}, ",
aec172
+"      ticks = {0, 0}, ",
aec172
+"      io_ticks = 11, ",
aec172
+"      time_in_queue = 305",
aec172
+"    }",
aec172
+"    [3]: ffffe8fefec026c8",
aec172
+"    struct disk_stats {",
aec172
+"      sectors = {0, 0}, ",
aec172
+"      ios = {0, 0}, ",
aec172
+"      merges = {5, 54}, ",
aec172
+"      ticks = {0, 0}, ",
aec172
+"      io_ticks = 17, ",
aec172
+"      time_in_queue = 41",
aec172
+"    }",
aec172
+" ",
aec172
 "\nNOTE",
aec172
 "  If the structure name does not conflict with any %s command name, the",
aec172
 "  \"struct\" command may be dropped.  Accordingly, the examples above could",
aec172
@@ -4382,8 +4479,8 @@ NULL
aec172
 char *help_union[] = {
aec172
 "union",
aec172
 "union contents",
aec172
-"union_name[.member[,member]] [-o][-l offset][-rfuxdp] [address | symbol]\n"
aec172
-"                                     [count | -c count]",
aec172
+"union_name[.member[,member]] [-o][-l offset][-rfuxdp]\n"
aec172
+"         [address | symbol][:cpuspec] [count | -c count]",
aec172
 "  This command displays either a union definition, or a formatted display",
aec172
 "  of the contents of a union at a specified address.  When no address is",
aec172
 "  specified, the union definition is shown along with the union size.",
aec172
@@ -4418,6 +4515,11 @@ char *help_union[] = {
aec172
 "                 to an embedded list_head structure contained within the",
aec172
 "                 target union structure, then the \"-l\" option must be used.",
aec172
 "         symbol  symbolic reference to the address of a union.",
aec172
+"       :cpuspec  CPU specification for a per-cpu address or symbol:",
aec172
+"                   :             CPU of the currently selected task.",
aec172
+"                   :a[ll]        all CPUs.",
aec172
+"                   :#[-#][,...]  CPU list(s), e.g. \"1,3,5\", \"1-3\",",
aec172
+"                                or \"1,3,5-7,10\".",
aec172
 "          count  count of unions to dump from an array of unions; if used,",
aec172
 "                 this must be the last argument entered.",
aec172
 "       -c count  \"-c\" is only required if \"count\" is not the last argument",
aec172
@@ -5433,30 +5535,26 @@ char *help_kmem[] = {
aec172
 " ",
aec172
 "  Dump the mem_map[] array:\n",
aec172
 "    %s> kmem -p",
aec172
-"          PAGE       PHYSICAL      MAPPING       INDEX CNT FLAGS",
aec172
-"    ffffea0000000000        0                0        0  0 0",
aec172
-"    ffffea0000000038     1000                0        0  1 400",
aec172
-"    ffffea0000000070     2000                0        0  1 400",
aec172
-"    ffffea00000000a8     3000                0        0  1 400",
aec172
-"    ffffea00000000e0     4000                0        0  1 400",
aec172
-"    ffffea0000000118     5000                0        0  1 400",
aec172
-"    ffffea0000000150     6000                0        0  1 400",
aec172
-"    ffffea0000000188     7000                0        0  1 80",
aec172
-"    ffffea00000001c0     8000                0        0  1 400",
aec172
-"    ffffea00000001f8     9000                0        0  1 80",
aec172
-"    ffffea0000000230     a000                0        0  1 80",
aec172
-"    ffffea0000000268     b000 ffff880012d9bd68     695b  1 2002c",
aec172
-"    ffffea00000002a0     c000                0        0  1 80",
aec172
-"    ffffea00000002d8     d000 ffff88002a9ee210        9  1 2002c",
aec172
-"    ffffea0000000310     e000 ffff880010b265d8      33c  1 2002c",
aec172
-"    ffffea0000000348     f000 ffff88001404dd68      2d1  2 868",
aec172
-"    ffffea0000000380    10000 ffff88001404dd68      2d6  2 868",
aec172
-"    ffffea00000003b8    11000 ffff88001404dd68      2d7  2 868",
aec172
-"    ffffea00000003f0    12000 ffff88001404dd68      2d8  2 868",
aec172
-"    ffffea0000000428    13000 ffff88001404dd68      2d9  2 868",
aec172
-"    ffffea0000000460    14000 ffff88001404dd68      2da  2 868",
aec172
-"    ffffea0000000498    15000 ffff88001404dd68      2db  2 868",
aec172
-"    ffffea00000004d0    16000 ffff88001404dd68      2dc  2 868",
aec172
+"      PAGE    PHYSICAL   MAPPING    INDEX CNT FLAGS",
aec172
+"    f5c51200     10000         0         0  1 80 slab",
aec172
+"    f5c51220     11000         0         0  1 80 slab",
aec172
+"    f5c51240     12000         0         0  1 80 slab",
aec172
+"    f5c51260     13000         0         0  1 80 slab",
aec172
+"    f5c51280     14000         0         0  1 80 slab",
aec172
+"    f5c512a0     15000         0         0  1 80 slab",
aec172
+"    f5c512c0     16000         0         0  1 80 slab",
aec172
+"    f5c512e0     17000         0         0  1 80 slab",
aec172
+"    f5c51300     18000         0         0  1 80 slab",
aec172
+"    f5c51320     19000         0         0  1 80 slab",
aec172
+"    f5c51340     1a000         0         0  1 80 slab",
aec172
+"    f5c51360     1b000         0         0  1 80 slab",
aec172
+"    f5c51380     1c000  e6c6a754     13b67  2 868 uptodate,lru,active,private",
aec172
+"    f5c513a0     1d000         0         0  1 80 slab",
aec172
+"    f5c513c0     1e000         0         0  1 80 slab",
aec172
+"    f5c513e0     1f000         0         0  1 80 slab",
aec172
+"    f5c51400     20000  e6c6a754     13bbb  2 868 uptodate,lru,active,private",
aec172
+"    f5c51420     21000         0         0  1 80 slab",
aec172
+"    f5c51440     22000         0         0  1 80 slab",
aec172
 "    ...",
aec172
 "    ",
aec172
 "  Use the commands above with a page pointer or a physical address argument:\n",
aec172
@@ -5469,12 +5567,14 @@ char *help_kmem[] = {
aec172
 "      2    16k      c02eb01c      ",
aec172
 "    c40425b0  (c40425b0 is 1st of 4 pages) ",
aec172
 " ",
aec172
-"    %s> kmem -p c035de00",
aec172
-"      PAGE    PHYSICAL   INODE     OFFSET  CNT FLAGS",
aec172
-"    c035de00   50c0000         0    129000  0  uptodate\n",
aec172
-"    %s> kmem -p 50c0000",
aec172
-"      PAGE    PHYSICAL   INODE     OFFSET  CNT FLAGS",
aec172
-"    c035de00   50c0000         0    129000  0  uptodate\n",
aec172
+"    %s> kmem -p c25a9c00",
aec172
+"      PAGE     PHYSICAL   MAPPING    INDEX CNT FLAGS",
aec172
+"    c25a9c00    1fe0000  f429d2e4   21fe3eb  2 800828 uptodate,lru,private",
aec172
+" ",
aec172
+"    %s> kmem -p 1fe0000",
aec172
+"      PAGE     PHYSICAL   MAPPING    INDEX CNT FLAGS",
aec172
+"    c25a9c00    1fe0000  f429d2e4   21fe3eb  2 800828 uptodate,lru,private",
aec172
+" ",
aec172
 "  Display the mapped memory regions allocated by vmalloc():\n",
aec172
 "    %s> kmem -v",
aec172
 "    VMAP_AREA  VM_STRUCT     ADDRESS RANGE        SIZE",
aec172
--- crash-7.0.2/task.c	2013-10-25 15:28:55.949879567 -0400
aec172
+++ crash-7.0.3/task.c	2013-10-17 14:42:50.532672513 -0400
aec172
@@ -474,7 +474,7 @@ task_init(void)
aec172
 		tt->this_task = pid_to_task(active_pid);
aec172
 	}
aec172
 	else {
aec172
-		if (KDUMP_DUMPFILE())
aec172
+		if (KDUMP_DUMPFILE() && !(pc->flags2 & QEMU_MEM_DUMP))
aec172
 			map_cpus_to_prstatus();
aec172
 		else if (ELF_NOTES_VALID() && DISKDUMP_DUMPFILE())
aec172
 			map_cpus_to_prstatus_kdump_cmprs();
aec172
@@ -4873,10 +4873,10 @@ task_mm(ulong task, int fill)
aec172
 char *
aec172
 task_cpu(int processor, char *buf, int verbose)
aec172
 {
aec172
-	if (processor < NO_PROC_ID)
aec172
+	if (processor < NR_CPUS)
aec172
 		sprintf(buf, "%d", processor);
aec172
-	if (processor == NO_PROC_ID)
aec172
-		sprintf(buf, verbose ? "NO_PROC_ID" : "-");
aec172
+	else
aec172
+		sprintf(buf, verbose ? "(unknown)" : "?");
aec172
 
aec172
         return buf;
aec172
 }
aec172
--- crash-7.0.2/kernel.c	2013-10-25 15:28:55.958879567 -0400
aec172
+++ crash-7.0.3/kernel.c	2013-10-25 10:13:04.143747815 -0400
aec172
@@ -5377,7 +5377,6 @@ cmd_irq(void)
aec172
         int i, c;
aec172
 	int nr_irqs;
aec172
 	ulong *cpus;
aec172
-	int len;
aec172
 	int show_intr, choose_cpu;
aec172
 	char buf[10];
aec172
 	char arg_buf[BUFSIZE];
aec172
@@ -5485,9 +5484,7 @@ cmd_irq(void)
aec172
 		error(FATAL, "cannot determine number of IRQs\n");
aec172
 
aec172
 	if (show_intr) {
aec172
-		if ((len = STRUCT_SIZE("cpumask_t")) < 0)
aec172
-			len = DIV_ROUND_UP(kt->cpus, BITS_PER_LONG) * sizeof(ulong);
aec172
-		cpus = (ulong *)GETBUF(len);
aec172
+		cpus = get_cpumask_buf();
aec172
 
aec172
 		if (choose_cpu) {
aec172
 			make_cpumask(arg_buf, cpus, FAULT_ON_ERROR, NULL);
aec172
@@ -5648,6 +5645,7 @@ generic_dump_irq(int irq)
aec172
 	ulong tmp1, tmp2;
aec172
 
aec172
 	handler = UNINITIALIZED;
aec172
+	action = 0;
aec172
 	
aec172
 	irq_desc_addr = get_irq_desc_addr(irq);
aec172
 	if (!irq_desc_addr && symbol_exists("irq_desc_ptrs")) {
aec172
@@ -8398,6 +8396,7 @@ static void add_ikconfig_entry(char *lin
aec172
 static int setup_ikconfig(char *config)
aec172
 {
aec172
 	char *ent, *tokptr;
aec172
+	struct ikconfig_list *new;
aec172
 
aec172
 	ikconfig_all = calloc(1, sizeof(struct ikconfig_list) * IKCONFIG_MAX);
aec172
 	if (!ikconfig_all) {
aec172
@@ -8424,8 +8423,9 @@ static int setup_ikconfig(char *config)
aec172
 		free(ikconfig_all);
aec172
 		return 0;
aec172
 	}
aec172
-	ikconfig_all = realloc(ikconfig_all,
aec172
-			   sizeof(struct ikconfig_list) * kt->ikconfig_ents);
aec172
+	if ((new = realloc(ikconfig_all,
aec172
+	    sizeof(struct ikconfig_list) * kt->ikconfig_ents)))
aec172
+		ikconfig_all = new;
aec172
 
aec172
 	return 1;
aec172
 }
aec172
--- crash-7.0.2/gdb_interface.c	2013-10-25 15:28:55.936879568 -0400
aec172
+++ crash-7.0.3/gdb_interface.c	2013-10-15 15:55:20.440389792 -0400
aec172
@@ -357,8 +357,8 @@ gdb_interface(struct gnu_request *req)
aec172
 		restart(0);
aec172
 
aec172
 	if (!req->fp) {
aec172
-		req->fp = pc->flags & RUNTIME ? fp : 
aec172
-			  CRASHDEBUG(1) ? fp : pc->nullfp;
aec172
+		req->fp = ((pc->flags & RUNTIME) || (pc->flags2 & ALLOW_FP)) ? 
aec172
+			fp : CRASHDEBUG(1) ? fp : pc->nullfp;
aec172
 	}
aec172
 
aec172
 	pc->cur_req = req;
aec172
--- crash-7.0.2/configure.c	2013-10-25 15:28:55.956879567 -0400
aec172
+++ crash-7.0.3/configure.c	2013-10-25 10:09:47.567756821 -0400
aec172
@@ -790,7 +790,7 @@ make_rh_rpm_package(char *package, int r
aec172
 				break;
aec172
 			} 
aec172
 		}
aec172
-		fclose(fp);
aec172
+		pclose(fp);
aec172
 	
aec172
 		if (!cur) {
aec172
 			fprintf(stderr, "cannot get version from \"crash -v\"\n");
aec172
--- crash-7.0.2/net.c	2013-10-25 15:28:55.923879569 -0400
aec172
+++ crash-7.0.3/net.c	2013-10-22 09:42:52.103705675 -0400
aec172
@@ -1,8 +1,8 @@
aec172
 /* net.c - core analysis suite
aec172
  *
aec172
  * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc.
aec172
- * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 David Anderson
aec172
- * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Red Hat, Inc. All rights reserved.
aec172
+ * Copyright (C) 2002-2013 David Anderson
aec172
+ * Copyright (C) 2002-2013 Red Hat, Inc. All rights reserved.
aec172
  *
aec172
  * This program is free software; you can redistribute it and/or modify
aec172
  * it under the terms of the GNU General Public License as published by
aec172
@@ -231,10 +231,22 @@ net_init(void)
aec172
 				} else if ((MEMBER_OFFSET("inet_sock", "sk") == 0) &&
aec172
 				    (MEMBER_OFFSET("sock", "__sk_common") == 0)) {
aec172
 					MEMBER_OFFSET_INIT(inet_opt_daddr, "sock_common", "skc_daddr");
aec172
+					if (INVALID_MEMBER(inet_opt_daddr))
aec172
+						ANON_MEMBER_OFFSET_INIT(inet_opt_daddr, "sock_common", 
aec172
+							"skc_daddr");
aec172
 					MEMBER_OFFSET_INIT(inet_opt_rcv_saddr, "sock_common", "skc_rcv_saddr");
aec172
+					if (INVALID_MEMBER(inet_opt_rcv_saddr))
aec172
+						ANON_MEMBER_OFFSET_INIT(inet_opt_rcv_saddr, "sock_common",
aec172
+							"skc_rcv_saddr");
aec172
 					MEMBER_OFFSET_INIT(inet_opt_dport, "inet_sock", "inet_dport");
aec172
+					if (INVALID_MEMBER(inet_opt_dport))
aec172
+						ANON_MEMBER_OFFSET_INIT(inet_opt_dport, "sock_common", 
aec172
+							"skc_dport");
aec172
 					MEMBER_OFFSET_INIT(inet_opt_sport, "inet_sock", "inet_sport");
aec172
 					MEMBER_OFFSET_INIT(inet_opt_num, "inet_sock", "inet_num");
aec172
+					if (INVALID_MEMBER(inet_opt_num))
aec172
+						ANON_MEMBER_OFFSET_INIT(inet_opt_num, "sock_common", 
aec172
+							"skc_num");
aec172
 				}
aec172
 			}	
aec172
 
aec172
--- crash-7.0.2/s390x.c	2013-10-25 15:28:55.928879568 -0400
aec172
+++ crash-7.0.3/s390x.c	2013-10-10 14:57:54.080339089 -0400
aec172
@@ -590,9 +590,12 @@ static int swap_entry(ulong entry)
aec172
 	if (THIS_KERNEL_VERSION < LINUX(2,6,19)) {
aec172
 		if ((entry & 0x601ULL) == 0x600ULL)
aec172
 			return 1;
aec172
-	} else {
aec172
+	} if (THIS_KERNEL_VERSION < LINUX(3,12,0)) {
aec172
 		if ((entry & 0x403ULL) == 0x403ULL)
aec172
 			return 1;
aec172
+	} else {
aec172
+		if ((entry & 0x603ULL) == 0x402ULL)
aec172
+			return 1;
aec172
 	}
aec172
 	return 0;
aec172
 }
aec172
--- crash-7.0.2/x86_64.c	2013-10-25 15:28:55.928879568 -0400
aec172
+++ crash-7.0.3/x86_64.c	2013-10-17 09:25:14.265545546 -0400
aec172
@@ -7251,6 +7251,9 @@ x86_64_get_framesize(struct bt_info *bt,
aec172
 		}
aec172
 	}
aec172
 
aec172
+	if ((sp->value >= kt->init_begin) && (sp->value < kt->init_end))
aec172
+		return 0;
aec172
+
aec172
 	framesize = max = 0;
aec172
         max_instructions = textaddr - sp->value; 
aec172
 	instr = arg = -1;
aec172
--- crash-7.0.2/remote.c	2013-10-25 15:28:55.935879568 -0400
aec172
+++ crash-7.0.3/remote.c	2013-10-25 10:09:51.680756632 -0400
aec172
@@ -1116,8 +1116,10 @@ daemon_proc_version(char *buf)
aec172
                 return FALSE;
aec172
 
aec172
         if (fread(buf, sizeof(char),
aec172
-                BUFSIZE-1, pipe) <= 0)
aec172
+                BUFSIZE-1, pipe) <= 0) {
aec172
+		pclose(pipe);
aec172
                 return FALSE;
aec172
+	}
aec172
 
aec172
         pclose(pipe);
aec172
 
aec172
--- crash-7.0.2/va_server.c	2013-10-25 15:28:55.939879568 -0400
aec172
+++ crash-7.0.3/va_server.c	2013-10-25 10:09:58.528756319 -0400
aec172
@@ -313,6 +313,7 @@ int read_map(char *crash_file)
aec172
 	ret = fseek(vas_file_p, (long)0, SEEK_SET);
aec172
 	if(ret == -1) {
aec172
 		printf("va_server: unable to fseek, err = %d\n", ferror(vas_file_p));
aec172
+		free(disk_hdr);
aec172
 		return -1;
aec172
 	}
aec172
 	items = fread((void *)disk_hdr, 1, Page_Size, vas_file_p);
aec172
--- crash-7.0.2/va_server_v1.c	2013-10-25 15:28:55.935879568 -0400
aec172
+++ crash-7.0.3/va_server_v1.c	2013-10-25 10:10:02.032756158 -0400
aec172
@@ -308,6 +308,7 @@ int read_map_v1(int blk_pos)
aec172
 	ret = fseek(vas_file_p, (long)(blk_pos*Page_Size), SEEK_SET);
aec172
 	if(ret == -1) {
aec172
 		console("va_server: unable to fseek, err = %d\n", ferror(vas_file_p));
aec172
+		free(disk_hdr);
aec172
 		return -1;
aec172
 	}
aec172
 	items = fread((void *)disk_hdr, 1, Page_Size, vas_file_p);
aec172
--- crash-7.0.2/symbols.c	2013-10-25 15:28:55.956879567 -0400
aec172
+++ crash-7.0.3/symbols.c	2013-10-24 15:33:12.359826102 -0400
aec172
@@ -72,7 +72,10 @@ struct elf_common;
aec172
 static void Elf32_Sym_to_common(Elf32_Sym *, struct elf_common *); 
aec172
 static void Elf64_Sym_to_common(Elf64_Sym *, struct elf_common *); 
aec172
 static void cmd_datatype_common(ulong);
aec172
-static int display_per_cpu_info(struct syment *);
aec172
+static void do_datatype_addr(struct datatype_member *, ulong, int,
aec172
+			     ulong, char **, int);
aec172
+static void process_gdb_output(char *, unsigned, const char *, int);
aec172
+static int display_per_cpu_info(struct syment *, int, char *);
aec172
 static struct load_module *get_module_percpu_sym_owner(struct syment *);
aec172
 static int is_percpu_symbol(struct syment *);
aec172
 static void dump_percpu_symbols(struct load_module *);
aec172
@@ -116,6 +119,8 @@ static int show_member_offset(FILE *, st
aec172
 #define IN_STRUCT      (0x40000)
aec172
 #define DATATYPE_QUERY (0x80000)
aec172
 #define ANON_MEMBER_QUERY (0x100000)
aec172
+#define SHOW_RAW_DATA     (0x200000)
aec172
+#define DEREF_POINTERS    (0x400000)
aec172
 
aec172
 #define INTEGER_TYPE    (UINT8|INT8|UINT16|INT16|UINT32|INT32|UINT64|INT64)
aec172
 
aec172
@@ -132,6 +137,7 @@ static void dump_datatype_flags(ulong, F
aec172
 static long anon_member_offset(char *, char *);
aec172
 static int gdb_whatis(char *);
aec172
 static void do_datatype_declaration(struct datatype_member *, ulong);
aec172
+static int member_to_datatype(char *, struct datatype_member *, ulong);
aec172
 
aec172
 #define DEBUGINFO_ERROR_MESSAGE1 \
aec172
 "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"
aec172
@@ -5704,13 +5710,13 @@ dereference_pointer(ulong addr, struct d
aec172
 static void 
aec172
 cmd_datatype_common(ulong flags)
aec172
 {
aec172
-	int i, c;
aec172
+	int c;
aec172
 	ulong addr, aflag;
aec172
+	char *cpuspec;
aec172
+	ulong *cpus;
aec172
 	struct syment *sp;
aec172
-	int rawdata;
aec172
-	long len;
aec172
 	ulong list_head_offset;
aec172
-	int count, pflag;
aec172
+	int count;
aec172
 	int argc_members;
aec172
 	int optind_save;
aec172
 	unsigned int radix, restore_radix;
aec172
@@ -5721,19 +5727,19 @@ cmd_datatype_common(ulong flags)
aec172
 
aec172
         dm = &datatype_member;
aec172
 	count = 0xdeadbeef;
aec172
-	rawdata = 0;
aec172
 	aflag = addr = 0;
aec172
         list_head_offset = 0;
aec172
         argc_members = 0;
aec172
 	radix = restore_radix = 0;
aec172
 	separator = members = NULL;
aec172
-	pflag = 0;
aec172
+	cpuspec = NULL;
aec172
+	cpus = NULL;
aec172
 
aec172
         while ((c = getopt(argcnt, args, "pxdhfuc:rvol:")) != EOF) {
aec172
                 switch (c)
aec172
 		{
aec172
 		case 'p':
aec172
-			pflag++;
aec172
+			flags |= DEREF_POINTERS;
aec172
 			break;
aec172
 
aec172
 		case 'd':
aec172
@@ -5756,7 +5762,7 @@ cmd_datatype_common(ulong flags)
aec172
 			break;
aec172
 
aec172
 		case 'r':
aec172
-			rawdata = 1;
aec172
+			flags |= SHOW_RAW_DATA;
aec172
 			break;
aec172
 
aec172
 		case 'v':
aec172
@@ -5816,11 +5822,22 @@ cmd_datatype_common(ulong flags)
aec172
 		if (aflag && (count != 0xdeadbeef))
aec172
 			error(FATAL, "too many arguments!\n");
aec172
 
aec172
+		if (!aflag) {
aec172
+			cpuspec = strchr(args[optind], ':');
aec172
+			if (cpuspec)
aec172
+				*cpuspec++ = NULLCHAR;
aec172
+		}
aec172
+
aec172
 		if (clean_arg() && IS_A_NUMBER(args[optind])) { 
aec172
 			if (aflag) 
aec172
 				count = stol(args[optind], 
aec172
 					FAULT_ON_ERROR, NULL);
aec172
-			else {
aec172
+			else if (cpuspec) {
aec172
+				if (pc->curcmd_flags & MEMTYPE_FILEADDR)
aec172
+					error(FATAL, "-f option cannot be used with percpu\n");
aec172
+				addr = htol(args[optind], FAULT_ON_ERROR, NULL);
aec172
+				aflag++;
aec172
+			} else {
aec172
 				if (pc->curcmd_flags & MEMTYPE_FILEADDR)
aec172
 					pc->curcmd_private = stoll(args[optind], 
aec172
 						FAULT_ON_ERROR, NULL);
aec172
@@ -5835,6 +5852,12 @@ cmd_datatype_common(ulong flags)
aec172
 				aflag++;
aec172
 			}
aec172
 		} else if ((sp = symbol_search(args[optind]))) {
aec172
+			if (cpuspec && !is_percpu_symbol(sp)) {
aec172
+				error(WARNING,
aec172
+				      "%s is not percpu; cpuspec ignored.\n",
aec172
+				      sp->name);
aec172
+				cpuspec = NULL;
aec172
+			}
aec172
 	                addr = sp->value;
aec172
 			aflag++;
aec172
 	        } else {
aec172
@@ -5846,6 +5869,14 @@ cmd_datatype_common(ulong flags)
aec172
 		}
aec172
 	}
aec172
 
aec172
+	if (cpuspec) {
aec172
+		cpus = get_cpumask_buf();
aec172
+		if (STREQ(cpuspec, ""))
aec172
+			SET_BIT(cpus, CURRENT_CONTEXT()->processor);
aec172
+		else
aec172
+			make_cpumask(cpuspec, cpus, FAULT_ON_ERROR, NULL);
aec172
+	}
aec172
+
aec172
 	optind = optind_save;
aec172
 
aec172
 	if (count == 0xdeadbeef)
aec172
@@ -5853,7 +5884,7 @@ cmd_datatype_common(ulong flags)
aec172
 	else if (!aflag)
aec172
 		error(FATAL, "no kernel virtual address argument entered\n");
aec172
 
aec172
-	if (pflag && !aflag)
aec172
+	if ((flags & DEREF_POINTERS) && !aflag)
aec172
 		error(FATAL, "-p option requires address argument\n");
aec172
 
aec172
 	if (list_head_offset)
aec172
@@ -5878,6 +5909,15 @@ cmd_datatype_common(ulong flags)
aec172
 		DATATYPE_QUERY|ANON_MEMBER_QUERY|RETURN_ON_ERROR) < 1))
aec172
 		error(FATAL, "invalid data structure reference: %s\n", structname);
aec172
 
aec172
+	if (! (flags & (STRUCT_REQUEST|UNION_REQUEST)) ) {
aec172
+		flags |= dm->type;
aec172
+		if (!(flags & (UNION_REQUEST|STRUCT_REQUEST)))
aec172
+			error(FATAL, "invalid argument");
aec172
+	} else if ( (flags &(STRUCT_REQUEST|UNION_REQUEST)) != dm->type) {
aec172
+		error(FATAL, "data type mismatch: %s is not a %s\n",
aec172
+		      dm->name, flags & UNION_REQUEST ? "union" : "struct");
aec172
+	}
aec172
+
aec172
         if ((argc_members > 1) && !aflag) {
aec172
                 error(INFO, flags & SHOW_OFFSET ? 
aec172
 		    "-o option not valid with multiple member format\n" :
aec172
@@ -5891,7 +5931,52 @@ cmd_datatype_common(ulong flags)
aec172
 		error(FATAL, 
aec172
 		    "-o option not valid with multiple member format\n");
aec172
 
aec172
-	len = dm->size;
aec172
+	set_temporary_radix(radix, &restore_radix);
aec172
+
aec172
+	/*
aec172
+	 *  No address was passed -- dump the structure/member declaration.
aec172
+	 */
aec172
+	if (!aflag) {
aec172
+		if (argc_members &&
aec172
+		    !member_to_datatype(memberlist[0], dm,
aec172
+					ANON_MEMBER_QUERY))
aec172
+			error(FATAL, "invalid data structure reference: %s.%s\n",
aec172
+			      dm->name, memberlist[0]);
aec172
+		do_datatype_declaration(dm, flags | (dm->flags & TYPEDEF));
aec172
+	} else if (cpus) {
aec172
+		for (c = 0; c < kt->cpus; c++) {
aec172
+			ulong cpuaddr;
aec172
+
aec172
+			if (!NUM_IN_BITMAP(cpus, c))
aec172
+				continue;
aec172
+
aec172
+			cpuaddr = addr + kt->__per_cpu_offset[c];
aec172
+			fprintf(fp, "[%d]: %lx\n", c, cpuaddr);
aec172
+			do_datatype_addr(dm, cpuaddr , count,
aec172
+					 flags, memberlist, argc_members);
aec172
+		}
aec172
+	} else
aec172
+		do_datatype_addr(dm, addr, count, flags,
aec172
+				 memberlist, argc_members);
aec172
+
aec172
+	restore_current_radix(restore_radix);
aec172
+
aec172
+freebuf:
aec172
+        if (argc_members) {
aec172
+                FREEBUF(structname);
aec172
+                FREEBUF(members);
aec172
+	}
aec172
+
aec172
+	if (cpus)
aec172
+		FREEBUF(cpus);
aec172
+}
aec172
+
aec172
+static void
aec172
+do_datatype_addr(struct datatype_member *dm, ulong addr, int count,
aec172
+		 ulong flags, char **memberlist, int argc_members)
aec172
+{
aec172
+	int i, c;
aec172
+	long len = dm->size;
aec172
 
aec172
 	if (count < 0) {
aec172
 		addr -= len * abs(count);
aec172
@@ -5908,83 +5993,44 @@ cmd_datatype_common(ulong flags)
aec172
 		i = 0;
aec172
         	do {
aec172
                 	if (argc_members) {
aec172
-                        	*separator = '.';
aec172
-                        	strcpy(separator+1, memberlist[i]);
aec172
-			}
aec172
-
aec172
-			switch (arg_to_datatype(structname, dm,
aec172
-				ANON_MEMBER_QUERY|RETURN_ON_ERROR))
aec172
-			{
aec172
-			case 0: error(FATAL, "invalid data structure reference: %s\n", 
aec172
-					structname);
aec172
-				break;
aec172
-			case 1: break;
aec172
-			case 2: if (rawdata)
aec172
+				if (!member_to_datatype(memberlist[i], dm,
aec172
+							ANON_MEMBER_QUERY))
aec172
+					error(FATAL, "invalid data structure reference: %s.%s\n",
aec172
+					      dm->name, memberlist[i]);
aec172
+				if (flags & SHOW_RAW_DATA)
aec172
         				error(FATAL, 
aec172
-					    "member-specific output not allowed with -r\n");
aec172
-				break;
aec172
+					      "member-specific output not allowed with -r\n");
aec172
 			}
aec172
 
aec172
-			if (!(dm->flags & TYPEDEF)) {
aec172
-				if (flags &(STRUCT_REQUEST|UNION_REQUEST) ) {
aec172
-					if ((flags & (STRUCT_REQUEST|UNION_REQUEST)) != dm->type) 
aec172
-						goto freebuf;
aec172
-				} else
aec172
-					flags |= dm->type;
aec172
-			}
aec172
-
aec172
-			/* 
aec172
-	 		 *  No address was passed -- dump the structure/member declaration.
aec172
-	 		 */
aec172
-			if (!aflag || (aflag && (flags & SHOW_OFFSET))) {
aec172
-				if (aflag)
aec172
-					dm->vaddr = addr;
aec172
-				set_temporary_radix(radix, &restore_radix);
aec172
-				do_datatype_declaration(dm, flags | (dm->flags & TYPEDEF));
aec172
-				restore_current_radix(restore_radix);
aec172
-				goto freebuf;
aec172
-			}
aec172
-
aec172
-			if (!(flags & (UNION_REQUEST|STRUCT_REQUEST)))
aec172
-				error(FATAL, "invalid argument");
aec172
-
aec172
 			/*
aec172
-		 	 *  Display data.
aec172
+		 	 *  Display member addresses or data
aec172
 		 	 */
aec172
-			if (rawdata)
aec172
+			if (flags & SHOW_OFFSET) {
aec172
+				dm->vaddr = addr;
aec172
+				do_datatype_declaration(dm, flags | (dm->flags & TYPEDEF));
aec172
+			} else if (flags & SHOW_RAW_DATA)
aec172
 				raw_data_dump(addr, len, flags & STRUCT_VERBOSE);
aec172
-			else if (pflag && !dm->member) {
aec172
-				set_temporary_radix(radix, &restore_radix);
aec172
+			else if ((flags & DEREF_POINTERS) && !dm->member) {
aec172
 				print_struct_with_dereference(addr, dm, flags);
aec172
-				restore_current_radix(restore_radix);
aec172
                 	} else {
aec172
 	                        if (dm->member)
aec172
 	                                open_tmpfile();
aec172
 	
aec172
-				set_temporary_radix(radix, &restore_radix);
aec172
-
aec172
 				if (flags & UNION_REQUEST)
aec172
 					print_union(dm->name, addr);
aec172
 				else if (flags & STRUCT_REQUEST)
aec172
 					print_struct(dm->name, addr);
aec172
 
aec172
 				if (dm->member) {
aec172
-					if (!(pflag && 
aec172
+					if (!((flags & DEREF_POINTERS) &&
aec172
 				    	    dereference_pointer(addr, dm, flags)))
aec172
 						parse_for_member(dm, PARSE_FOR_DATA);
aec172
 					close_tmpfile();
aec172
 				}
aec172
 
aec172
-				restore_current_radix(restore_radix);
aec172
                 	}
aec172
 		} while (++i < argc_members);
aec172
         }
aec172
-
aec172
-freebuf:
aec172
-        if (argc_members) {
aec172
-                FREEBUF(structname);
aec172
-                FREEBUF(members);
aec172
-	}
aec172
 }
aec172
 
aec172
 
aec172
@@ -6108,13 +6154,7 @@ arg_to_datatype(char *s, struct datatype
aec172
 	if (!both) 
aec172
 		return 1;
aec172
 
aec172
-	dm->member = p1+1;
aec172
-
aec172
-	if ((dm->member_offset = MEMBER_OFFSET(dm->name, dm->member)) >= 0)
aec172
-		return 2;
aec172
-
aec172
-	if ((flags & ANON_MEMBER_QUERY) &&
aec172
-	    ((dm->member_offset = ANON_MEMBER_OFFSET(dm->name, dm->member)) >= 0))
aec172
+	if (member_to_datatype(p1 + 1, dm, flags))
aec172
 		return 2;
aec172
 
aec172
 datatype_member_fatal:
aec172
@@ -6137,6 +6177,21 @@ datatype_member_fatal:
aec172
        	return (error(FATAL, "invalid argument: %s\n", s));
aec172
 }
aec172
 
aec172
+static int
aec172
+member_to_datatype(char *s, struct datatype_member *dm, ulong flags)
aec172
+{
aec172
+	dm->member = s;
aec172
+
aec172
+	if ((dm->member_offset = MEMBER_OFFSET(dm->name, s)) >= 0)
aec172
+		return TRUE;
aec172
+
aec172
+	if ((flags & ANON_MEMBER_QUERY) &&
aec172
+	    ((dm->member_offset = ANON_MEMBER_OFFSET(dm->name, s)) >= 0))
aec172
+		return TRUE;
aec172
+
aec172
+	return FALSE;
aec172
+}
aec172
+
aec172
 /*
aec172
  *  debug routine -- not called on purpose by anybody.
aec172
  */
aec172
@@ -6388,13 +6443,12 @@ cmd_p(void)
aec172
 {
aec172
         int c;
aec172
 	struct syment *sp, *percpu_sp;
aec172
-	unsigned radix, restore_radix;
aec172
-	int leader, do_load_module_filter, success;
aec172
+	unsigned radix;
aec172
+	int do_load_module_filter;
aec172
 	char buf1[BUFSIZE]; 
aec172
-	char buf2[BUFSIZE]; 
aec172
-	char *p1;
aec172
+	char *cpuspec;
aec172
 
aec172
-	leader = do_load_module_filter = radix = restore_radix = 0;
aec172
+	do_load_module_filter = radix = 0;
aec172
 
aec172
         while ((c = getopt(argcnt, args, "dhxu")) != EOF) {
aec172
                 switch(c)
aec172
@@ -6427,33 +6481,57 @@ cmd_p(void)
aec172
         if (argerrs || !args[optind])
aec172
                 cmd_usage(pc->curcmd, SYNOPSIS);
aec172
 
aec172
+	cpuspec = strrchr(args[optind], ':');
aec172
+	if (cpuspec)
aec172
+		*cpuspec++ = NULLCHAR;
aec172
+
aec172
+	sp = NULL;
aec172
 	if ((sp = symbol_search(args[optind])) && !args[optind+1]) {
aec172
 		if ((percpu_sp = per_cpu_symbol_search(args[optind])) &&
aec172
-		    display_per_cpu_info(percpu_sp))
aec172
+		    display_per_cpu_info(percpu_sp, radix, cpuspec))
aec172
 			return;
aec172
-		sprintf(buf2, "%s = ", args[optind]);
aec172
-		leader = strlen(buf2);
aec172
 		if (module_symbol(sp->value, NULL, NULL, NULL, *gdb_output_radix))
aec172
 			do_load_module_filter = TRUE;
aec172
 	} else if ((percpu_sp = per_cpu_symbol_search(args[optind])) &&
aec172
-		   display_per_cpu_info(percpu_sp))
aec172
+		   display_per_cpu_info(percpu_sp, radix, cpuspec))
aec172
 		return;
aec172
 	else if (st->flags & LOAD_MODULE_SYMS)
aec172
 		do_load_module_filter = TRUE;
aec172
 
aec172
+	if (cpuspec) {
aec172
+		if (sp)
aec172
+			error(WARNING, "%s is not percpu; cpuspec ignored.\n",
aec172
+			      sp->name);
aec172
+		else
aec172
+			/* maybe a valid C expression (e.g. ':') */
aec172
+			*(cpuspec-1) = ':';
aec172
+	}
aec172
+
aec172
+	process_gdb_output(concat_args(buf1, 0, TRUE), radix,
aec172
+			   sp ? sp->name : NULL, do_load_module_filter);
aec172
+}
aec172
+
aec172
+static void
aec172
+process_gdb_output(char *gdb_request, unsigned radix,
aec172
+		   const char *leader, int do_load_module_filter)
aec172
+{
aec172
+	unsigned restore_radix;
aec172
+	int success;
aec172
+	char buf1[BUFSIZE]; 
aec172
+	char *p1;
aec172
+
aec172
 	if (leader || do_load_module_filter)
aec172
 		open_tmpfile();
aec172
 
aec172
 	set_temporary_radix(radix, &restore_radix);
aec172
 
aec172
-       	success = gdb_pass_through(concat_args(buf1, 0, TRUE), NULL, 
aec172
-		GNU_RETURN_ON_ERROR);
aec172
+       	success = gdb_pass_through(gdb_request, NULL, GNU_RETURN_ON_ERROR);
aec172
 
aec172
 	if (success && (leader || do_load_module_filter)) {
aec172
 		int firstline;
aec172
 
aec172
 		if (leader) {
aec172
-			fprintf(pc->saved_fp, "%s", buf2);
aec172
+			fprintf(pc->saved_fp, "%s = ", leader);
aec172
 			fflush(pc->saved_fp);
aec172
 		}
aec172
 
aec172
@@ -6482,8 +6560,41 @@ cmd_p(void)
aec172
 	restore_current_radix(restore_radix);
aec172
 
aec172
 	if (!success) 
aec172
-		error(FATAL, "gdb request failed: %s\n",
aec172
-			concat_args(buf1, 0, TRUE));
aec172
+		error(FATAL, "gdb request failed: %s\n", gdb_request);
aec172
+}
aec172
+
aec172
+/*
aec172
+ *  Get the type of an expression using gdb's "whatis" command.
aec172
+ *  The returned string is dynamically allocated, and it should
aec172
+ *  be passed to FREEBUF() when no longer needed.
aec172
+ *  Return NULL if the type cannot be determined.
aec172
+ */
aec172
+static char *
aec172
+expr_type_name(const char *expr)
aec172
+{
aec172
+	char buf[BUFSIZE], *p;
aec172
+
aec172
+	open_tmpfile();
aec172
+	sprintf(buf, "whatis %s", expr);
aec172
+	if (!gdb_pass_through(buf, fp, GNU_RETURN_ON_ERROR)) {
aec172
+		close_tmpfile();
aec172
+		return NULL;
aec172
+	}
aec172
+
aec172
+	rewind(pc->tmpfile);
aec172
+	while (fgets(buf, BUFSIZE, pc->tmpfile) && !STRNEQ(buf, "type = "))
aec172
+		;
aec172
+	p = feof(pc->tmpfile) ? NULL : buf + strlen("type = ");
aec172
+	close_tmpfile();
aec172
+
aec172
+	if (p) {
aec172
+		size_t len = strlen(clean_line(p));
aec172
+		/* GDB reports unknown types as <...descriptive text...> */
aec172
+		if (p[0] == '<' && p[len-1] == '>')
aec172
+			return NULL;
aec172
+		return strcpy(GETBUF(len + 1), p);
aec172
+	}
aec172
+	return NULL;
aec172
 }
aec172
 
aec172
 /*
aec172
@@ -6491,30 +6602,73 @@ cmd_p(void)
aec172
  *  the addresses of each its per-cpu instances.
aec172
  */
aec172
 static int
aec172
-display_per_cpu_info(struct syment *sp)
aec172
+display_per_cpu_info(struct syment *sp, int radix, char *cpuspec)
aec172
 {
aec172
+	ulong *cpus;
aec172
 	int c;
aec172
 	ulong addr;
aec172
 	char buf[BUFSIZE];
aec172
+	char leader[sizeof("&per_cpu(") + strlen(sp->name) +
aec172
+		    sizeof(", " STR(UINT_MAX) ")")];
aec172
+	char *typename;
aec172
+	int do_load_module_filter;
aec172
 
aec172
 	if (((kt->flags & (SMP|PER_CPU_OFF)) != (SMP|PER_CPU_OFF)) ||
aec172
 	    (!is_percpu_symbol(sp)) ||
aec172
 	    !((sp->type == 'd') || (sp->type == 'D') || (sp->type == 'V')))
aec172
 		return FALSE;
aec172
 
aec172
-	fprintf(fp, "PER-CPU DATA TYPE:\n  ");
aec172
-        sprintf(buf, "whatis %s", sp->name);
aec172
-        if (!gdb_pass_through(buf, pc->nullfp, GNU_RETURN_ON_ERROR))
aec172
-                fprintf(fp, "[undetermined type] %s;\n", sp->name);
aec172
-	else
aec172
-        	whatis_variable(sp);
aec172
+	if (cpuspec) {
aec172
+		cpus = get_cpumask_buf();
aec172
+		if (STREQ(cpuspec, ""))
aec172
+			SET_BIT(cpus, CURRENT_CONTEXT()->processor);
aec172
+		else
aec172
+			make_cpumask(cpuspec, cpus, FAULT_ON_ERROR, NULL);
aec172
+	} else
aec172
+		cpus = NULL;
aec172
+
aec172
+	typename = expr_type_name(sp->name);
aec172
+
aec172
+	if (!cpus) {
aec172
+		fprintf(fp, "PER-CPU DATA TYPE:\n  ");
aec172
+		if (!typename)
aec172
+			fprintf(fp, "[undetermined type] %s;\n", sp->name);
aec172
+		else
aec172
+			whatis_variable(sp);
aec172
+
aec172
+		fprintf(fp, "PER-CPU ADDRESSES:\n");
aec172
+	}
aec172
+
aec172
+	do_load_module_filter =
aec172
+		module_symbol(sp->value, NULL, NULL, NULL, *gdb_output_radix);
aec172
 
aec172
-	fprintf(fp, "PER-CPU ADDRESSES:\n");
aec172
 	for (c = 0; c < kt->cpus; c++) {
aec172
+		if (cpus && !NUM_IN_BITMAP(cpus, c))
aec172
+			continue;
aec172
 		addr = sp->value + kt->__per_cpu_offset[c];
aec172
-		fprintf(fp, "  [%d]: %lx\n", c, addr);
aec172
+		if (!cpus)
aec172
+			fprintf(fp, "  [%d]: %lx\n", c, addr);
aec172
+		else if (typename) {
aec172
+			snprintf(buf, sizeof buf, "p *(%s*) 0x%lx",
aec172
+				 typename, addr);
aec172
+			sprintf(leader, "per_cpu(%s, %u)",
aec172
+				sp->name, c);
aec172
+			process_gdb_output(buf, radix, leader,
aec172
+					   do_load_module_filter);
aec172
+		} else {
aec172
+			snprintf(buf, sizeof buf, "p (void*) 0x%lx", addr);
aec172
+			sprintf(leader, "&per_cpu(%s, %u)",
aec172
+				sp->name, c);
aec172
+			process_gdb_output(buf, radix, leader,
aec172
+					   do_load_module_filter);
aec172
+		}
aec172
 	}
aec172
 
aec172
+	if (typename)
aec172
+		FREEBUF(typename);
aec172
+	if (cpus)
aec172
+		FREEBUF(cpus);
aec172
+
aec172
 	return TRUE;
aec172
 }
aec172
 
aec172
@@ -6859,6 +7013,10 @@ dump_datatype_flags(ulong flags, FILE *o
aec172
 		fprintf(ofp, "%sDATATYPE_QUERY", others++ ? "|" : "");
aec172
 	if (flags & ANON_MEMBER_QUERY)
aec172
 		fprintf(ofp, "%sANON_MEMBER_QUERY", others++ ? "|" : "");
aec172
+	if (flags & SHOW_RAW_DATA)
aec172
+		fprintf(ofp, "%sSHOW_RAW_DATA", others++ ? "|" : "");
aec172
+	if (flags & DEREF_POINTERS)
aec172
+		fprintf(ofp, "%sDEREF_POINTERS", others++ ? "|" : "");
aec172
 	fprintf(ofp, ")\n");
aec172
 }
aec172
 
aec172
@@ -7890,11 +8048,18 @@ dump_offset_table(char *spec, ulong make
aec172
                 OFFSET(page_objects));
aec172
         fprintf(fp, "                     page_slab: %ld\n",
aec172
                 OFFSET(page_slab));
aec172
+        fprintf(fp, "                page_slab_page: %ld\n",
aec172
+                OFFSET(page_slab_page));
aec172
         fprintf(fp, "               page_first_page: %ld\n",
aec172
                 OFFSET(page_first_page));
aec172
         fprintf(fp, "                 page_freelist: %ld\n",
aec172
                 OFFSET(page_freelist));
aec172
 
aec172
+	fprintf(fp, "        trace_print_flags_mask: %ld\n",
aec172
+		OFFSET(trace_print_flags_mask));
aec172
+	fprintf(fp, "        trace_print_flags_name: %ld\n",
aec172
+		OFFSET(trace_print_flags_name));
aec172
+
aec172
         fprintf(fp, "    swap_info_struct_swap_file: %ld\n",
aec172
 		OFFSET(swap_info_struct_swap_file));
aec172
         fprintf(fp, "  swap_info_struct_swap_vfsmnt: %ld\n",
aec172
@@ -9021,6 +9186,7 @@ dump_offset_table(char *spec, ulong make
aec172
 	fprintf(fp, "\n                    size_table:\n");
aec172
 	fprintf(fp, "                          page: %ld\n", SIZE(page));
aec172
 	fprintf(fp, "                    page_flags: %ld\n", SIZE(page_flags));
aec172
+	fprintf(fp, "             trace_print_flags: %ld\n", SIZE(trace_print_flags));
aec172
         fprintf(fp, "              free_area_struct: %ld\n", 
aec172
 		SIZE(free_area_struct));
aec172
         fprintf(fp, "                     free_area: %ld\n", 
aec172
--- crash-7.0.2/diskdump.c	2013-10-25 15:28:55.941879568 -0400
aec172
+++ crash-7.0.3/diskdump.c	2013-10-23 09:12:15.913831516 -0400
aec172
@@ -40,11 +40,13 @@ struct diskdump_data {
aec172
 	struct disk_dump_sub_header	*sub_header;
aec172
 	struct kdump_sub_header		*sub_header_kdump;
aec172
 
aec172
+	unsigned long long	max_mapnr;	/* 64bit max_mapnr */
aec172
+
aec172
 	size_t	data_offset;
aec172
 	int	block_size;
aec172
 	int	block_shift;
aec172
 	char	*bitmap;
aec172
-	int	bitmap_len;
aec172
+	off_t	bitmap_len;
aec172
 	char	*dumpable_bitmap;
aec172
 	int	byte, bit;
aec172
 	char	*compressed_page;	/* copy of compressed page data */
aec172
@@ -170,9 +172,9 @@ add_diskdump_data(char* name)
aec172
 	dd->filename = name;
aec172
 
aec172
 	if (CRASHDEBUG(1))
aec172
-		fprintf(fp, "%s: start_pfn=%lu, end_pfn=%lu\n", name,
aec172
-			dd->sub_header_kdump->start_pfn,
aec172
-			dd->sub_header_kdump->end_pfn);
aec172
+		fprintf(fp, "%s: start_pfn=%llu, end_pfn=%llu\n", name,
aec172
+			dd->sub_header_kdump->start_pfn_64,
aec172
+			dd->sub_header_kdump->end_pfn_64);
aec172
 }
aec172
 
aec172
 static void 
aec172
@@ -199,13 +201,13 @@ get_bit(char *map, int byte, int bit)
aec172
 }
aec172
 
aec172
 static inline int 
aec172
-page_is_ram(unsigned int nr)
aec172
+page_is_ram(unsigned long nr)
aec172
 {
aec172
 	return get_bit(dd->bitmap, nr >> 3, nr & 7);
aec172
 }
aec172
 
aec172
 static inline int 
aec172
-page_is_dumpable(unsigned int nr)
aec172
+page_is_dumpable(unsigned long nr)
aec172
 {
aec172
 	return dd->dumpable_bitmap[nr>>3] & (1 << (nr & 7));
aec172
 }
aec172
@@ -214,7 +216,7 @@ static inline int
aec172
 dump_is_partial(const struct disk_dump_header *header)
aec172
 {
aec172
 	return header->bitmap_blocks >=
aec172
-	    divideup(divideup(header->max_mapnr, 8), dd->block_size) * 2;
aec172
+	    divideup(divideup(dd->max_mapnr, 8), dd->block_size) * 2;
aec172
 }
aec172
 
aec172
 static int 
aec172
@@ -321,6 +323,9 @@ x86_process_elf_notes(void *note_ptr, un
aec172
  * [40]    unsigned long   size_note;          /  header_version 4 and later  /
aec172
  * [44]    off_t           offset_eraseinfo;   /  header_version 5 and later  /
aec172
  * [52]    unsigned long   size_eraseinfo;     /  header_version 5 and later  /
aec172
+ * [56]    unsigned long long   start_pfn_64;  /  header_version 6 and later  /
aec172
+ * [64]    unsigned long long   end_pfn_64;    /  header_version 6 and later  /
aec172
+ * [72]    unsigned long long   max_mapnr_64;  /  header_version 6 and later  /
aec172
  * };
aec172
  * 
aec172
  * But when compiled on an ARM processor, each 64-bit "off_t" would be pushed
aec172
@@ -337,7 +342,10 @@ x86_process_elf_notes(void *note_ptr, un
aec172
  * [40]    off_t           offset_note;        /  header_version 4 and later  /
aec172
  * [48]    unsigned long   size_note;          /  header_version 4 and later  /
aec172
  * [56]    off_t           offset_eraseinfo;   /  header_version 5 and later  /
aec172
- * [62]    unsigned long   size_eraseinfo;     /  header_version 5 and later  /
aec172
+ * [64]    unsigned long   size_eraseinfo;     /  header_version 5 and later  /
aec172
+ * [72]    unsigned long long   start_pfn_64;  /  header_version 6 and later  /
aec172
+ * [80]    unsigned long long   end_pfn_64;    /  header_version 6 and later  /
aec172
+ * [88]    unsigned long long   max_mapnr_64;  /  header_version 6 and later  /
aec172
  * };
aec172
  * 
aec172
  */
aec172
@@ -357,6 +365,10 @@ struct kdump_sub_header_ARM_target {
aec172
 	int 		pad3;	
aec172
         off_t           offset_eraseinfo;   /* header_version 5 and later */
aec172
         unsigned long   size_eraseinfo;     /* header_version 5 and later */
aec172
+	int		pad4;
aec172
+	unsigned long long start_pfn_64;    /* header_version 6 and later */
aec172
+	unsigned long long end_pfn_64;      /* header_version 6 and later */
aec172
+	unsigned long long max_mapnr_64;    /* header_version 6 and later */
aec172
 };
aec172
 
aec172
 static void
aec172
@@ -380,6 +392,15 @@ arm_kdump_header_adjust(int header_versi
aec172
 		kdsh->offset_eraseinfo = kdsh_ARM_target->offset_eraseinfo;
aec172
 		kdsh->size_eraseinfo = kdsh_ARM_target->size_eraseinfo;
aec172
 	}
aec172
+	if (header_version >= 6) {
aec172
+		kdsh->start_pfn_64 = kdsh_ARM_target->start_pfn_64;
aec172
+		kdsh->end_pfn_64 = kdsh_ARM_target->end_pfn_64;
aec172
+		kdsh->max_mapnr_64 = kdsh_ARM_target->max_mapnr_64;
aec172
+	} else {
aec172
+		kdsh->start_pfn_64 = kdsh_ARM_target->start_pfn;
aec172
+		kdsh->end_pfn_64 = kdsh_ARM_target->end_pfn;
aec172
+		kdsh->max_mapnr_64 = dd->max_mapnr;
aec172
+	}
aec172
 }
aec172
 #endif  /* __i386__ && ARM */
aec172
 
aec172
@@ -390,7 +411,10 @@ read_dump_header(char *file)
aec172
 	struct disk_dump_sub_header *sub_header = NULL;
aec172
 	struct kdump_sub_header *sub_header_kdump = NULL;
aec172
 	size_t size;
aec172
-	int bitmap_len;
aec172
+	off_t bitmap_len;
aec172
+	char *bufptr;
aec172
+	size_t len;
aec172
+	ssize_t bytes_read;
aec172
 	int block_size = (int)sysconf(_SC_PAGESIZE);
aec172
 	off_t offset;
aec172
 	const off_t failed = (off_t)-1;
aec172
@@ -516,6 +540,13 @@ restart:
aec172
 			}
aec172
 		}
aec172
 		dd->sub_header = sub_header;
aec172
+
aec172
+		/* the 64bit max_mapnr only exists in sub-header of compressed
aec172
+		 * kdump file, if it's not a compressed kdump file, we have to
aec172
+		 * use the old 32bit max_mapnr in dumpfile header.
aec172
+		 * max_mapnr may be truncated here.
aec172
+		 */
aec172
+		dd->max_mapnr = header->max_mapnr;
aec172
 	} else if (KDUMP_CMPRS_VALID()) {
aec172
 		if ((sub_header_kdump = malloc(block_size)) == NULL)
aec172
 			error(FATAL, "compressed kdump: cannot malloc sub_header_kdump buffer\n");
aec172
@@ -540,8 +571,20 @@ restart:
aec172
 #if defined(__i386__) && defined(ARM)
aec172
 		arm_kdump_header_adjust(header->header_version);
aec172
 #endif
aec172
+		/* use 64bit max_mapnr in compressed kdump file sub-header */
aec172
+		if (header->header_version >= 6)
aec172
+			dd->max_mapnr = dd->sub_header_kdump->max_mapnr_64;
aec172
+		else {
aec172
+			dd->sub_header_kdump->start_pfn_64
aec172
+				= dd->sub_header_kdump->start_pfn;
aec172
+			dd->sub_header_kdump->end_pfn_64
aec172
+				= dd->sub_header_kdump->end_pfn;
aec172
+		}
aec172
 	}
aec172
 
aec172
+	if (header->header_version < 6)
aec172
+		dd->max_mapnr = header->max_mapnr;
aec172
+
aec172
 	/* read memory bitmap */
aec172
 	bitmap_len = block_size * header->bitmap_blocks;
aec172
 	dd->bitmap_len = bitmap_len;
aec172
@@ -571,10 +614,18 @@ restart:
aec172
 				DISKDUMP_VALID() ? "diskdump" : "compressed kdump");
aec172
 			goto err;
aec172
 		}
aec172
-		if (read(dd->dfd, dd->bitmap, bitmap_len) < bitmap_len) {
aec172
-			error(INFO, "%s: cannot read memory bitmap\n",
aec172
-				DISKDUMP_VALID() ? "diskdump" : "compressed kdump");
aec172
-			goto err;
aec172
+		bufptr = dd->bitmap;
aec172
+		len = bitmap_len;
aec172
+		while (len) {
aec172
+			bytes_read = read(dd->dfd, bufptr, len);
aec172
+			if (bytes_read  < 0) {
aec172
+				error(INFO, "%s: cannot read memory bitmap\n",
aec172
+					DISKDUMP_VALID() ? "diskdump"
aec172
+					: "compressed kdump");
aec172
+				goto err;
aec172
+			}
aec172
+			len -= bytes_read;
aec172
+			bufptr += bytes_read;
aec172
 		}
aec172
 	}
aec172
 
aec172
@@ -679,13 +730,13 @@ restart:
aec172
 	}
aec172
 
aec172
 	if (!is_split) {
aec172
-		max_sect_len = divideup(header->max_mapnr, BITMAP_SECT_LEN);
aec172
+		max_sect_len = divideup(dd->max_mapnr, BITMAP_SECT_LEN);
aec172
 		pfn = 0;
aec172
 		dd->filename = file;
aec172
 	}
aec172
 	else {
aec172
-		ulong start = sub_header_kdump->start_pfn;
aec172
-		ulong end = sub_header_kdump->end_pfn;
aec172
+		unsigned long long start = sub_header_kdump->start_pfn_64;
aec172
+		unsigned long long end = sub_header_kdump->end_pfn_64;
aec172
 		max_sect_len = divideup(end - start + 1, BITMAP_SECT_LEN);
aec172
 		pfn = start;
aec172
 	}
aec172
@@ -727,8 +778,9 @@ pfn_to_pos(ulong pfn)
aec172
 	ulong p1, p2;
aec172
 
aec172
 	if (KDUMP_SPLIT()) {
aec172
-		p1 = pfn - dd->sub_header_kdump->start_pfn;
aec172
-		p2 = round(p1, BITMAP_SECT_LEN) + dd->sub_header_kdump->start_pfn;
aec172
+		p1 = pfn - dd->sub_header_kdump->start_pfn_64;
aec172
+		p2 = round(p1, BITMAP_SECT_LEN)
aec172
+			+ dd->sub_header_kdump->start_pfn_64;
aec172
 	}
aec172
 	else {
aec172
 		p1 = pfn; 
aec172
@@ -1034,12 +1086,12 @@ read_diskdump(int fd, void *bufptr, int
aec172
 	if (KDUMP_SPLIT()) {
aec172
 		/* Find proper dd */
aec172
 		int i;
aec172
-		unsigned long start_pfn;
aec172
-		unsigned long end_pfn;
aec172
+		unsigned long long start_pfn;
aec172
+		unsigned long long end_pfn;
aec172
 
aec172
 		for (i=0; i
aec172
-			start_pfn = dd_list[i]->sub_header_kdump->start_pfn;
aec172
-			end_pfn = dd_list[i]->sub_header_kdump->end_pfn;
aec172
+			start_pfn = dd_list[i]->sub_header_kdump->start_pfn_64;
aec172
+			end_pfn = dd_list[i]->sub_header_kdump->end_pfn_64;
aec172
 			if ((pfn >= start_pfn) && (pfn <= end_pfn))	{
aec172
 				dd = dd_list[i];
aec172
 				break;
aec172
@@ -1058,14 +1110,14 @@ read_diskdump(int fd, void *bufptr, int
aec172
 	curpaddr = paddr & ~((physaddr_t)(dd->block_size-1));
aec172
 	page_offset = paddr & ((physaddr_t)(dd->block_size-1));
aec172
 
aec172
-	if ((pfn >= dd->header->max_mapnr) || !page_is_ram(pfn)) {
aec172
+	if ((pfn >= dd->max_mapnr) || !page_is_ram(pfn)) {
aec172
 		if (CRASHDEBUG(8)) {
aec172
 			fprintf(fp, "read_diskdump: SEEK_ERROR: "
aec172
 			    "paddr/pfn: %llx/%lx ",
aec172
 				(ulonglong)paddr, pfn);
aec172
-			if (pfn >= dd->header->max_mapnr)
aec172
-				fprintf(fp, "max_mapnr: %x\n",
aec172
-					dd->header->max_mapnr);
aec172
+			if (pfn >= dd->max_mapnr)
aec172
+				fprintf(fp, "max_mapnr: %llx\n",
aec172
+					dd->max_mapnr);
aec172
 			else
aec172
 				fprintf(fp, "!page_is_ram\n");
aec172
 		}
aec172
@@ -1507,12 +1559,31 @@ __diskdump_memory_dump(FILE *fp)
aec172
 	fprintf(fp, "               tv_usec: %lx\n", dh->timestamp.tv_usec);
aec172
 	fprintf(fp, "              status: %x (", dh->status);
aec172
         others = 0;
aec172
-        if (dh->status & DUMP_HEADER_COMPLETED)
aec172
-                fprintf(fp, "%sDUMP_HEADER_COMPLETED", others++ ? "|" : "");
aec172
-        if (dh->status & DUMP_HEADER_INCOMPLETED)
aec172
-                fprintf(fp, "%sDUMP_HEADER_INCOMPLETED", others++ ? "|" : "");
aec172
-        if (dh->status & DUMP_HEADER_COMPRESSED)
aec172
-                fprintf(fp, "%sDUMP_HEADER_COMPRESSED", others++ ? "|" : "");
aec172
+	switch (dd->flags & (DISKDUMP_LOCAL|KDUMP_CMPRS_LOCAL))
aec172
+	{
aec172
+        case DISKDUMP_LOCAL:
aec172
+		if (dh->status == DUMP_HEADER_COMPLETED)
aec172
+			fprintf(fp, "%sDUMP_HEADER_COMPLETED", 
aec172
+				others++ ? "|" : "");
aec172
+		else if (dh->status == DUMP_HEADER_INCOMPLETED)
aec172
+			fprintf(fp, "%sDUMP_HEADER_INCOMPLETED", 
aec172
+				others++ ? "|" : "");
aec172
+		else if (dh->status == DUMP_HEADER_COMPRESSED)
aec172
+			fprintf(fp, "%sDUMP_HEADER_COMPRESSED", 
aec172
+				others++ ? "|" : "");
aec172
+		break;
aec172
+	case KDUMP_CMPRS_LOCAL:
aec172
+		if (dh->status & DUMP_DH_COMPRESSED_ZLIB)
aec172
+			fprintf(fp, "%sDUMP_DH_COMPRESSED_ZLIB", 
aec172
+				others++ ? "|" : "");
aec172
+		if (dh->status & DUMP_DH_COMPRESSED_LZO)
aec172
+			fprintf(fp, "%sDUMP_DH_COMPRESSED_LZO", 
aec172
+				others++ ? "|" : "");
aec172
+		if (dh->status & DUMP_DH_COMPRESSED_SNAPPY)
aec172
+			fprintf(fp, "%sDUMP_DH_COMPRESSED_SNAPPY", 
aec172
+				others++ ? "|" : "");
aec172
+		break;
aec172
+	}
aec172
 	fprintf(fp, ")\n");
aec172
 	fprintf(fp, "          block_size: %d\n", dh->block_size);
aec172
 	fprintf(fp, "        sub_hdr_size: %d\n", dh->sub_hdr_size);
aec172
@@ -1662,6 +1733,23 @@ __diskdump_memory_dump(FILE *fp)
aec172
 				dump_eraseinfo(fp);
aec172
 			}
aec172
 		}
aec172
+		if (dh->header_version >= 6) {
aec172
+			fprintf(fp, "        start_pfn_64: ");
aec172
+			if (KDUMP_SPLIT())
aec172
+				fprintf(fp, "%lld (0x%llx)\n",
aec172
+					kdsh->start_pfn_64, kdsh->start_pfn_64);
aec172
+			else
aec172
+				fprintf(fp, "(unused)\n");
aec172
+			fprintf(fp, "          end_pfn_64: ");
aec172
+			if (KDUMP_SPLIT())
aec172
+				fprintf(fp, "%lld (0x%llx)\n",
aec172
+					kdsh->end_pfn_64, kdsh->end_pfn_64);
aec172
+			else
aec172
+				fprintf(fp, "(unused)\n");
aec172
+
aec172
+			fprintf(fp, "        max_mapnr_64: %llu (0x%llx)\n",
aec172
+				kdsh->max_mapnr_64, kdsh->max_mapnr_64);
aec172
+		}
aec172
 		fprintf(fp, "\n");
aec172
 	} else
aec172
         	fprintf(fp, "(n/a)\n\n");
aec172
@@ -1670,7 +1758,8 @@ __diskdump_memory_dump(FILE *fp)
aec172
 	fprintf(fp, "        block_size: %d\n", dd->block_size);
aec172
 	fprintf(fp, "       block_shift: %d\n", dd->block_shift);
aec172
 	fprintf(fp, "            bitmap: %lx\n", (ulong)dd->bitmap);
aec172
-	fprintf(fp, "        bitmap_len: %d\n", dd->bitmap_len);
aec172
+	fprintf(fp, "        bitmap_len: %lld\n", (ulonglong)dd->bitmap_len);
aec172
+	fprintf(fp, "         max_mapnr: %lld (0x%llx)\n", dd->max_mapnr, dd->max_mapnr);
aec172
 	fprintf(fp, "   dumpable_bitmap: %lx\n", (ulong)dd->dumpable_bitmap);
aec172
 	fprintf(fp, "              byte: %d\n", dd->byte);
aec172
 	fprintf(fp, "               bit: %d\n", dd->bit);
aec172
--- crash-7.0.2/makedumpfile.c	2013-10-25 15:28:55.951879567 -0400
aec172
+++ crash-7.0.3/makedumpfile.c	2013-10-25 10:10:07.615755902 -0400
aec172
@@ -59,7 +59,7 @@ store_flat_data_array(char *file, struct
aec172
 	unsigned long long	num_allocated = 0;
aec172
 	unsigned long long	num_stored    = 0;
aec172
 	unsigned long long	size_allocated;
aec172
-	struct flat_data	*ptr = NULL, *cur;
aec172
+	struct flat_data	*ptr = NULL, *cur, *new;
aec172
 	struct makedumpfile_data_header	fdh;
aec172
 
aec172
 	fd = open(file, O_RDONLY);
aec172
@@ -77,12 +77,13 @@ store_flat_data_array(char *file, struct
aec172
 			num_allocated += 100;
aec172
 			size_allocated = sizeof(struct flat_data)
aec172
 					 * num_allocated;
aec172
-			ptr = realloc(ptr, size_allocated);
aec172
-			if (ptr == NULL) {
aec172
+			new = realloc(ptr, size_allocated);
aec172
+			if (new == NULL) {
aec172
 				error(INFO, 
aec172
 				    "unable to realloc flat_data structures\n");
aec172
 				break;
aec172
 			}
aec172
+			ptr = new;
aec172
 		}
aec172
 		offset_fdh = lseek(fd, 0x0, SEEK_CUR);
aec172
 
aec172
--- crash-7.0.2/unwind_arm.c	2013-10-25 15:28:55.938879568 -0400
aec172
+++ crash-7.0.3/unwind_arm.c	2013-09-06 15:03:40.804904775 -0400
aec172
@@ -325,7 +325,8 @@ init_module_unwind_tables(void)
aec172
 	hq_open();
aec172
 	cnt = do_list(&ld);
aec172
 	if (cnt == -1) {
aec172
-		error(WARNING, "UNWIND: failed to gather unwind_table list");
aec172
+		error(WARNING, "UNWIND: failed to gather unwind_table list\n");
aec172
+		hq_close();
aec172
 		return FALSE;
aec172
 	}
aec172
 	table_list = (ulong *)GETBUF(cnt * sizeof(ulong));
aec172
--- crash-7.0.2/sadump.c	2013-10-25 15:28:55.941879568 -0400
aec172
+++ crash-7.0.3/sadump.c	2013-10-25 10:10:13.104755651 -0400
aec172
@@ -18,6 +18,7 @@
aec172
 
aec172
 #include "defs.h"
aec172
 #include "sadump.h"
aec172
+#include <arpa/inet.h> /* htonl, htons */
aec172
 #include <elf.h>
aec172
 
aec172
 enum {
aec172
@@ -118,7 +119,7 @@ read_dump_header(char *file)
aec172
 {
aec172
 	struct sadump_part_header *sph = NULL;
aec172
 	struct sadump_header *sh = NULL;
aec172
-	struct sadump_disk_set_header *sdh = NULL;
aec172
+	struct sadump_disk_set_header *new, *sdh = NULL;
aec172
 	struct sadump_media_header *smh = NULL;
aec172
 	struct sadump_diskset_data *sd_list_len_0 = NULL;
aec172
 	size_t block_size = SADUMP_DEFAULT_BLOCK_SIZE;
aec172
@@ -127,7 +128,8 @@ read_dump_header(char *file)
aec172
 	uint32_t smram_cpu_state_size = 0;
aec172
 	ulong bitmap_len, dumpable_bitmap_len;
aec172
 	char *bitmap = NULL, *dumpable_bitmap = NULL, *page_buf = NULL;
aec172
-	char guid1[33], guid2[33];
aec172
+	char guid1[SADUMP_EFI_GUID_TEXT_REPR_LEN+1];
aec172
+	char guid2[SADUMP_EFI_GUID_TEXT_REPR_LEN+1];
aec172
 
aec172
 	sph = malloc(block_size);
aec172
 	if (!sph) {
aec172
@@ -226,12 +228,13 @@ restart:
aec172
 		header_size = header_blocks * block_size;
aec172
 
aec172
 		if (header_size > block_size) {
aec172
-			sdh = realloc(sdh, header_size);
aec172
-			if (!sdh) {
aec172
+			new = realloc(sdh, header_size);
aec172
+			if (!new) {
aec172
 				error(INFO, "sadump: cannot re-allocate disk "
aec172
 				      "set buffer\n");
aec172
 				goto err;
aec172
 			}
aec172
+			sdh = new;
aec172
 		}
aec172
 
aec172
 		if (!read_device(sdh, header_size, &offset)) {
aec172
@@ -468,7 +471,8 @@ add_disk(char *file)
aec172
 	struct sadump_part_header *ph;
aec172
 	struct sadump_diskset_data *this_disk;
aec172
 	int diskid;
aec172
-	char guid1[33], guid2[33];
aec172
+	char guid1[SADUMP_EFI_GUID_TEXT_REPR_LEN+1];
aec172
+	char guid2[SADUMP_EFI_GUID_TEXT_REPR_LEN+1];
aec172
 
aec172
 	diskid = sd->sd_list_len - 1;
aec172
 	this_disk = sd->sd_list[diskid];
aec172
@@ -863,7 +867,7 @@ guid_to_str(efi_guid_t *guid, char *buf,
aec172
 {
aec172
 	snprintf(buf, buflen,
aec172
 		 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
aec172
-		 guid->data1, guid->data2, guid->data3,
aec172
+		 htonl(guid->data1), htons(guid->data2), htons(guid->data3),
aec172
 		 guid->data4[0], guid->data4[1], guid->data4[2],
aec172
 		 guid->data4[3], guid->data4[4], guid->data4[5],
aec172
 		 guid->data4[6], guid->data4[7]);
aec172
@@ -905,7 +909,7 @@ int sadump_memory_dump(FILE *fp)
aec172
 	struct sadump_header *sh;
aec172
 	struct sadump_media_header *smh;
aec172
 	int i, others;
aec172
-	char guid[33];
aec172
+	char guid[SADUMP_EFI_GUID_TEXT_REPR_LEN+1];
aec172
 
aec172
 	fprintf(fp, "sadump_data: \n");
aec172
 	fprintf(fp, "          filename: %s\n", sd->filename);
aec172
--- crash-7.0.2/defs.h	2013-10-25 15:28:55.937879568 -0400
aec172
+++ crash-7.0.3/defs.h	2013-10-25 11:49:58.544481437 -0400
aec172
@@ -59,7 +59,7 @@
aec172
 #define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
aec172
 #endif
aec172
 
aec172
-#define BASELEVEL_REVISION  "7.0.2"
aec172
+#define BASELEVEL_REVISION  "7.0.3"
aec172
 
aec172
 #undef TRUE
aec172
 #undef FALSE
aec172
@@ -503,6 +503,7 @@ struct program_context {
aec172
 #define QEMU_MEM_DUMP (0x100ULL)
aec172
 #define GET_LOG       (0x200ULL)
aec172
 #define VMCOREINFO    (0x400ULL)
aec172
+#define ALLOW_FP      (0x800ULL)
aec172
 	char *cleanup;
aec172
 	char *namelist_orig;
aec172
 	char *namelist_debug_orig;
aec172
@@ -1876,6 +1877,9 @@ struct offset_table {
aec172
 	long task_struct_thread_context_fp;
aec172
 	long task_struct_thread_context_sp;
aec172
 	long task_struct_thread_context_pc;
aec172
+	long page_slab_page;
aec172
+	long trace_print_flags_mask;
aec172
+	long trace_print_flags_name;
aec172
 };
aec172
 
aec172
 struct size_table {         /* stash of commonly-used sizes */
aec172
@@ -2016,6 +2020,7 @@ struct size_table {         /* stash of
aec172
 	long hrtimer_clock_base;
aec172
 	long hrtimer_base;
aec172
 	long tnt;
aec172
+	long trace_print_flags;
aec172
 };
aec172
 
aec172
 struct array_table {
aec172
@@ -2183,6 +2188,13 @@ struct vm_table {                /* kern
aec172
 	int cpu_slab_type;
aec172
 	int nr_vm_event_items;
aec172
 	char **vm_event_items;
aec172
+	int nr_bad_slab_caches;
aec172
+	ulong *bad_slab_caches;
aec172
+	int nr_pageflags;
aec172
+	struct pageflags_data {
aec172
+		ulong mask;
aec172
+		char *name;
aec172
+	} *pageflags_data;
aec172
 };
aec172
 
aec172
 #define NODES                       (0x1)
aec172
@@ -2211,6 +2223,7 @@ struct vm_table {                /* kern
aec172
 #define NODELISTS_IS_PTR       (0x800000)
aec172
 #define KMALLOC_COMMON        (0x1000000)
aec172
 #define USE_VMAP_AREA         (0x2000000)
aec172
+#define PAGEFLAGS             (0x4000000)
aec172
 
aec172
 #define IS_FLATMEM()		(vt->flags & FLATMEM)
aec172
 #define IS_DISCONTIGMEM()	(vt->flags & DISCONTIGMEM)
aec172
@@ -4321,6 +4334,7 @@ int calculate(char *, ulong *, ulonglong
aec172
 int endian_mismatch(char *, char, ulong);
aec172
 uint16_t swap16(uint16_t, int);
aec172
 uint32_t swap32(uint32_t, int);
aec172
+ulong *get_cpumask_buf(void);
aec172
 int make_cpumask(char *, ulong *, int, int *);
aec172
 size_t strlcpy(char *, char *, size_t);
aec172
 struct rb_node *rb_first(struct rb_root *);
aec172
--- crash-7.0.2/diskdump.h	2013-10-25 15:28:56.133879559 -0400
aec172
+++ crash-7.0.3/diskdump.h	2013-10-18 11:11:20.610295600 -0400
aec172
@@ -42,7 +42,9 @@ struct disk_dump_header {
aec172
 						   header in blocks */
aec172
 	unsigned int		bitmap_blocks;	/* Size of Memory bitmap in
aec172
 						   block */
aec172
-	unsigned int		max_mapnr;	/* = max_mapnr */
aec172
+	unsigned int		max_mapnr;	/* = max_mapnr, OBSOLETE!
aec172
+						   32bit only, full 64bit
aec172
+						   in sub header. */
aec172
 	unsigned int		total_ram_blocks;/* Number of blocks should be
aec172
 						   written */
aec172
 	unsigned int		device_blocks;	/* Number of total blocks in
aec172
@@ -61,14 +63,21 @@ struct kdump_sub_header {
aec172
 	unsigned long	phys_base;
aec172
 	int		dump_level;         /* header_version 1 and later */
aec172
 	int		split;              /* header_version 2 and later */
aec172
-	unsigned long	start_pfn;          /* header_version 2 and later */
aec172
-	unsigned long	end_pfn;            /* header_version 2 and later */
aec172
+	unsigned long	start_pfn;          /* header_version 2 and later,
aec172
+					       OBSOLETE! 32bit only, full 64bit
aec172
+					       in start_pfn_64. */
aec172
+	unsigned long	end_pfn;            /* header_version 2 and later,
aec172
+					       OBSOLETE! 32bit only, full 64bit
aec172
+					       in end_pfn_64. */
aec172
 	off_t		offset_vmcoreinfo;  /* header_version 3 and later */
aec172
 	unsigned long	size_vmcoreinfo;    /* header_version 3 and later */
aec172
 	off_t		offset_note;        /* header_version 4 and later */
aec172
 	unsigned long	size_note;          /* header_version 4 and later */
aec172
 	off_t		offset_eraseinfo;   /* header_version 5 and later */
aec172
 	unsigned long	size_eraseinfo;     /* header_version 5 and later */
aec172
+	unsigned long long start_pfn_64;    /* header_version 6 and later */
aec172
+	unsigned long long end_pfn_64;      /* header_version 6 and later */
aec172
+	unsigned long long max_mapnr_64;    /* header_version 6 and later */
aec172
 };
aec172
 
aec172
 /* page flags */
aec172
--- crash-7.0.2/lkcd_vmdump_v1.h	2013-10-25 15:28:55.935879568 -0400
aec172
+++ crash-7.0.3/lkcd_vmdump_v1.h	2013-10-24 09:06:51.222888110 -0400
aec172
@@ -117,10 +117,12 @@ typedef struct _dump_header_s {
aec172
 #ifndef IA64
aec172
 #ifndef S390
aec172
 #ifndef S390X
aec172
+#ifndef ARM64
aec172
 	struct pt_regs       dh_regs;
aec172
 #endif
aec172
 #endif
aec172
 #endif
aec172
+#endif
aec172
 
aec172
 	/* the address of the current task */
aec172
 	struct task_struct  *dh_current_task;
aec172
--- crash-7.0.2/lkcd_vmdump_v2_v3.h	2013-10-25 15:28:55.938879568 -0400
aec172
+++ crash-7.0.3/lkcd_vmdump_v2_v3.h	2013-10-24 09:13:13.588870592 -0400
aec172
@@ -84,9 +84,11 @@ typedef struct _dump_header_asm_s {
aec172
 	/* the dump registers */
aec172
 #ifndef S390
aec172
 #ifndef S390X
aec172
+#ifndef ARM64
aec172
 	struct pt_regs       dha_regs;
aec172
 #endif
aec172
 #endif
aec172
+#endif
aec172
 
aec172
 } dump_header_asm_t;
aec172
 
aec172
--- crash-7.0.2/sadump.h	2013-10-25 15:28:55.939879568 -0400
aec172
+++ crash-7.0.3/sadump.h	2013-09-13 08:48:05.576229221 -0400
aec172
@@ -41,6 +41,8 @@ typedef struct {
aec172
 	uint8_t data4[8];
aec172
 } efi_guid_t;
aec172
 
aec172
+#define SADUMP_EFI_GUID_TEXT_REPR_LEN 36
aec172
+
aec172
 struct sadump_part_header {
aec172
 #define SADUMP_SIGNATURE1	0x75646173
aec172
 #define SADUMP_SIGNATURE2	0x0000706d
aec172
--- crash-7.0.2/extensions/snap.c	2013-10-25 15:28:55.943879568 -0400
aec172
+++ crash-7.0.3/extensions/snap.c	2013-10-25 10:10:39.188754456 -0400
aec172
@@ -416,7 +416,8 @@ generate_elf_header(int type, int fd, ch
aec172
 	} else if (machine_type("PPC64")) {
aec172
 		e_machine = EM_PPC64;
aec172
 		prstatus_len = sizeof(prstatus.ppc64);
aec172
-	}
aec172
+	} else
aec172
+		return NULL;
aec172
 
aec172
 	/* should be enought for the notes + roundup + two blocks */
aec172
 	buffer = (char *)GETBUF(sizeof(Elf64_Ehdr) +
aec172
@@ -538,7 +539,7 @@ generate_elf_header(int type, int fd, ch
aec172
 			break;
aec172
 		}
aec172
 
aec172
-		l_offset += load[i].p_filesz;
aec172
+//		l_offset += load[i].p_filesz;
aec172
 		offset += sizeof(Elf64_Phdr);
aec172
 		ptr += sizeof(Elf64_Phdr);
aec172
 	}
aec172
--- crash-7.0.2/extensions/trace.c	2013-10-25 15:28:55.944879568 -0400
aec172
+++ crash-7.0.3/extensions/trace.c	2013-10-25 10:10:44.031754234 -0400
aec172
@@ -1453,6 +1453,7 @@ static void ftrace_show(int argc, char *
aec172
 	if ((file = popen(trace_cmd, "r"))) {
aec172
 		ret = fread(buf, 1, sizeof(buf), file);
aec172
 		buf[ret] = 0;
aec172
+		pclose(file);
aec172
 	}
aec172
 	if (!strstr(buf, "trace-cmd version")) {
aec172
 		if (env_trace_cmd)
aec172
--- crash-7.0.3/defs.h.orig
aec172
+++ crash-7.0.3/defs.h
aec172
@@ -1880,6 +1880,8 @@ struct offset_table {
aec172
 	long page_slab_page;
aec172
 	long trace_print_flags_mask;
aec172
 	long trace_print_flags_name;
aec172
+	long task_struct_rss_stat;
aec172
+	long task_rss_stat_count;
aec172
 };
aec172
 
aec172
 struct size_table {         /* stash of commonly-used sizes */
aec172
--- crash-7.0.3/symbols.c.orig
aec172
+++ crash-7.0.3/symbols.c
aec172
@@ -7643,6 +7643,10 @@ dump_offset_table(char *spec, ulong make
aec172
                 OFFSET(task_struct_tgid));
aec172
         fprintf(fp, "         task_struct_namespace: %ld\n",
aec172
                 OFFSET(task_struct_namespace));
aec172
+        fprintf(fp, "          task_struct_rss_stat: %ld\n",
aec172
+                OFFSET(task_struct_rss_stat));
aec172
+        fprintf(fp, "           task_rss_stat_count: %ld\n",
aec172
+                OFFSET(task_rss_stat_count));
aec172
         fprintf(fp, "              task_struct_pids: %ld\n",
aec172
                 OFFSET(task_struct_pids));
aec172
         fprintf(fp, "          task_struct_last_run: %ld\n",
aec172
--- crash-7.0.3/memory.c.orig
aec172
+++ crash-7.0.3/memory.c
aec172
@@ -4003,6 +4003,7 @@ void
aec172
 get_task_mem_usage(ulong task, struct task_mem_usage *tm)
aec172
 {
aec172
 	struct task_context *tc;
aec172
+	long rss = 0;
aec172
 
aec172
 	BZERO(tm, sizeof(struct task_mem_usage));
aec172
 
aec172
@@ -4036,22 +4037,65 @@ get_task_mem_usage(ulong task, struct ta
aec172
 				filepages = 0;
aec172
 				anonpages = 1;
aec172
 			}
aec172
-			tm->rss += ULONG(tt->mm_struct + 
aec172
+			rss += LONG(tt->mm_struct +
aec172
 				OFFSET(mm_struct_rss_stat) +
aec172
 				OFFSET(mm_rss_stat_count) +
aec172
-				(filepages * sizeof(ulong)));
aec172
-			tm->rss += ULONG(tt->mm_struct + 
aec172
+				(filepages * sizeof(long)));
aec172
+			rss += LONG(tt->mm_struct +
aec172
 				OFFSET(mm_struct_rss_stat) +
aec172
 				OFFSET(mm_rss_stat_count) +
aec172
-				(anonpages * sizeof(ulong)));
aec172
+				(anonpages * sizeof(long)));
aec172
 		}
aec172
+
aec172
+		/* Check whether SPLIT_RSS_COUNTING is enabled */
aec172
+		if (VALID_MEMBER(task_struct_rss_stat)) {
aec172
+			int i, sync_rss;
aec172
+			ulong tgid;
aec172
+			struct task_context *tc1;
aec172
+
aec172
+			tgid = task_tgid(task);
aec172
+
aec172
+			tc1 = FIRST_CONTEXT();
aec172
+			for (i = 0; i < RUNNING_TASKS(); i++, tc1++) {
aec172
+				if (task_tgid(tc1->task) != tgid)
aec172
+					continue;
aec172
+
aec172
+				/* count 0 -> filepages */
aec172
+				if (!readmem(tc1->task +
aec172
+					OFFSET(task_struct_rss_stat) +
aec172
+					OFFSET(task_rss_stat_count), KVADDR,
aec172
+					&sync_rss,
aec172
+					sizeof(int),
aec172
+					"task_struct rss_stat MM_FILEPAGES",
aec172
+					RETURN_ON_ERROR))
aec172
+						continue;
aec172
+
aec172
+				rss += sync_rss;
aec172
+
aec172
+				/* count 1 -> anonpages */
aec172
+				if (!readmem(tc1->task +
aec172
+					OFFSET(task_struct_rss_stat) +
aec172
+					OFFSET(task_rss_stat_count) +
aec172
+					sizeof(int),
aec172
+					KVADDR, &sync_rss,
aec172
+					sizeof(int),
aec172
+					"task_struct rss_stat MM_ANONPAGES",
aec172
+					RETURN_ON_ERROR))
aec172
+						continue;
aec172
+
aec172
+				rss += sync_rss;
aec172
+			}
aec172
+		}
aec172
+
aec172
 		/*  
aec172
 		 *  mm_struct._anon_rss and mm_struct._file_rss should exist. 
aec172
 		 */
aec172
 		if (VALID_MEMBER(mm_struct_anon_rss))
aec172
-			tm->rss +=  ULONG(tt->mm_struct + OFFSET(mm_struct_anon_rss));
aec172
+			rss +=  LONG(tt->mm_struct + OFFSET(mm_struct_anon_rss));
aec172
 		if (VALID_MEMBER(mm_struct_file_rss))
aec172
-			tm->rss +=  ULONG(tt->mm_struct + OFFSET(mm_struct_file_rss));
aec172
+			rss +=  LONG(tt->mm_struct + OFFSET(mm_struct_file_rss));
aec172
+
aec172
+		tm->rss = (unsigned long)rss;
aec172
 	}
aec172
         tm->total_vm = ULONG(tt->mm_struct + OFFSET(mm_struct_total_vm));
aec172
         tm->pgd_addr = ULONG(tt->mm_struct + OFFSET(mm_struct_pgd));
aec172
--- crash-7.0.3/task.c.orig
aec172
+++ crash-7.0.3/task.c
aec172
@@ -349,6 +349,11 @@ task_init(void)
aec172
 		MEMBER_OFFSET_INIT(task_struct_run_list, "task_struct",
aec172
 			"run_list");
aec172
 
aec172
+	MEMBER_OFFSET_INIT(task_struct_rss_stat, "task_struct",
aec172
+		"rss_stat");
aec172
+	MEMBER_OFFSET_INIT(task_rss_stat_count, "task_rss_stat",
aec172
+		"count");
aec172
+
aec172
         if ((tt->task_struct = (char *)malloc(SIZE(task_struct))) == NULL)
aec172
         	error(FATAL, "cannot malloc task_struct space.");
aec172