|
|
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 |
|