diff --git a/.crash.metadata b/.crash.metadata index c8dff53..c69b121 100644 --- a/.crash.metadata +++ b/.crash.metadata @@ -1 +1 @@ -2216841453fec77f7f964f9bcd211102ad465ff0 SOURCES/crash-7.0.2.tar.gz +1d3647e807c59189746cbccdf6a5be6e15e6f397 SOURCES/crash-7.0.9.tar.gz diff --git a/.gitignore b/.gitignore index 1aae80d..13f7396 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/crash-7.0.2.tar.gz +SOURCES/crash-7.0.9.tar.gz diff --git a/SOURCES/S390X_NR_CPUS.patch b/SOURCES/S390X_NR_CPUS.patch deleted file mode 100644 index 22ee2dd..0000000 --- a/SOURCES/S390X_NR_CPUS.patch +++ /dev/null @@ -1,15 +0,0 @@ ---- crash-7.0.2/defs.h.orig -+++ crash-7.0.2/defs.h -@@ -125,10 +125,10 @@ - #define NR_CPUS (2048) - #endif - #ifdef S390 --#define NR_CPUS (64) -+#define NR_CPUS (512) - #endif - #ifdef S390X --#define NR_CPUS (64) -+#define NR_CPUS (512) - #endif - #ifdef ARM - #define NR_CPUS (4) diff --git a/SOURCES/backtrace_fixes.patch b/SOURCES/backtrace_fixes.patch deleted file mode 100644 index 4083a6e..0000000 --- a/SOURCES/backtrace_fixes.patch +++ /dev/null @@ -1,508 +0,0 @@ ---- crash-7.0.2/kernel.c.orig -+++ crash-7.0.2/kernel.c -@@ -1,8 +1,8 @@ - /* kernel.c - core analysis suite - * - * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc. -- * Copyright (C) 2002-2013 David Anderson -- * Copyright (C) 2002-2013 Red Hat, Inc. All rights reserved. -+ * Copyright (C) 2002-2014 David Anderson -+ * Copyright (C) 2002-2014 Red Hat, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by -@@ -1994,7 +1994,10 @@ cmd_bt(void) - break; - - case 'F': -- bt->flags |= (BT_FULL|BT_FULL_SYM_SLAB); -+ if (bt->flags & BT_FULL_SYM_SLAB) -+ bt->flags |= BT_FULL_SYM_SLAB2; -+ else -+ bt->flags |= (BT_FULL|BT_FULL_SYM_SLAB); - break; - - case 'o': ---- crash-7.0.2/task.c.orig -+++ crash-7.0.2/task.c -@@ -5304,7 +5304,10 @@ cmd_foreach(void) - break; - - case 'F': -- fd->flags |= FOREACH_F_FLAG; -+ if (fd->flags & FOREACH_F_FLAG) -+ fd->flags |= FOREACH_F_FLAG2; -+ else -+ fd->flags |= FOREACH_F_FLAG; - break; - - case 'a': -@@ -5859,6 +5862,8 @@ foreach(struct foreach_data *fd) - bt->flags |= BT_FULL; - if (fd->flags & FOREACH_F_FLAG) - bt->flags |= (BT_FULL|BT_FULL_SYM_SLAB); -+ if (fd->flags & FOREACH_F_FLAG2) -+ bt->flags |= BT_FULL_SYM_SLAB2; - if (fd->flags & FOREACH_x_FLAG) - bt->radix = 16; - if (fd->flags & FOREACH_d_FLAG) ---- crash-7.0.2/help.c.orig -+++ crash-7.0.2/help.c -@@ -1,8 +1,8 @@ - /* help.c - core analysis suite - * - * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc. -- * Copyright (C) 2002-2013 David Anderson -- * Copyright (C) 2002-2013 Red Hat, Inc. All rights reserved. -+ * Copyright (C) 2002-2014 David Anderson -+ * Copyright (C) 2002-2014 Red Hat, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by -@@ -1553,9 +1553,12 @@ char *help_rd[] = { - " -d display output in signed decimal format (default is hexadecimal).", - " -D display output in unsigned decimal format (default is hexadecimal).", - " -s displays output symbolically when appropriate.", --" -S displays output symbolically when appropriate; if the address", --" references a slab cache object, the name of the slab cache will", --" be displayed in brackets.", -+" -S[S] displays output symbolically when appropriate; if the memory", -+" contents reference a slab cache object, the name of the slab cache", -+" will be displayed in brackets. If -S is entered twice, and the", -+" memory contents reference a slab cache object, both the memory", -+" contents and the name of the slab cache will be displayed in", -+" brackets.", - " -x do not display ASCII translation at end of each line.", - #ifdef NOTDEF - " -o Shows offset value from the starting address.", -@@ -1593,36 +1596,39 @@ char *help_rd[] = { - "", - " Display the same block of memory, first without symbols, again", - " with symbols, and then with symbols and slab cache references:\n", --" %s> rd dff12e80 36", --" dff12e80: dff12e94 00000000 c05a363a dff12ed0 ........:6Z.....", --" dff12e90: 00000001 dff12e98 0041fe3f ffffffff ........?.A.....", --" dff12ea0: 00000001 d5147800 00000000 def8abc0 .....x..........", --" dff12eb0: dff12ebc c05a4aa0 00000000 dff12ed0 .....JZ.........", --" dff12ec0: 00000001 00000000 00000000 00000000 ................", --" dff12ed0: 0808b353 00000000 dff12efc c0698220 S........... .i.", --" dff12ee0: dff12efc df7c6480 00000001 c046f99b .....d|.......F.", --" dff12ef0: 00000000 00000000 0808b352 dff12f68 ........R...h/..", --" dff12f00: c155a128 00000000 00000001 ffffffff (.U.............", --" %s> rd -s dff12e80 36", --" dff12e80: dff12e94 00000000 sock_aio_write+83 dff12ed0 ", --" dff12e90: 00000001 dff12e98 0041fe3f ffffffff ", --" dff12ea0: 00000001 d5147800 00000000 def8abc0 ", --" dff12eb0: dff12ebc sys_recvfrom+207 00000000 dff12ed0 ", --" dff12ec0: 00000001 00000000 00000000 00000000 ", --" dff12ed0: 0808b353 00000000 dff12efc socket_file_ops ", --" dff12ee0: dff12efc df7c6480 00000001 do_sync_write+182 ", --" dff12ef0: 00000000 00000000 0808b352 dff12f68 ", --" dff12f00: c155a128 00000000 00000001 ffffffff ", --" %s> rd -S dff12e80 36", --" dff12e80: [size-4096] 00000000 sock_aio_write+83 [size-4096] ", --" dff12e90: 00000001 [size-4096] 0041fe3f ffffffff ", --" dff12ea0: 00000001 [sock_inode_cache] 00000000 [filp] ", --" dff12eb0: [size-4096] sys_recvfrom+207 00000000 [size-4096] ", --" dff12ec0: 00000001 00000000 00000000 00000000 ", --" dff12ed0: 0808b353 00000000 [size-4096] socket_file_ops ", --" dff12ee0: [size-4096] [filp] 00000001 do_sync_write+182 ", --" dff12ef0: 00000000 00000000 0808b352 [size-4096] ", --" dff12f00: [vm_area_struct] 00000000 00000001 ffffffff\n", -+" %s> rd f6e31f70 28", -+" f6e31f70: f6e31f6c f779c180 c04a4032 00a9dd40 l.....y.2@J.@...", -+" f6e31f80: 00000fff c0472da0 f6e31fa4 f779c180 .....-G.......y.", -+" f6e31f90: fffffff7 00a9b70f f6e31000 c04731ee .............1G.", -+" f6e31fa0: f6e31fa4 00000000 00000000 00000000 ................", -+" f6e31fb0: 00000000 00a9dd40 c0404f17 00000000 ....@....O@.....", -+" f6e31fc0: 00a9dd40 00000fff 00a9dd40 00a9b70f @.......@.......", -+" f6e31fd0: bf9e2718 ffffffda c040007b 0000007b .'......{.@.{...", -+" %s> rd -s f6e31f70 28", -+" f6e31f70: f6e31f6c f779c180 kmsg_read 00a9dd40 ", -+" f6e31f80: 00000fff vfs_read+159 f6e31fa4 f779c180 ", -+" f6e31f90: fffffff7 00a9b70f f6e31000 sys_read+60 ", -+" f6e31fa0: f6e31fa4 00000000 00000000 00000000 ", -+" f6e31fb0: 00000000 00a9dd40 syscall_call+7 00000000 ", -+" f6e31fc0: 00a9dd40 00000fff 00a9dd40 00a9b70f ", -+" f6e31fd0: bf9e2718 ffffffda startup_32+123 0000007b ", -+" %s> rd -S f6e31f70 28", -+" f6e31f70: [size-4096] [filp] kmsg_read 00a9dd40 ", -+" f6e31f80: 00000fff vfs_read+159 [size-4096] [filp] ", -+" f6e31f90: fffffff7 00a9b70f [size-4096] sys_read+60 ", -+" f6e31fa0: [size-4096] 00000000 00000000 00000000 ", -+" f6e31fb0: 00000000 00a9dd40 syscall_call+7 00000000 ", -+" f6e31fc0: 00a9dd40 00000fff 00a9dd40 00a9b70f ", -+" f6e31fd0: bf9e2718 ffffffda startup_32+123 0000007b ", -+" %s> rd -SS f6e31f70 28", -+" f6e31f70: [f6e31f6c:size-4096] [f779c180:filp] kmsg_read 00a9dd40 ", -+" f6e31f80: 00000fff vfs_read+159 [f6e31fa4:size-4096] [f779c180:filp] ", -+" f6e31f90: fffffff7 00a9b70f [f6e31000:size-4096] sys_read+60 ", -+" f6e31fa0: [f6e31fa4:size-4096] 00000000 00000000 00000000 ", -+" f6e31fb0: 00000000 00a9dd40 syscall_call+7 00000000 ", -+" f6e31fc0: 00a9dd40 00000fff 00a9dd40 00a9b70f ", -+" f6e31fd0: bf9e2718 ffffffda startup_32+123 0000007b ", -+"", - " Read jiffies in hexadecimal and decimal format:\n", - " %s> rd jiffies", - " c0213ae0: 0008cc3a :...\n", -@@ -1706,10 +1712,13 @@ char *help_bt[] = { - " -f display all stack data contained in a frame; this option can be", - " used to determine the arguments passed to each function; on ia64,", - " the argument register contents are dumped.", --" -F similar to -f, except that the stack data is displayed symbolically", -+" -F[F] similar to -f, except that the stack data is displayed symbolically", - " when appropriate; if the stack data references a slab cache object,", - " the name of the slab cache will be displayed in brackets; on ia64,", --" the substitution is done to the argument register contents.", -+" the substitution is done to the argument register contents. If -F", -+" is entered twice, and the stack data references a slab cache object,", -+" both the address and the name of the slab cache will be displayed", -+" in brackets.", - " -o x86: use old backtrace method, permissible only on kernels that were", - " compiled without the -fomit-frame_pointer.", - " x86_64: use old backtrace method, which dumps potentially stale", -@@ -1937,6 +1946,34 @@ char *help_bt[] = { - " R10: 0000000000000000 R11: 0000000000000202 R12: ffff88007ac97300", - " R13: 0000000000000000 R14: 00007f571e104a80 R15: 00007f571e305048", - " ORIG_RAX: 0000000000000029 CS: 0033 SS: 002b", -+"", -+" The following three examples show the difference in the display of", -+" the same stack frame's contents using -f, -F, and -FF:", -+" ", -+" %s> bf -f", -+" ...", -+" #4 [ffff810072b47f10] vfs_write at ffffffff800789d8", -+" ffff810072b47f18: ffff81007e020380 ffff81007e2c2880 ", -+" ffff810072b47f28: 0000000000000002 fffffffffffffff7 ", -+" ffff810072b47f38: 00002b141825d000 ffffffff80078f75 ", -+" #5 [ffff810072b47f40] sys_write at ffffffff80078f75", -+" ...", -+" %s> bt -F", -+" ...", -+" #4 [ffff810072b47f10] vfs_write at ffffffff800789d8", -+" ffff810072b47f18: [files_cache] [filp] ", -+" ffff810072b47f28: 0000000000000002 fffffffffffffff7 ", -+" ffff810072b47f38: 00002b141825d000 sys_write+69 ", -+" #5 [ffff810072b47f40] sys_write at ffffffff80078f75", -+" ...", -+" %s> bf -FF", -+" ...", -+" #4 [ffff810072b47f10] vfs_write at ffffffff800789d8", -+" ffff810072b47f18: [ffff81007e020380:files_cache] [ffff81007e2c2880:filp]", -+" ffff810072b47f28: 0000000000000002 fffffffffffffff7 ", -+" ffff810072b47f38: 00002b141825d000 sys_write+69 ", -+" #5 [ffff810072b47f40] sys_write at ffffffff80078f75", -+" ...", - NULL - }; - ---- crash-7.0.2/cmdline.c.orig -+++ crash-7.0.2/cmdline.c -@@ -1,8 +1,8 @@ - /* cmdline.c - core analysis suite - * - * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc. -- * Copyright (C) 2002-2013 David Anderson -- * Copyright (C) 2002-2013 Red Hat, Inc. All rights reserved. -+ * Copyright (C) 2002-2014 David Anderson -+ * Copyright (C) 2002-2014 Red Hat, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by -@@ -1405,6 +1405,9 @@ exec_input_file(void) - } - - exec_command(); -+ -+ if (received_SIGINT()) -+ goto done_input; - } - - done_input: -@@ -2501,6 +2504,9 @@ exec_args_input_file(struct command_tabl - pc->cmd_cleanup(pc->cmd_cleanup_arg); - - free_all_bufs(); -+ -+ if (received_SIGINT()) -+ break; - } - - fclose(pc->args_ifile); ---- crash-7.0.2/defs.h.orig -+++ crash-7.0.2/defs.h -@@ -1,8 +1,8 @@ - /* defs.h - core analysis suite - * - * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc. -- * Copyright (C) 2002-2013 David Anderson -- * Copyright (C) 2002-2013 Red Hat, Inc. All rights reserved. -+ * Copyright (C) 2002-2014 David Anderson -+ * Copyright (C) 2002-2014 Red Hat, Inc. All rights reserved. - * Copyright (C) 2002 Silicon Graphics, Inc. - * - * This program is free software; you can redistribute it and/or modify -@@ -1043,34 +1043,35 @@ extern struct machdep_table *machdep; - #define MAX_FOREACH_ARGS (50) - #define MAX_REGEX_ARGS (10) - --#define FOREACH_CMD (0x1) --#define FOREACH_r_FLAG (0x2) --#define FOREACH_s_FLAG (0x4) --#define FOREACH_S_FLAG (0x8) --#define FOREACH_i_FLAG (0x10) --#define FOREACH_e_FLAG (0x20) --#define FOREACH_g_FLAG (0x40) --#define FOREACH_l_FLAG (0x80) --#define FOREACH_p_FLAG (0x100) --#define FOREACH_t_FLAG (0x200) --#define FOREACH_u_FLAG (0x400) --#define FOREACH_m_FLAG (0x800) --#define FOREACH_v_FLAG (0x1000) --#define FOREACH_KERNEL (0x2000) --#define FOREACH_USER (0x4000) --#define FOREACH_SPECIFIED (0x8000) --#define FOREACH_ACTIVE (0x10000) --#define FOREACH_k_FLAG (0x20000) --#define FOREACH_c_FLAG (0x40000) --#define FOREACH_f_FLAG (0x80000) --#define FOREACH_o_FLAG (0x100000) --#define FOREACH_T_FLAG (0x200000) --#define FOREACH_F_FLAG (0x400000) --#define FOREACH_x_FLAG (0x800000) --#define FOREACH_d_FLAG (0x1000000) --#define FOREACH_STATE (0x2000000) --#define FOREACH_a_FLAG (0x4000000) --#define FOREACH_G_FLAG (0x8000000) -+#define FOREACH_CMD (0x1) -+#define FOREACH_r_FLAG (0x2) -+#define FOREACH_s_FLAG (0x4) -+#define FOREACH_S_FLAG (0x8) -+#define FOREACH_i_FLAG (0x10) -+#define FOREACH_e_FLAG (0x20) -+#define FOREACH_g_FLAG (0x40) -+#define FOREACH_l_FLAG (0x80) -+#define FOREACH_p_FLAG (0x100) -+#define FOREACH_t_FLAG (0x200) -+#define FOREACH_u_FLAG (0x400) -+#define FOREACH_m_FLAG (0x800) -+#define FOREACH_v_FLAG (0x1000) -+#define FOREACH_KERNEL (0x2000) -+#define FOREACH_USER (0x4000) -+#define FOREACH_SPECIFIED (0x8000) -+#define FOREACH_ACTIVE (0x10000) -+#define FOREACH_k_FLAG (0x20000) -+#define FOREACH_c_FLAG (0x40000) -+#define FOREACH_f_FLAG (0x80000) -+#define FOREACH_o_FLAG (0x100000) -+#define FOREACH_T_FLAG (0x200000) -+#define FOREACH_F_FLAG (0x400000) -+#define FOREACH_x_FLAG (0x800000) -+#define FOREACH_d_FLAG (0x1000000) -+#define FOREACH_STATE (0x2000000) -+#define FOREACH_a_FLAG (0x4000000) -+#define FOREACH_G_FLAG (0x8000000) -+#define FOREACH_F_FLAG2 (0x10000000) - - #define FOREACH_PS_EXCLUSIVE \ - (FOREACH_g_FLAG|FOREACH_a_FLAG|FOREACH_t_FLAG|FOREACH_c_FLAG|FOREACH_p_FLAG|FOREACH_l_FLAG|FOREACH_r_FLAG) -@@ -4817,6 +4818,8 @@ ulong cpu_map_addr(const char *type); - #define BT_KDUMP_ELF_REGS (0x80000000000ULL) - #define BT_USER_SPACE (0x100000000000ULL) - #define BT_KERNEL_SPACE (0x200000000000ULL) -+#define BT_FULL_SYM_SLAB2 (0x400000000000ULL) -+#define BT_EFRAME_TARGET (0x800000000000ULL) - #define BT_SYMBOL_OFFSET (BT_SYMBOLIC_ARGS) - - #define BT_REF_HEXVAL (0x1) ---- crash-7.0.2/x86_64.c.orig -+++ crash-7.0.2/x86_64.c -@@ -1,7 +1,7 @@ - /* x86_64.c -- core analysis suite - * -- * Copyright (C) 2004-2013 David Anderson -- * Copyright (C) 2004-2013 Red Hat, Inc. All rights reserved. -+ * Copyright (C) 2004-2014 David Anderson -+ * Copyright (C) 2004-2014 Red Hat, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by -@@ -107,6 +107,7 @@ static ulong x86_64_get_stacktop_hyper(u - static int x86_64_framesize_cache_resize(void); - static int x86_64_framesize_cache_func(int, ulong, int *, int); - static ulong x86_64_get_framepointer(struct bt_info *, ulong); -+int search_for_eframe_target_caller(struct bt_info *, ulong, int *); - static int x86_64_get_framesize(struct bt_info *, ulong, ulong); - static void x86_64_framesize_debug(struct bt_info *); - static void x86_64_get_active_set(void); -@@ -3279,9 +3280,11 @@ in_exception_stack: - level++; - rsp += SIZE(pt_regs); - irq_eframe = 0; -+ bt->flags |= BT_EFRAME_TARGET; - if (bt->eframe_ip && ((framesize = x86_64_get_framesize(bt, - bt->eframe_ip, rsp)) >= 0)) - rsp += framesize; -+ bt->flags &= ~BT_EFRAME_TARGET; - } - level++; - } -@@ -4111,6 +4114,8 @@ x86_64_eframe_verify(struct bt_info *bt, - long rip, long rsp, long rflags) - { - int estack; -+ struct syment *sp; -+ ulong offset, exception; - - if ((rflags & RAZ_MASK) || !(rflags & 0x2)) - return FALSE; -@@ -4144,7 +4149,18 @@ x86_64_eframe_verify(struct bt_info *bt, - */ - if (STREQ(closest_symbol(rip), "ia32_sysenter_target")) - return TRUE; -- } -+ -+ if ((rip == 0) && INSTACK(rsp, bt) && -+ STREQ(bt->call_target, "ret_from_fork")) -+ return TRUE; -+ -+ if (readmem(kvaddr - 8, KVADDR, &exception, sizeof(ulong), -+ "exception type", RETURN_ON_ERROR|QUIET) && -+ (sp = value_search(exception, &offset)) && -+ STREQ(sp->name, "page_fault")) -+ return TRUE; -+ -+ } - - if ((cs == 0x10) && kvaddr) { - if (is_kernel_text(rip) && IS_KVADDR(rsp) && -@@ -7157,6 +7173,57 @@ x86_64_get_framepointer(struct bt_info * - return framepointer; - } - -+int -+search_for_eframe_target_caller(struct bt_info *bt, ulong stkptr, int *framesize) -+{ -+ int i; -+ ulong *up, offset, rsp; -+ struct syment *sp1, *sp2; -+ char *called_function; -+ -+ if ((sp1 = value_search(bt->eframe_ip, &offset))) -+ called_function = sp1->name; -+ else -+ return FALSE; -+ -+ rsp = stkptr; -+ -+ for (i = (rsp - bt->stackbase)/sizeof(ulong); -+ rsp < bt->stacktop; i++, rsp += sizeof(ulong)) { -+ -+ up = (ulong *)(&bt->stackbuf[i*sizeof(ulong)]); -+ -+ if (!is_kernel_text(*up)) -+ continue; -+ -+ if (!(sp1 = value_search(*up, &offset))) -+ continue; -+ -+ if (!offset && !(bt->flags & BT_FRAMESIZE_DISABLE)) -+ continue; -+ -+ /* -+ * Get the syment of the function that the text -+ * routine above called before leaving its return -+ * address on the stack -- if it can be determined. -+ */ -+ if ((sp2 = x86_64_function_called_by((*up)-5))) { -+ if (STREQ(sp2->name, called_function)) { -+ if (CRASHDEBUG(1)) { -+ fprintf(fp, -+ "< %lx/%s rsp: %lx caller: %s >\n", -+ bt->eframe_ip, called_function, -+ stkptr, sp1->name); -+ } -+ *framesize = rsp - stkptr; -+ return TRUE; -+ } -+ } -+ } -+ -+ return FALSE; -+} -+ - #define BT_FRAMESIZE_IGNORE_MASK \ - (BT_OLD_BACK_TRACE|BT_TEXT_SYMBOLS|BT_TEXT_SYMBOLS_ALL|BT_FRAMESIZE_DISABLE) - -@@ -7190,6 +7257,10 @@ x86_64_get_framesize(struct bt_info *bt, - - exception = bt->eframe_ip == textaddr ? TRUE : FALSE; - -+ if ((bt->flags & BT_EFRAME_TARGET) && -+ search_for_eframe_target_caller(bt, rsp, &framesize)) -+ return framesize; -+ - if (!(bt->flags & BT_FRAMESIZE_DEBUG) && - x86_64_framesize_cache_func(FRAMESIZE_QUERY, textaddr, &framesize, - exception)) { ---- crash-7.0.2/memory.c.orig -+++ crash-7.0.2/memory.c -@@ -288,6 +288,7 @@ static ulong kmem_cache_nodelists(ulong) - #define NET_ENDIAN (0x4000) - #define DISPLAY_RAW (0x8000) - #define NO_ERROR (0x10000) -+#define SLAB_CACHE2 (0x20000) - #define DISPLAY_TYPES (DISPLAY_RAW|DISPLAY_ASCII|DISPLAY_8|\ - DISPLAY_16|DISPLAY_32|DISPLAY_64) - -@@ -1147,8 +1148,12 @@ cmd_rd(void) - case 'S': - if (flag & DISPLAY_DEFAULT) { - flag |= SYMBOLIC; -- if (c == 'S') -- flag |= SLAB_CACHE; -+ if (c == 'S') { -+ if (flag & SLAB_CACHE) -+ flag |= SLAB_CACHE2; -+ else -+ flag |= SLAB_CACHE; -+ } - } else { - error(INFO, "-%c option" - " is only allowed with %d-bit display\n", -@@ -1475,7 +1480,7 @@ display_memory(ulonglong addr, long coun - if ((flag & SLAB_CACHE) && - vaddr_to_kmem_cache(mem.u64, slab, - !VERBOSE)) { -- if (CRASHDEBUG(1)) -+ if ((flag & SLAB_CACHE2) || CRASHDEBUG(1)) - sprintf(buf, "[%llx:%s]", - (ulonglong)mem.u64, - slab); -@@ -1512,7 +1517,7 @@ display_memory(ulonglong addr, long coun - if ((flag & SLAB_CACHE) && - vaddr_to_kmem_cache(mem.u32, slab, - !VERBOSE)) { -- if (CRASHDEBUG(1)) -+ if ((flag & SLAB_CACHE2) || CRASHDEBUG(1)) - sprintf(buf, "[%x:%s]", - mem.u32, slab); - else -@@ -1854,7 +1859,7 @@ format_stack_entry(struct bt_info *bt, c - sprintf(retbuf, INT_PRLEN == 16 ? - "%-16s" : "%-8s", buf); - else if (vaddr_to_kmem_cache(value, slab, !VERBOSE)) { -- if (CRASHDEBUG(1)) -+ if ((bt->flags & BT_FULL_SYM_SLAB2) || CRASHDEBUG(1)) - sprintf(buf, "[%lx:%s]", value, slab); - else - sprintf(buf, "[%s]", slab); -@@ -1871,7 +1876,7 @@ format_stack_entry(struct bt_info *bt, c - strlen(value_to_symstr(value, buf, 0))) - sprintf(retbuf, "%-16s", buf); - else if (vaddr_to_kmem_cache(value, slab, !VERBOSE)) { -- if (CRASHDEBUG(1)) -+ if ((bt->flags & BT_FULL_SYM_SLAB2) || CRASHDEBUG(1)) - sprintf(buf, "[%lx:%s]", value, slab); - else - sprintf(buf, "[%s]", slab); diff --git a/SOURCES/bt-mislabeling.patch b/SOURCES/bt-mislabeling.patch new file mode 100644 index 0000000..203f0e4 --- /dev/null +++ b/SOURCES/bt-mislabeling.patch @@ -0,0 +1,257 @@ +--- crash-7.0.9/defs.h.orig ++++ crash-7.0.9/defs.h +@@ -5180,14 +5180,15 @@ struct x86_64_pt_regs_offsets { + }; + + #define MAX_EXCEPTION_STACKS 7 +-#define NMI_STACK 2 /* ebase[] index to NMI exception stack */ +-#define DEBUG_STACK 3 /* ebase[] index to DEBUG exception stack */ ++#define NMI_STACK (machdep->machspec->stkinfo.NMI_stack_index) + + struct x86_64_stkinfo { + ulong ebase[NR_CPUS][MAX_EXCEPTION_STACKS]; + int esize[MAX_EXCEPTION_STACKS]; + ulong ibase[NR_CPUS]; + int isize; ++ int NMI_stack_index; ++ char *exception_stacks[MAX_EXCEPTION_STACKS]; + }; + + struct machine_specific { +--- crash-7.0.9/x86_64.c.orig ++++ crash-7.0.9/x86_64.c +@@ -114,6 +114,7 @@ static void x86_64_get_active_set(void); + static int x86_64_get_kvaddr_ranges(struct vaddr_range *); + static int x86_64_verify_paddr(uint64_t); + static void GART_init(void); ++static void x86_64_exception_stacks_init(void); + + struct machine_specific x86_64_machine_specific = { 0 }; + +@@ -798,6 +799,14 @@ x86_64_dump_machdep_table(ulong arg) + ms->stkinfo.esize[5], + ms->stkinfo.esize[6], + machdep->flags & NO_TSS ? " (NO TSS) " : " "); ++ ++ fprintf(fp, " NMI_stack_index: %d\n", ++ ms->stkinfo.NMI_stack_index); ++ fprintf(fp, " exception_stacks:\n"); ++ for (i = 0; i < MAX_EXCEPTION_STACKS; i++) ++ fprintf(fp, " [%d]: %s\n", i, ++ ms->stkinfo.exception_stacks[i]); ++ + fprintf(fp, " ebase[%s][%d]:", + arg ? "NR_CPUS" : "cpus", MAX_EXCEPTION_STACKS); + cpus = arg ? NR_CPUS : kt->cpus; +@@ -1059,17 +1068,6 @@ x86_64_per_cpu_init(void) + verify_spinlock(); + } + +-static char * +-x86_64_exception_stacks[MAX_EXCEPTION_STACKS] = { +- "STACKFAULT", +- "DOUBLEFAULT", +- "NMI", +- "DEBUG", +- "MCE", +- "(unknown)", +- "(unknown)" +-}; +- + /* + * Gather the ist addresses for each CPU. + */ +@@ -1086,6 +1084,8 @@ x86_64_ist_init(void) + tss_sp = per_cpu_symbol_search("per_cpu__init_tss"); + ist_sp = per_cpu_symbol_search("per_cpu__orig_ist"); + ++ x86_64_exception_stacks_init(); ++ + if (!tss_sp && symbol_exists("init_tss")) { + init_tss = symbol_value("init_tss"); + +@@ -1135,7 +1135,7 @@ x86_64_ist_init(void) + if (ms->stkinfo.ebase[c][i] != estacks[i]) + error(WARNING, + "cpu %d %s stack: init_tss: %lx orig_ist: %lx\n", c, +- x86_64_exception_stacks[i], ++ ms->stkinfo.exception_stacks[i], + ms->stkinfo.ebase[c][i], estacks[i]); + ms->stkinfo.ebase[c][i] = estacks[i]; + } +@@ -1165,22 +1165,12 @@ x86_64_ist_init(void) + break; + cnt++; + if ((THIS_KERNEL_VERSION >= LINUX(2,6,18)) && +- (i == DEBUG_STACK)) ++ STREQ(ms->stkinfo.exception_stacks[i], "DEBUG")) + ms->stkinfo.esize[i] = esize*2; + else + ms->stkinfo.esize[i] = esize; + ms->stkinfo.ebase[c][i] -= ms->stkinfo.esize[i]; + } +- /* +- * RT kernel only uses 3 exception stacks for the 5 types. +- */ +- if ((c == 0) && (cnt == 3)) { +- x86_64_exception_stacks[0] = "RT"; +- x86_64_exception_stacks[1] = "RT"; +- x86_64_exception_stacks[2] = "RT"; +- x86_64_exception_stacks[3] = "(unknown)"; +- x86_64_exception_stacks[4] = "(unknown)"; +- } + } + + /* +@@ -2351,7 +2341,7 @@ x86_64_eframe_search(struct bt_info *bt) + break; + bt->hp->esp = ms->stkinfo.ebase[c][i]; + fprintf(fp, "CPU %d %s EXCEPTION STACK:", +- c, x86_64_exception_stacks[i]); ++ c, ms->stkinfo.exception_stacks[i]); + + if (hide_offline_cpu(c)) { + fprintf(fp, " [OFFLINE]\n\n"); +@@ -3084,7 +3074,7 @@ in_exception_stack: + + if (!BT_REFERENCE_CHECK(bt)) + fprintf(fp, "--- <%s exception stack> ---\n", +- x86_64_exception_stacks[estack_index]); ++ ms->stkinfo.exception_stacks[estack_index]); + + /* + * Find the CPU-saved, or handler-saved registers +@@ -3133,7 +3123,7 @@ in_exception_stack: + fprintf(ofp, + " [ %s exception stack recursion: " + "prior stack location overwritten ]\n", +- x86_64_exception_stacks[estack_index]); ++ ms->stkinfo.exception_stacks[estack_index]); + return; + } + +@@ -4540,12 +4530,12 @@ skip_stage: + bt->stacktop = ms->stkinfo.ebase[bt->tc->processor][estack] + + ms->stkinfo.esize[estack]; + console("x86_64_get_dumpfile_stack_frame: searching %s estack at %lx\n", +- x86_64_exception_stacks[estack], bt->stackbase); ++ ms->stkinfo.exception_stacks[estack], bt->stackbase); + if (!(bt->stackbase)) + goto skip_stage; + bt->stackbuf = ms->irqstack; + alter_stackbuf(bt); +- in_nmi_stack = STREQ(x86_64_exception_stacks[estack], "NMI"); ++ in_nmi_stack = STREQ(ms->stkinfo.exception_stacks[estack], "NMI"); + goto next_stack; + + } +@@ -4772,6 +4762,69 @@ x86_64_display_idt_table(void) + FREEBUF(idt_table_buf); + } + ++static void ++x86_64_exception_stacks_init(void) ++{ ++ char *idt_table_buf; ++ char buf[BUFSIZE]; ++ int i; ++ ulong *ip, ist; ++ long size; ++ struct machine_specific *ms; ++ ++ ms = machdep->machspec; ++ ++ ms->stkinfo.NMI_stack_index = -1; ++ for (i = 0; i < MAX_EXCEPTION_STACKS; i++) ++ ms->stkinfo.exception_stacks[i] = "(unknown)"; ++ ++ if (!kernel_symbol_exists("idt_table")) ++ return; ++ ++ if (INVALID_SIZE(gate_struct)) ++ size = 16; ++ else ++ size = SIZE(gate_struct); ++ ++ idt_table_buf = GETBUF(size * 256); ++ readmem(symbol_value("idt_table"), KVADDR, idt_table_buf, ++ size * 256, "idt_table", FAULT_ON_ERROR); ++ ip = (ulong *)idt_table_buf; ++ ++ if (CRASHDEBUG(1)) ++ fprintf(fp, "exception IST:\n"); ++ ++ for (i = 0; i < 256; i++, ip += 2) { ++ ist = ((*ip) >> 32) & 0x7; ++ if (ist) { ++ x86_64_extract_idt_function(ip, buf, NULL); ++ if (CRASHDEBUG(1)) ++ fprintf(fp, " %ld: %s\n", ist, buf); ++ if (strstr(buf, "nmi")) { ++ ms->stkinfo.NMI_stack_index = ist-1; ++ ms->stkinfo.exception_stacks[ist-1] = "NMI"; ++ } ++ if (strstr(buf, "debug")) ++ ms->stkinfo.exception_stacks[ist-1] = "DEBUG"; ++ if (strstr(buf, "stack")) ++ ms->stkinfo.exception_stacks[ist-1] = "STACKFAULT"; ++ if (strstr(buf, "double")) ++ ms->stkinfo.exception_stacks[ist-1] = "DOUBLEFAULT"; ++ if (strstr(buf, "machine")) ++ ms->stkinfo.exception_stacks[ist-1] = "MCE"; ++ } ++ } ++ ++ if (CRASHDEBUG(1)) { ++ fprintf(fp, "exception stacks:\n"); ++ for (i = 0; i < MAX_EXCEPTION_STACKS; i++) ++ fprintf(fp, " [%d]: %s\n", i, ms->stkinfo.exception_stacks[i]); ++ } ++ ++ FREEBUF(idt_table_buf); ++} ++ ++ + /* + * Extract the function name out of the IDT entry. + */ +@@ -5103,9 +5156,9 @@ x86_64_display_machine_stats(void) + if (machdep->machspec->stkinfo.ebase[0][i] == 0) + break; + fprintf(fp, "%11s STACK SIZE: %d\n", +- x86_64_exception_stacks[i], ++ machdep->machspec->stkinfo.exception_stacks[i], + machdep->machspec->stkinfo.esize[i]); +- sprintf(buf, "%s STACKS:\n", x86_64_exception_stacks[i]); ++ sprintf(buf, "%s STACKS:\n", machdep->machspec->stkinfo.exception_stacks[i]); + fprintf(fp, "%24s", buf); + for (c = 0; c < kt->cpus; c++) { + if (machdep->machspec->stkinfo.ebase[c][i] == 0) + +--- crash-7.0.9/memory.c.orig ++++ crash-7.0.9/memory.c +@@ -8632,8 +8632,7 @@ static char * + vaddr_to_kmem_cache(ulong vaddr, char *buf, int verbose) + { + physaddr_t paddr; +- ulong page; +- ulong cache; ++ ulong page, cache, page_flags; + + if (!kvtop(NULL, vaddr, &paddr, 0)) { + if (verbose) +@@ -8651,6 +8650,14 @@ vaddr_to_kmem_cache(ulong vaddr, char *b + return NULL; + } + ++ if (vt->PG_slab) { ++ readmem(page+OFFSET(page_flags), KVADDR, ++ &page_flags, sizeof(ulong), "page.flags", ++ FAULT_ON_ERROR); ++ if (!(page_flags & (1 << vt->PG_slab))) ++ return NULL; ++ } ++ + if ((vt->flags & KMALLOC_SLUB) || + ((vt->flags & KMALLOC_COMMON) && + VALID_MEMBER(page_slab) && VALID_MEMBER(page_first_page))) { diff --git a/SOURCES/fix-ps-performance-on-live-system.patch b/SOURCES/fix-ps-performance-on-live-system.patch deleted file mode 100644 index 2398c88..0000000 --- a/SOURCES/fix-ps-performance-on-live-system.patch +++ /dev/null @@ -1,139 +0,0 @@ -commit a3a441aeabd6c5c3c86b4793a283927507a5cc10 -Author: Dave Anderson -Date: Mon Sep 22 16:25:16 2014 -0400 - - Fix for the "ps" command performance degradation patch the was - introduced in crash-7.0.8. Without this patch, it is possible that - the "ps" command may fail prematurely with the error message - "ps: bsearch for tgid failed: task:
tgid: " - when running on a live system or against a "live" dumpfile. - (panfy.fnst@cn.fujitsu.com) - -diff --git a/memory.c b/memory.c -index 518c917..2376e6f 100644 ---- a/memory.c -+++ b/memory.c -@@ -4187,54 +4187,52 @@ get_task_mem_usage(ulong task, struct task_mem_usage *tm) - tg = (struct tgid_context *)bsearch(&tgid, tgid_array, RUNNING_TASKS(), - sizeof(struct tgid_context), sort_by_tgid); - -- if (tg == NULL) -- error(FATAL, "bsearch for tgid failed: task: %lx tgid: %ld\n", -- task, tgid.tgid); -- -- /* find the first element which has the same tgid */ -- first = tg; -- while ((first > tgid_array) && ((first - 1)->tgid == first->tgid)) -- first--; -- -- /* find the last element which have same tgid */ -- last = tg; -- while ((last < (tgid_array + (RUNNING_TASKS() - 1))) && -- (last->tgid == (last + 1)->tgid)) -- last++; -- -- while (first <= last) -- { -- /* count 0 -> filepages */ -- if (!readmem(first->task + -- OFFSET(task_struct_rss_stat) + -- OFFSET(task_rss_stat_count), KVADDR, -- &sync_rss, -- sizeof(int), -- "task_struct rss_stat MM_FILEPAGES", -- RETURN_ON_ERROR)) -- continue; -+ if (tg) { -+ /* find the first element which has the same tgid */ -+ first = tg; -+ while ((first > tgid_array) && ((first - 1)->tgid == first->tgid)) -+ first--; -+ -+ /* find the last element which have same tgid */ -+ last = tg; -+ while ((last < (tgid_array + (RUNNING_TASKS() - 1))) && -+ (last->tgid == (last + 1)->tgid)) -+ last++; -+ -+ while (first <= last) -+ { -+ /* count 0 -> filepages */ -+ if (!readmem(first->task + -+ OFFSET(task_struct_rss_stat) + -+ OFFSET(task_rss_stat_count), KVADDR, -+ &sync_rss, -+ sizeof(int), -+ "task_struct rss_stat MM_FILEPAGES", -+ RETURN_ON_ERROR)) -+ continue; - -- rss += sync_rss; -- -- /* count 1 -> anonpages */ -- if (!readmem(first->task + -- OFFSET(task_struct_rss_stat) + -- OFFSET(task_rss_stat_count) + -- sizeof(int), -- KVADDR, &sync_rss, -- sizeof(int), -- "task_struct rss_stat MM_ANONPAGES", -- RETURN_ON_ERROR)) -- continue; -+ rss += sync_rss; -+ -+ /* count 1 -> anonpages */ -+ if (!readmem(first->task + -+ OFFSET(task_struct_rss_stat) + -+ OFFSET(task_rss_stat_count) + -+ sizeof(int), -+ KVADDR, &sync_rss, -+ sizeof(int), -+ "task_struct rss_stat MM_ANONPAGES", -+ RETURN_ON_ERROR)) -+ continue; - -- rss += sync_rss; -+ rss += sync_rss; - -- if(first == last) -- break; -- first++; -- } -+ if (first == last) -+ break; -+ first++; -+ } - -- tt->last_tgid = last; -+ tt->last_tgid = last; -+ } - } - - /* - - -commit 62b294b27ce08decb63b204aeb9c6d3d5ace96b2 -Author: Dave Anderson -Date: Fri Sep 19 14:20:57 2014 -0400 - - Fix for the one-time (dumpfile), or as-required (live system), - gathering of tasks from the kernel pid_hash[] in 2.6.24 and later - kernels. Without the patch, if an entry in a pid_hash[] chain is - not related to the "init_pid_ns" pid_namespace structure, any - remaining entries in the hlist chain are skipped. - (vvs@parallels.com) - -diff --git a/task.c b/task.c -index b33c96a..66f2e0a 100644 ---- a/task.c -+++ b/task.c -@@ -2033,7 +2033,7 @@ do_chained: - * Use init_pid_ns level 0 (PIDTYPE_PID). - */ - if (upid_ns != tt->init_pid_ns) -- continue; -+ goto chain_next; - - pid = upid - OFFSET(pid_numbers); - - diff --git a/SOURCES/kmem-S-CONFIG_SLUB.patch b/SOURCES/kmem-S-CONFIG_SLUB.patch deleted file mode 100644 index 52542eb..0000000 --- a/SOURCES/kmem-S-CONFIG_SLUB.patch +++ /dev/null @@ -1,84 +0,0 @@ ---- crash-7.0.2/memory.c.orig -+++ crash-7.0.2/memory.c -@@ -1,8 +1,8 @@ - /* memory.c - core analysis suite - * - * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc. -- * Copyright (C) 2002-2013 David Anderson -- * Copyright (C) 2002-2013 Red Hat, Inc. All rights reserved. -+ * Copyright (C) 2002-2014 David Anderson -+ * Copyright (C) 2002-2014 Red Hat, Inc. All rights reserved. - * Copyright (C) 2002 Silicon Graphics, Inc. - * - * This program is free software; you can redistribute it and/or modify -@@ -4162,6 +4162,8 @@ get_task_mem_usage(ulong task, struct ta - #define SLAB_FIRST_NODE (ADDRESS_SPECIFIED << 22) - #define CACHE_SET (ADDRESS_SPECIFIED << 23) - -+#define SLAB_BITFIELD (ADDRESS_SPECIFIED << 25) -+ - #define GET_ALL \ - (GET_SHARED_PAGES|GET_TOTALRAM_PAGES|GET_BUFFERS_PAGES|GET_SLAB_PAGES) - -@@ -16312,6 +16314,10 @@ dump_kmem_cache_slub(struct meminfo *si) - si->cache_count = get_kmem_cache_list(&si->cache_list); - si->cache_buf = GETBUF(SIZE(kmem_cache)); - -+ if (VALID_MEMBER(page_objects) && -+ OFFSET(page_objects) == OFFSET(page_inuse)) -+ si->flags |= SLAB_BITFIELD; -+ - if (!si->reqname && - !(si->flags & (ADDRESS_SPECIFIED|GET_SLAB_PAGES))) - fprintf(fp, "%s", kmem_cache_hdr); -@@ -16613,7 +16619,7 @@ static void - do_slab_slub(struct meminfo *si, int verbose) - { - physaddr_t paddr; -- ulong vaddr; -+ ulong vaddr, objects_vaddr; - ushort inuse, objects; - ulong freelist, cpu_freelist, cpu_slab_ptr; - int i, cpu_slab, is_free, node; -@@ -16652,9 +16658,23 @@ do_slab_slub(struct meminfo *si, int ver - * is kept in the slab. - */ - if (VALID_MEMBER(page_objects)) { -- if (!readmem(si->slab + OFFSET(page_objects), KVADDR, &objects, -+ objects_vaddr = si->slab + OFFSET(page_objects); -+ if (si->flags & SLAB_BITFIELD) -+ objects_vaddr += sizeof(ushort); -+ if (!readmem(objects_vaddr, KVADDR, &objects, - sizeof(ushort), "page.objects", RETURN_ON_ERROR)) - return; -+ /* -+ * Strip page.frozen bit. -+ */ -+ if (si->flags & SLAB_BITFIELD) { -+ if (__BYTE_ORDER == __LITTLE_ENDIAN) { -+ objects <<= 1; -+ objects >>= 1; -+ } -+ if (__BYTE_ORDER == __BIG_ENDIAN) -+ objects >>= 1; -+ } - - if (CRASHDEBUG(1) && (objects != si->objects)) - error(NOTE, "%s: slab: %lx oo objects: %ld " -@@ -16678,14 +16698,11 @@ do_slab_slub(struct meminfo *si, int ver - cpu_slab = i; - /* - * Later slub scheme uses the per-cpu freelist -- * and keeps page->inuse maxed out, so count -- * the free objects by hand. -+ * so count the free objects by hand. - */ - if (cpu_freelist) - freelist = cpu_freelist; -- if ((si->objects - inuse) == 0) -- inuse = si->objects - -- count_free_objects(si, freelist); -+ inuse = si->objects - count_free_objects(si, freelist); - break; - } - } diff --git a/SOURCES/ppc64_bt_active_task.patch b/SOURCES/ppc64_bt_active_task.patch new file mode 100644 index 0000000..5193844 --- /dev/null +++ b/SOURCES/ppc64_bt_active_task.patch @@ -0,0 +1,95 @@ +--- crash-7.0.9/ppc64.c.orig ++++ crash-7.0.9/ppc64.c +@@ -1,7 +1,7 @@ + /* ppc64.c -- core analysis suite + * +- * Copyright (C) 2004-2014 David Anderson +- * Copyright (C) 2004-2014 Red Hat, Inc. All rights reserved. ++ * Copyright (C) 2004-2015 David Anderson ++ * Copyright (C) 2004-2015 Red Hat, Inc. All rights reserved. + * Copyright (C) 2004, 2006 Haren Myneni, IBM Corporation + * + * This program is free software; you can redistribute it and/or modify +@@ -414,7 +414,7 @@ ppc64_init(int when) + break; + + case LOG_ONLY: +- machdep->kvbase = kt->vmcoreinfo._stext_SYMBOL; ++ machdep->identity_map_base = kt->vmcoreinfo._stext_SYMBOL; + break; + } + } +@@ -1898,8 +1898,8 @@ ppc64_print_regs(struct ppc64_pt_regs *r + int i; + + /* print out the gprs... */ +- for(i=0; i<32; i++) { +- if(!(i % 3)) ++ for (i=0; i<32; i++) { ++ if (i && !(i % 3)) + fprintf(fp, "\n"); + + fprintf(fp, " R%d:%s %016lx ", i, +@@ -1940,9 +1940,8 @@ ppc64_print_eframe(char *efrm_str, struc + if (BT_REFERENCE_CHECK(bt)) + return; + +- fprintf(fp, " %s [%lx] exception frame:", efrm_str, regs->trap); ++ fprintf(fp, " %s [%lx] exception frame:\n", efrm_str, regs->trap); + ppc64_print_regs(regs); +- fprintf(fp, "\n"); + } + + /* +@@ -1996,8 +1995,6 @@ ppc64_kdump_stack_frame(struct bt_info * + fprintf(fp, " LR [%016lx] %s\n", pt_regs->link, + closest_symbol(pt_regs->link)); + +- fprintf(fp, "\n"); +- + return TRUE; + } + +@@ -2008,7 +2005,7 @@ static int + ppc64_get_dumpfile_stack_frame(struct bt_info *bt_in, ulong *nip, ulong *ksp) + { + int panic_task; +- int i, panic; ++ int i; + char *sym; + ulong *up; + struct bt_info bt_local, *bt; +@@ -2092,10 +2089,8 @@ ppc64_get_dumpfile_stack_frame(struct bt + fprintf(fp, "Could not find SP for task %0lx\n", + bt->task); + } +- return TRUE; + } + +- panic = FALSE; + /* + * Check the process stack first. We are scanning stack for only + * panic task. Even though we have dumping CPU's regs, we will be +@@ -2112,8 +2107,12 @@ retry: + if (STREQ(sym, ".netconsole_netdump") || + STREQ(sym, ".netpoll_start_netdump") || + STREQ(sym, ".start_disk_dump") || ++ STREQ(sym, "crash_kexec") || ++ STREQ(sym, "crash_fadump") || ++ STREQ(sym, "crash_ipi_callback") || + STREQ(sym, ".crash_kexec") || + STREQ(sym, ".crash_fadump") || ++ STREQ(sym, ".crash_ipi_callback") || + STREQ(sym, ".disk_dump")) { + *nip = *up; + *ksp = bt->stackbase + +@@ -2122,9 +2121,6 @@ retry: + } + } + +- if (panic) +- return TRUE; +- + bt->flags &= ~(BT_HARDIRQ|BT_SOFTIRQ); + + if (check_hardirq && diff --git a/SOURCES/ps-performance.patch b/SOURCES/ps-performance.patch deleted file mode 100644 index df54183..0000000 --- a/SOURCES/ps-performance.patch +++ /dev/null @@ -1,357 +0,0 @@ ---- crash-7.0.2/task.c.orig -+++ crash-7.0.2/task.c -@@ -489,6 +489,7 @@ task_init(void) - } - - sort_context_array(); -+ sort_tgid_array(); - - if (pc->flags & SILENT) - initialize_task_state(); -@@ -635,6 +636,11 @@ allocate_task_space(int cnt) - malloc(cnt * sizeof(struct task_context)))) - error(FATAL, "cannot malloc context array (%d tasks)", - cnt); -+ if (!(tt->tgid_array = (struct tgid_context *) -+ malloc(cnt * sizeof(struct tgid_context)))) -+ error(FATAL, "cannot malloc tgid array (%d tasks)", -+ cnt); -+ - } else { - if (!(tt->task_local = (void *) - realloc(tt->task_local, cnt * sizeof(void *)))) -@@ -648,6 +654,13 @@ allocate_task_space(int cnt) - error(FATAL, - "%scannot realloc context array (%d tasks)", - (pc->flags & RUNTIME) ? "" : "\n", cnt); -+ -+ if (!(tt->tgid_array = (struct tgid_context *) -+ realloc(tt->tgid_array, -+ cnt * sizeof(struct tgid_context)))) -+ error(FATAL, -+ "%scannot realloc tgid array (%d tasks)", -+ (pc->flags & RUNTIME) ? "" : "\n", cnt); - } - } - -@@ -2272,13 +2285,14 @@ retry_active: - static struct task_context * - store_context(struct task_context *tc, ulong task, char *tp) - { -- pid_t *pid_addr; -+ pid_t *pid_addr, *tgid_addr; - char *comm_addr; - int *processor_addr; - ulong *parent_addr; - ulong *mm_addr; - int has_cpu; - int do_verify; -+ struct tgid_context *tg; - - processor_addr = NULL; - -@@ -2301,6 +2315,7 @@ store_context(struct task_context *tc, u - tc = tt->context_array + tt->running_tasks; - - pid_addr = (pid_t *)(tp + OFFSET(task_struct_pid)); -+ tgid_addr = (pid_t *)(tp + OFFSET(task_struct_tgid)); - comm_addr = (char *)(tp + OFFSET(task_struct_comm)); - if (tt->flags & THREAD_INFO) { - tc->thread_info = ULONG(tp + OFFSET(task_struct_thread_info)); -@@ -2326,6 +2341,14 @@ store_context(struct task_context *tc, u - tc->task = task; - tc->tc_next = NULL; - -+ /* -+ * Fill a tgid_context structure with the data from -+ * the incoming task. -+ */ -+ tg = tt->tgid_array + tt->running_tasks; -+ tg->tgid = *tgid_addr; -+ tg->task = task; -+ - if (do_verify && !verify_task(tc, do_verify)) { - error(INFO, "invalid task address: %lx\n", tc->task); - BZERO(tc, sizeof(struct task_context)); -@@ -2441,6 +2464,33 @@ sort_context_array_by_last_run(void) - } - - /* -+ * Set the tgid_context array by tgid number. -+ */ -+void -+sort_tgid_array(void) -+{ -+ if (VALID_MEMBER(mm_struct_rss) || (!VALID_MEMBER(task_struct_rss_stat))) -+ return; -+ -+ qsort((void *)tt->tgid_array, (size_t)tt->running_tasks, -+ sizeof(struct tgid_context), sort_by_tgid); -+ -+ tt->last_tgid = tt->tgid_array; -+} -+ -+int -+sort_by_tgid(const void *arg1, const void *arg2) -+{ -+ struct tgid_context *t1, *t2; -+ -+ t1 = (struct tgid_context *)arg1; -+ t2 = (struct tgid_context *)arg2; -+ -+ return (t1->tgid < t2->tgid ? -1 : -+ t1->tgid == t2->tgid ? 0 : 1); -+} -+ -+/* - * Keep a stash of the last task_struct accessed. Chances are it will - * be hit several times before the next task is accessed. - */ -@@ -6320,6 +6370,7 @@ dump_task_table(int verbose) - { - int i, j, more, nr_cpus; - struct task_context *tc; -+ struct tgid_context *tg; - char buf[BUFSIZE]; - int others, wrap, flen; - -@@ -6340,6 +6391,12 @@ dump_task_table(int verbose) - fprintf(fp, " .tc_next: %lx\n", (ulong)tc->tc_next); - } - fprintf(fp, " context_array: %lx\n", (ulong)tt->context_array); -+ fprintf(fp, " tgid_array: %lx\n", (ulong)tt->tgid_array); -+ fprintf(fp, " tgid_searches: %ld\n", tt->tgid_searches); -+ fprintf(fp, " tgid_cache_hits: %ld (%ld%%)\n", tt->tgid_cache_hits, -+ tt->tgid_searches ? -+ tt->tgid_cache_hits * 100 / tt->tgid_searches : 0); -+ fprintf(fp, " last_tgid: %lx\n", (ulong)tt->last_tgid); - fprintf(fp, "refresh_task_table: "); - if (tt->refresh_task_table == refresh_fixed_task_table) - fprintf(fp, "refresh_fixed_task_table()\n"); -@@ -6434,6 +6491,8 @@ dump_task_table(int verbose) - fprintf(fp, " task_struct: %lx\n", (ulong)tt->task_struct); - fprintf(fp, " mm_struct: %lx\n", (ulong)tt->mm_struct); - fprintf(fp, " init_pid_ns: %lx\n", tt->init_pid_ns); -+ fprintf(fp, " filepages: %ld\n", tt->filepages); -+ fprintf(fp, " anonpages: %ld\n", tt->anonpages); - - - wrap = sizeof(void *) == SIZEOF_32BIT ? 8 : 4; -@@ -6649,6 +6708,13 @@ dump_task_table(int verbose) - i, tc->task, tc->pid, tc->processor, tc->ptask, - (ulong)tc->mm_struct, tc->comm); - } -+ -+ fprintf(fp, "\nINDEX TASK TGID (COMM)\n"); -+ for (i = 0; i < RUNNING_TASKS(); i++) { -+ tg = &tt->tgid_array[i]; -+ tc = task_to_context(tg->task); -+ fprintf(fp, "[%3d] %lx %ld (%s)\n", i, tg->task, tg->tgid, tc->comm); -+ } - } - - /* ---- crash-7.0.2/main.c.orig -+++ crash-7.0.2/main.c -@@ -747,6 +747,7 @@ reattempt: - } else if (!(pc->flags & MINIMAL_MODE)) { - tt->refresh_task_table(); - sort_context_array(); -+ sort_tgid_array(); - } - } - if (!STREQ(pc->curcmd, pc->program_name)) ---- crash-7.0.2/defs.h.orig -+++ crash-7.0.2/defs.h -@@ -749,6 +749,11 @@ struct task_context { - struct task_context *tc_next; - }; - -+struct tgid_context { /* tgid and task stored for each task */ -+ ulong tgid; -+ ulong task; -+}; -+ - struct task_table { /* kernel/local task table data */ - struct task_context *current; - struct task_context *context_array; -@@ -782,6 +787,12 @@ struct task_table { - char *thread_info; - char *mm_struct; - ulong init_pid_ns; -+ struct tgid_context *tgid_array; -+ struct tgid_context *last_tgid; -+ ulong tgid_searches; -+ ulong tgid_cache_hits; -+ long filepages; -+ long anonpages; - }; - - #define TASK_INIT_DONE (0x1) -@@ -4710,6 +4721,8 @@ ulong generic_get_stackbase(ulong); - ulong generic_get_stacktop(ulong); - void dump_task_table(int); - void sort_context_array(void); -+void sort_tgid_array(void); -+int sort_by_tgid(const void *, const void *); - int in_irq_ctx(ulonglong, int, ulong); - - /* ---- crash-7.0.2/memory.c.orig -+++ crash-7.0.2/memory.c -@@ -215,6 +215,7 @@ static int next_module_vaddr(ulong, ulon - static int next_identity_mapping(ulong, ulong *); - static int vm_area_page_dump(ulong, ulong, ulong, ulong, ulong, - struct reference *); -+static void rss_page_types_init(void); - static int dump_swap_info(ulong, ulong *, ulong *); - static void swap_info_init(void); - static char *get_swapdev(ulong, char *); -@@ -1040,6 +1041,8 @@ vm_init(void) - - page_flags_init(); - -+ rss_page_types_init(); -+ - vt->flags |= VM_INIT; - } - -@@ -4001,6 +4004,54 @@ in_user_stack(ulong task, ulong vaddr) - } - - /* -+ * Set the const value of filepages and anonpages -+ * according to MM_FILEPAGES and MM_ANONPAGES. -+ */ -+static void -+rss_page_types_init(void) -+{ -+ long anonpages, filepages; -+ -+ if (VALID_MEMBER(mm_struct_rss)) -+ return; -+ -+ if (VALID_MEMBER(mm_struct_rss_stat)) -+ { -+ if (!enumerator_value("MM_FILEPAGES", &filepages) || -+ !enumerator_value("MM_ANONPAGES", &anonpages)) -+ { -+ filepages = 0; -+ anonpages = 1; -+ } -+ tt->filepages = filepages; -+ tt->anonpages = anonpages; -+ } -+} -+ -+static struct tgid_context * -+tgid_quick_search(ulong tgid) -+{ -+ struct tgid_context *last, *next; -+ -+ tt->tgid_searches++; -+ -+ last = tt->last_tgid; -+ if (tgid == last->tgid) { -+ tt->tgid_cache_hits++; -+ return last; -+ } -+ -+ next = last + 1; -+ if ((next < (tt->tgid_array + RUNNING_TASKS())) && -+ (tgid == next->tgid)) { -+ tt->tgid_cache_hits++; -+ return next; -+ } -+ -+ return NULL; -+} -+ -+/* - * Fill in the task_mem_usage structure with the RSS, virtual memory size, - * percent of physical memory being used, and the mm_struct address. - */ -@@ -4037,11 +4088,8 @@ get_task_mem_usage(ulong task, struct ta - if (VALID_MEMBER(mm_struct_rss_stat)) { - long anonpages, filepages; - -- if (!enumerator_value("MM_FILEPAGES", &filepages) || -- !enumerator_value("MM_ANONPAGES", &anonpages)) { -- filepages = 0; -- anonpages = 1; -- } -+ anonpages = tt->anonpages; -+ filepages = tt->filepages; - rss += LONG(tt->mm_struct + - OFFSET(mm_struct_rss_stat) + - OFFSET(mm_rss_stat_count) + -@@ -4054,19 +4102,35 @@ get_task_mem_usage(ulong task, struct ta - - /* Check whether SPLIT_RSS_COUNTING is enabled */ - if (VALID_MEMBER(task_struct_rss_stat)) { -- int i, sync_rss; -- ulong tgid; -- struct task_context *tc1; -- -- tgid = task_tgid(task); -- -- tc1 = FIRST_CONTEXT(); -- for (i = 0; i < RUNNING_TASKS(); i++, tc1++) { -- if (task_tgid(tc1->task) != tgid) -- continue; -+ int sync_rss; -+ struct tgid_context tgid, *tgid_array, *tg, *first, *last; -+ -+ tgid_array = tt->tgid_array; -+ tgid.tgid = task_tgid(task); - -+ if (!(tg = tgid_quick_search(tgid.tgid))) -+ tg = (struct tgid_context *)bsearch(&tgid, tgid_array, RUNNING_TASKS(), -+ sizeof(struct tgid_context), sort_by_tgid); -+ -+ if (tg == NULL) -+ error(FATAL, "bsearch for tgid failed: task: %lx tgid: %ld\n", -+ task, tgid.tgid); -+ -+ /* find the first element which has the same tgid */ -+ first = tg; -+ while ((first > tgid_array) && ((first - 1)->tgid == first->tgid)) -+ first--; -+ -+ /* find the last element which have same tgid */ -+ last = tg; -+ while ((last < (tgid_array + (RUNNING_TASKS() - 1))) && -+ (last->tgid == (last + 1)->tgid)) -+ last++; -+ -+ while (first <= last) -+ { - /* count 0 -> filepages */ -- if (!readmem(tc1->task + -+ if (!readmem(first->task + - OFFSET(task_struct_rss_stat) + - OFFSET(task_rss_stat_count), KVADDR, - &sync_rss, -@@ -4078,7 +4142,7 @@ get_task_mem_usage(ulong task, struct ta - rss += sync_rss; - - /* count 1 -> anonpages */ -- if (!readmem(tc1->task + -+ if (!readmem(first->task + - OFFSET(task_struct_rss_stat) + - OFFSET(task_rss_stat_count) + - sizeof(int), -@@ -4089,7 +4153,13 @@ get_task_mem_usage(ulong task, struct ta - continue; - - rss += sync_rss; -+ -+ if(first == last) -+ break; -+ first++; - } -+ -+ tt->last_tgid = last; - } - - /* diff --git a/SOURCES/rhel7.0_beta.patch b/SOURCES/rhel7.0_beta.patch deleted file mode 100644 index f1b2239..0000000 --- a/SOURCES/rhel7.0_beta.patch +++ /dev/null @@ -1,2425 +0,0 @@ ---- crash-7.0.2/main.c 2013-10-25 15:28:55.938879568 -0400 -+++ crash-7.0.3/main.c 2013-10-15 15:55:10.136390264 -0400 -@@ -1335,6 +1335,8 @@ dump_program_context(void) - fprintf(fp, "%sGET_LOG", others++ ? "|" : ""); - if (pc->flags2 & VMCOREINFO) - fprintf(fp, "%sVMCOREINFO", others++ ? "|" : ""); -+ if (pc->flags2 & ALLOW_FP) -+ fprintf(fp, "%sALLOW_FP", others++ ? "|" : ""); - fprintf(fp, ")\n"); - - fprintf(fp, " namelist: %s\n", pc->namelist); ---- crash-7.0.2/tools.c 2013-10-25 15:28:55.922879569 -0400 -+++ crash-7.0.3/tools.c 2013-10-25 10:09:31.938757537 -0400 -@@ -989,7 +989,7 @@ dtoi(char *s, int flags, int *errptr) - if ((s[j] < '0' || s[j] > '9')) - break ; - -- if (s[j] != '\0' || (sscanf(s, "%d", &retval) != 1)) { -+ if (s[j] != '\0' || (sscanf(s, "%d", (int *)&retval) != 1)) { - if (!(flags & QUIET)) - error(INFO, "%s: \"%c\" is not a digit 0 - 9\n", - s, s[j]); -@@ -5489,6 +5489,19 @@ swap32(uint32_t val, int swap) - return val; - } - -+/* -+ * Get a sufficiently large buffer for cpumask. -+ * You should call FREEBUF() on the result when you no longer need it. -+ */ -+ulong * -+get_cpumask_buf(void) -+{ -+ int cpulen; -+ if ((cpulen = STRUCT_SIZE("cpumask_t")) < 0) -+ cpulen = DIV_ROUND_UP(kt->cpus, BITS_PER_LONG) * sizeof(ulong); -+ return (ulong *)GETBUF(cpulen); -+} -+ - int - make_cpumask(char *s, ulong *mask, int flags, int *errptr) - { -@@ -5505,14 +5518,20 @@ make_cpumask(char *s, ulong *mask, int f - p = strtok(s, ","); - while (p) { - s = strtok(NULL, ""); -- start = end = -1; -- q = strtok(p, "-"); -- start = dtoi(q, flags, errptr); -- if ((q = strtok(NULL, "-"))) -- end = dtoi(q, flags, errptr); - -- if (end == -1) -- end = start; -+ if (STREQ(p, "a") || STREQ(p, "all")) { -+ start = 0; -+ end = kt->cpus - 1; -+ } else { -+ start = end = -1; -+ q = strtok(p, "-"); -+ start = dtoi(q, flags, errptr); -+ if ((q = strtok(NULL, "-"))) -+ end = dtoi(q, flags, errptr); -+ -+ if (end == -1) -+ end = start; -+ } - - for (i = start; i <= end; i++) - SET_BIT(mask, i); ---- crash-7.0.2/memory.c 2013-10-25 15:28:55.934879568 -0400 -+++ crash-7.0.3/memory.c 2013-10-25 10:09:35.641757367 -0400 -@@ -134,6 +134,10 @@ static char *error_handle_string(ulong); - static void dump_mem_map(struct meminfo *); - static void dump_mem_map_SPARSEMEM(struct meminfo *); - static void fill_mem_map_cache(ulong, ulong, char *); -+static void page_flags_init(void); -+static int page_flags_init_from_pageflag_names(void); -+static int page_flags_init_from_pageflags_enum(void); -+static int translate_page_flags(char *, ulong); - static void dump_free_pages(struct meminfo *); - static int dump_zone_page_usage(void); - static void dump_multidimensional_free_pages(struct meminfo *); -@@ -613,6 +617,13 @@ vm_init(void) - MEMBER_OFFSET_INIT(kmem_list3_free_objects, - kmem_cache_node_struct, "free_objects"); - MEMBER_OFFSET_INIT(kmem_list3_shared, kmem_cache_node_struct, "shared"); -+ /* -+ * Common to slab/slub -+ */ -+ ANON_MEMBER_OFFSET_INIT(page_slab, "page", "slab_cache"); -+ ANON_MEMBER_OFFSET_INIT(page_slab_page, "page", "slab_page"); -+ ANON_MEMBER_OFFSET_INIT(page_first_page, "page", "first_page"); -+ - } else if (MEMBER_EXISTS("kmem_cache", "cpu_slab") && - STRUCT_EXISTS("kmem_cache_node")) { - vt->flags |= KMALLOC_SLUB; -@@ -642,6 +653,7 @@ vm_init(void) - ANON_MEMBER_OFFSET_INIT(page_slab, "page", "slab"); - if (INVALID_MEMBER(page_slab)) - ANON_MEMBER_OFFSET_INIT(page_slab, "page", "slab_cache"); -+ ANON_MEMBER_OFFSET_INIT(page_slab_page, "page", "slab_page"); - ANON_MEMBER_OFFSET_INIT(page_first_page, "page", "first_page"); - ANON_MEMBER_OFFSET_INIT(page_freelist, "page", "freelist"); - if (INVALID_MEMBER(kmem_cache_objects)) { -@@ -703,16 +715,16 @@ vm_init(void) - } - - if (!kt->kernel_NR_CPUS) { -- if (ARRAY_LENGTH(kmem_cache_s_cpudata)) -+ if (enumerator_value("WORK_CPU_UNBOUND", (long *)&value1)) -+ kt->kernel_NR_CPUS = (int)value1; -+ else if ((i = get_array_length("__per_cpu_offset", NULL, 0))) -+ kt->kernel_NR_CPUS = i; -+ else if (ARRAY_LENGTH(kmem_cache_s_cpudata)) - kt->kernel_NR_CPUS = ARRAY_LENGTH(kmem_cache_s_cpudata); - else if (ARRAY_LENGTH(kmem_cache_s_array)) - kt->kernel_NR_CPUS = ARRAY_LENGTH(kmem_cache_s_array); - else if (ARRAY_LENGTH(kmem_cache_cpu_slab)) - kt->kernel_NR_CPUS = ARRAY_LENGTH(kmem_cache_cpu_slab); -- else if (enumerator_value("WORK_CPU_UNBOUND", (long *)&value1)) -- kt->kernel_NR_CPUS = (int)value1; -- else if ((i = get_array_length("__per_cpu_offset", NULL, 0))) -- kt->kernel_NR_CPUS = i; - } - - if (CRASHDEBUG(1)) -@@ -1025,8 +1037,7 @@ vm_init(void) - - kmem_cache_init(); - -- PG_reserved_flag_init(); -- PG_slab_flag_init(); -+ page_flags_init(); - - vt->flags |= VM_INIT; - } -@@ -4533,15 +4544,37 @@ PG_slab_flag_init(void) - char buf[BUFSIZE]; /* safe for a page struct */ - - /* -- * Set the old defaults in case the search below fails. -+ * Set the old defaults in case all else fails. - */ -- if (VALID_MEMBER(page_pte)) { -+ if (enumerator_value("PG_slab", (long *)&flags)) { -+ vt->PG_slab = flags; -+ if (CRASHDEBUG(2)) -+ fprintf(fp, "PG_slab (enum): %lx\n", vt->PG_slab); -+ } else if (VALID_MEMBER(page_pte)) { - if (THIS_KERNEL_VERSION < LINUX(2,6,0)) - vt->PG_slab = 10; - else if (THIS_KERNEL_VERSION >= LINUX(2,6,0)) - vt->PG_slab = 7; -- } else if (THIS_KERNEL_VERSION >= LINUX(2,6,0)) -- vt->PG_slab = 7; -+ } else if (THIS_KERNEL_VERSION >= LINUX(2,6,0)) { -+ vt->PG_slab = 7; -+ } else { -+ if (try_get_symbol_data("vm_area_cachep", sizeof(void *), &vaddr) && -+ phys_to_page((physaddr_t)VTOP(vaddr), &pageptr) && -+ readmem(pageptr, KVADDR, buf, SIZE(page), -+ "vm_area_cachep page", RETURN_ON_ERROR|QUIET)) { -+ -+ flags = ULONG(buf + OFFSET(page_flags)); -+ -+ if ((bit = ffsl(flags))) { -+ vt->PG_slab = bit - 1; -+ -+ if (CRASHDEBUG(2)) -+ fprintf(fp, -+ "PG_slab bit: vaddr: %lx page: %lx flags: %lx => %ld\n", -+ vaddr, pageptr, flags, vt->PG_slab); -+ } -+ } -+ } - - if (vt->flags & KMALLOC_SLUB) { - /* -@@ -4561,34 +4594,20 @@ PG_slab_flag_init(void) - fprintf(fp, "PG_head_tail_mask: %lx\n", - vt->PG_head_tail_mask); - } -- -- return; -- } -- -- if (enumerator_value("PG_slab", (long *)&flags)) { -- vt->PG_slab = flags; -- if (CRASHDEBUG(2)) -- fprintf(fp, "PG_slab (enum): %lx\n", vt->PG_slab); -- return; -- } -- -- if (try_get_symbol_data("vm_area_cachep", sizeof(void *), &vaddr) && -- phys_to_page((physaddr_t)VTOP(vaddr), &pageptr) && -- readmem(pageptr, KVADDR, buf, SIZE(page), -- "vm_area_cachep page", RETURN_ON_ERROR|QUIET)) { -- -- flags = ULONG(buf + OFFSET(page_flags)); -- -- if ((bit = ffsl(flags))) { -- vt->PG_slab = bit - 1; -- -- if (CRASHDEBUG(2)) -- fprintf(fp, -- "PG_slab bit: vaddr: %lx page: %lx flags: %lx => %ld\n", -- vaddr, pageptr, flags, vt->PG_slab); -- -+ } else { -+ if (enumerator_value("PG_tail", (long *)&flags)) -+ vt->PG_head_tail_mask = (1L << flags); -+ else if (enumerator_value("PG_compound", (long *)&flags) && -+ enumerator_value("PG_reclaim", (long *)&flags2)) { -+ vt->PG_head_tail_mask = ((1L << flags) | (1L << flags2)); -+ if (CRASHDEBUG(2)) -+ fprintf(fp, "PG_head_tail_mask: %lx (PG_compound|PG_reclaim)\n", -+ vt->PG_head_tail_mask); - } - } -+ -+ if (!vt->PG_slab) -+ error(INFO, "cannot determine PG_slab bit value\n"); - } - - /* -@@ -5009,7 +5028,10 @@ dump_mem_map_SPARSEMEM(struct meminfo *m - bufferindex += sprintflag("%sreserved"); - bufferindex += sprintf(outputbuffer+bufferindex, "\n"); - } else if (THIS_KERNEL_VERSION > LINUX(2,4,9)) { -- bufferindex += sprintf(outputbuffer+bufferindex, "%lx\n", flags); -+ if (vt->flags & PAGEFLAGS) -+ bufferindex += translate_page_flags(outputbuffer+bufferindex, flags); -+ else -+ bufferindex += sprintf(outputbuffer+bufferindex, "%lx\n", flags); - } else { - - if ((flags >> v24_PG_locked) & 1) -@@ -5444,7 +5466,10 @@ dump_mem_map(struct meminfo *mi) - bufferindex += sprintflag("%sreserved"); - bufferindex += sprintf(outputbuffer+bufferindex, "\n"); - } else if (THIS_KERNEL_VERSION > LINUX(2,4,9)) { -- bufferindex += sprintf(outputbuffer+bufferindex, "%lx\n", flags); -+ if (vt->flags & PAGEFLAGS) -+ bufferindex += translate_page_flags(outputbuffer+bufferindex, flags); -+ else -+ bufferindex += sprintf(outputbuffer+bufferindex, "%lx\n", flags); - } else { - - if ((flags >> v24_PG_locked) & 1) -@@ -5591,6 +5616,196 @@ fill_mem_map_cache(ulong pp, ulong ppend - } - } - -+static void -+page_flags_init(void) -+{ -+ if (!page_flags_init_from_pageflag_names()) -+ page_flags_init_from_pageflags_enum(); -+ -+ PG_reserved_flag_init(); -+ PG_slab_flag_init(); -+} -+ -+static int -+page_flags_init_from_pageflag_names(void) -+{ -+ int i, len; -+ char *buffer, *nameptr; -+ char namebuf[BUFSIZE]; -+ ulong mask; -+ void *name; -+ -+ MEMBER_OFFSET_INIT(trace_print_flags_mask, "trace_print_flags", "mask"); -+ MEMBER_OFFSET_INIT(trace_print_flags_name, "trace_print_flags", "name"); -+ STRUCT_SIZE_INIT(trace_print_flags, "trace_print_flags"); -+ -+ if (INVALID_SIZE(trace_print_flags) || -+ INVALID_MEMBER(trace_print_flags_mask) || -+ INVALID_MEMBER(trace_print_flags_name) || -+ !kernel_symbol_exists("pageflag_names") || -+ !(len = get_array_length("pageflag_names", NULL, 0))) -+ return FALSE; -+ -+ buffer = GETBUF(SIZE(trace_print_flags) * len); -+ -+ if (!readmem(symbol_value("pageflag_names"), KVADDR, buffer, -+ SIZE(trace_print_flags) * len, "pageflag_names array", -+ RETURN_ON_ERROR)) { -+ FREEBUF(buffer); -+ return FALSE; -+ } -+ -+ if (!(vt->pageflags_data = (struct pageflags_data *) -+ malloc(sizeof(struct pageflags_data) * len))) { -+ error(INFO, "cannot malloc pageflags_data cache\n"); -+ FREEBUF(buffer); -+ return FALSE; -+ } -+ -+ if (CRASHDEBUG(1)) -+ fprintf(fp, "pageflags from pageflag_names: \n"); -+ -+ for (i = 0; i < len; i++) { -+ mask = ULONG(buffer + (SIZE(trace_print_flags)*i) + -+ OFFSET(trace_print_flags_mask)); -+ name = VOID_PTR(buffer + (SIZE(trace_print_flags)*i) + -+ OFFSET(trace_print_flags_name)); -+ -+ if ((mask == -1UL) && !name) { /* Linux 3.5 and earlier */ -+ len--; -+ break; -+ } -+ -+ if (!read_string((ulong)name, namebuf, BUFSIZE-1)) { -+ error(INFO, "failed to read pageflag_names entry\n", -+ i, name, mask); -+ goto pageflags_fail; -+ } -+ -+ if (!(nameptr = (char *)malloc(strlen(namebuf)+1))) { -+ error(INFO, "cannot malloc pageflag_names space\n"); -+ goto pageflags_fail; -+ } -+ strcpy(nameptr, namebuf); -+ -+ vt->pageflags_data[i].name = nameptr; -+ vt->pageflags_data[i].mask = mask; -+ -+ if (CRASHDEBUG(1)) { -+ fprintf(fp, " %08lx %s\n", -+ vt->pageflags_data[i].mask, -+ vt->pageflags_data[i].name); -+ } -+ } -+ -+ FREEBUF(buffer); -+ vt->nr_pageflags = len; -+ vt->flags |= PAGEFLAGS; -+ return TRUE; -+ -+pageflags_fail: -+ FREEBUF(buffer); -+ free(vt->pageflags_data); -+ vt->pageflags_data = NULL; -+ return FALSE; -+} -+ -+static int -+page_flags_init_from_pageflags_enum(void) -+{ -+ int c; -+ int p, len; -+ char *nameptr; -+ char buf[BUFSIZE]; -+ char *arglist[MAXARGS]; -+ -+ if (!(vt->pageflags_data = (struct pageflags_data *) -+ malloc(sizeof(struct pageflags_data) * 32))) { -+ error(INFO, "cannot malloc pageflags_data cache\n"); -+ return FALSE; -+ } -+ -+ p = 0; -+ pc->flags2 |= ALLOW_FP; -+ open_tmpfile(); -+ -+ if (dump_enumerator_list("pageflags")) { -+ rewind(pc->tmpfile); -+ while (fgets(buf, BUFSIZE, pc->tmpfile)) { -+ if (!strstr(buf, " = ")) -+ continue; -+ -+ c = parse_line(buf, arglist); -+ -+ if (strstr(arglist[0], "__NR_PAGEFLAGS")) { -+ len = atoi(arglist[2]); -+ if (!len || (len > 32)) -+ goto enum_fail; -+ vt->nr_pageflags = len; -+ break; -+ } -+ -+ if (!(nameptr = (char *)malloc(strlen(arglist[0])))) { -+ error(INFO, "cannot malloc pageflags name space\n"); -+ goto enum_fail; -+ } -+ strcpy(nameptr, arglist[0] + strlen("PG_")); -+ vt->pageflags_data[p].name = nameptr; -+ vt->pageflags_data[p].mask = 1 << atoi(arglist[2]); -+ -+ p++; -+ } -+ } else -+ goto enum_fail; -+ -+ close_tmpfile(); -+ pc->flags2 &= ~ALLOW_FP; -+ -+ if (CRASHDEBUG(1)) { -+ fprintf(fp, "pageflags from enum: \n"); -+ for (p = 0; p < vt->nr_pageflags; p++) -+ fprintf(fp, " %08lx %s\n", -+ vt->pageflags_data[p].mask, -+ vt->pageflags_data[p].name); -+ } -+ -+ vt->flags |= PAGEFLAGS; -+ return TRUE; -+ -+enum_fail: -+ close_tmpfile(); -+ pc->flags2 &= ~ALLOW_FP; -+ -+ for (c = 0; c < p; c++) -+ free(vt->pageflags_data[c].name); -+ free(vt->pageflags_data); -+ vt->pageflags_data = NULL; -+ vt->nr_pageflags = 0; -+ -+ return FALSE; -+} -+ -+static int -+translate_page_flags(char *buffer, ulong flags) -+{ -+ char buf[BUFSIZE]; -+ int i, others; -+ -+ sprintf(buf, "%lx", flags); -+ -+ if (flags) { -+ for (i = others = 0; i < vt->nr_pageflags; i++) { -+ if (flags & vt->pageflags_data[i].mask) -+ sprintf(&buf[strlen(buf)], "%s%s", -+ others++ ? "," : " ", -+ vt->pageflags_data[i].name); -+ } -+ } -+ strcat(buf, "\n"); -+ strcpy(buffer, buf); -+ -+ return(strlen(buf)); -+} - - /* - * dump_page_hash_table() displays the entries in each page_hash_table. -@@ -7240,7 +7455,8 @@ dump_kmeminfo(void) - page_cache_size = nr_file_pages - swapper_space_nrpages - - buffer_pages; - FREEBUF(swapper_space); -- } -+ } else -+ page_cache_size = 0; - - - pct = (page_cache_size * 100)/totalram_pages; -@@ -8085,7 +8301,9 @@ vaddr_to_kmem_cache(ulong vaddr, char *b - return NULL; - } - -- if (vt->flags & KMALLOC_SLUB) { -+ if ((vt->flags & KMALLOC_SLUB) || -+ ((vt->flags & KMALLOC_COMMON) && -+ VALID_MEMBER(page_slab) && VALID_MEMBER(page_first_page))) { - readmem(compound_head(page)+OFFSET(page_slab), - KVADDR, &cache, sizeof(void *), - "page.slab", FAULT_ON_ERROR); -@@ -8136,6 +8354,10 @@ vaddr_to_slab(ulong vaddr) - - if (vt->flags & KMALLOC_SLUB) - slab = compound_head(page); -+ else if ((vt->flags & KMALLOC_COMMON) && VALID_MEMBER(page_slab_page)) -+ readmem(page+OFFSET(page_slab_page), -+ KVADDR, &slab, sizeof(void *), -+ "page.slab_page", FAULT_ON_ERROR); - else if (VALID_MEMBER(page_prev)) - readmem(page+OFFSET(page_prev), - KVADDR, &slab, sizeof(void *), -@@ -8212,7 +8434,7 @@ kmem_cache_init(void) - OFFSET(kmem_cache_s_num) : OFFSET(kmem_cache_s_c_num); - next_offset = vt->flags & (PERCPU_KMALLOC_V1|PERCPU_KMALLOC_V2) ? - OFFSET(kmem_cache_s_next) : OFFSET(kmem_cache_s_c_nextp); -- max_cnum = max_limit = max_cpus = cache_count = 0; -+ max_cnum = max_limit = max_cpus = cache_count = tmp2 = 0; - - /* - * Pre-2.6 versions used the "cache_cache" as the head of the -@@ -8431,6 +8653,43 @@ kmem_cache_downsize(void) - FREEBUF(cache_buf); - } - -+/* -+ * Stash a list of presumably-corrupted slab cache addresses. -+ */ -+static void -+mark_bad_slab_cache(ulong cache) -+{ -+ size_t sz; -+ -+ if (vt->nr_bad_slab_caches) { -+ sz = sizeof(ulong) * (vt->nr_bad_slab_caches + 1); -+ if (!(vt->bad_slab_caches = realloc(vt->bad_slab_caches, sz))) { -+ error(INFO, "cannot realloc bad_slab_caches array\n"); -+ vt->nr_bad_slab_caches = 0; -+ return; -+ } -+ } else { -+ if (!(vt->bad_slab_caches = (ulong *)malloc(sizeof(ulong)))) { -+ error(INFO, "cannot malloc bad_slab_caches array\n"); -+ return; -+ } -+ } -+ -+ vt->bad_slab_caches[vt->nr_bad_slab_caches++] = cache; -+} -+ -+static int -+bad_slab_cache(ulong cache) -+{ -+ int i; -+ -+ for (i = 0; i < vt->nr_bad_slab_caches; i++) { -+ if (vt->bad_slab_caches[i] == cache) -+ return TRUE; -+ } -+ -+ return FALSE; -+} - - /* - * Determine the largest cpudata limit for a given cache. -@@ -8526,8 +8785,13 @@ kmem_cache_s_array_nodes: - for (i = max_limit = 0; (i < kt->cpus) && cpudata[i]; i++) { - if (!readmem(cpudata[i]+OFFSET(array_cache_limit), - KVADDR, &limit, sizeof(int), -- "array cache limit", RETURN_ON_ERROR)) -- goto bail_out; -+ "array cache limit", RETURN_ON_ERROR)) { -+ error(INFO, -+ "kmem_cache: %lx: invalid array_cache pointer: %lx\n", -+ cache, cpudata[i]); -+ mark_bad_slab_cache(cache); -+ return max_limit; -+ } - if (CRASHDEBUG(3)) - fprintf(fp, " array limit[%d]: %d\n", i, limit); - if (limit > max_limit) -@@ -9232,6 +9496,11 @@ dump_kmem_cache_percpu_v2(struct meminfo - goto next_cache; - } - -+ if (bad_slab_cache(si->cache)) { -+ fprintf(fp, "%lx %-18s [INVALID/CORRUPTED]\n", si->cache, buf); -+ goto next_cache; -+ } -+ - si->curname = buf; - - readmem(si->cache+OFFSET(kmem_cache_s_objsize), -@@ -9264,7 +9533,7 @@ dump_kmem_cache_percpu_v2(struct meminfo - "kmem_cache_s num", FAULT_ON_ERROR); - si->c_num = (ulong)tmp_val; - -- if( vt->flags & PERCPU_KMALLOC_V2_NODES ) -+ if (vt->flags & PERCPU_KMALLOC_V2_NODES) - do_slab_chain_percpu_v2_nodes(SLAB_GET_COUNTS, si); - else - do_slab_chain_percpu_v2(SLAB_GET_COUNTS, si); -@@ -10160,22 +10429,22 @@ do_slab_chain_percpu_v2_nodes(long cmd, - if (!slab_chains[s]) - continue; - -- if (!specified_slab) { -- if (!readmem(slab_chains[s], -- KVADDR, &si->slab, sizeof(ulong), -- "slabs", QUIET|RETURN_ON_ERROR)) { -- error(INFO, -- "%s: %s list: bad slab pointer: %lx\n", -- si->curname, -- slab_chain_name_v2[s], -- slab_chains[s]); -- list_borked = 1; -- continue; -+ if (!specified_slab) { -+ if (!readmem(slab_chains[s], -+ KVADDR, &si->slab, sizeof(ulong), -+ "slabs", QUIET|RETURN_ON_ERROR)) { -+ error(INFO, "%s: %s list: " -+ "bad slab pointer: %lx\n", -+ si->curname, -+ slab_chain_name_v2[s], -+ slab_chains[s]); -+ list_borked = 1; -+ continue; - } - last = slab_chains[s]; - } else - last = 0; -- -+ - if (si->slab == slab_chains[s]) - continue; - -@@ -11709,6 +11978,8 @@ dump_vm_table(int verbose) - fprintf(fp, "%sVM_EVENT", others++ ? "|" : "");\ - if (vt->flags & PGCNT_ADJ) - fprintf(fp, "%sPGCNT_ADJ", others++ ? "|" : "");\ -+ if (vt->flags & PAGEFLAGS) -+ fprintf(fp, "%sPAGEFLAGS", others++ ? "|" : "");\ - if (vt->flags & SWAPINFO_V1) - fprintf(fp, "%sSWAPINFO_V1", others++ ? "|" : "");\ - if (vt->flags & SWAPINFO_V2) -@@ -11747,10 +12018,15 @@ dump_vm_table(int verbose) - fprintf(fp, " kmem_cache_count: %ld\n", vt->kmem_cache_count); - fprintf(fp, " kmem_cache_namelen: %d\n", vt->kmem_cache_namelen); - fprintf(fp, "kmem_cache_len_nodes: %ld\n", vt->kmem_cache_len_nodes); -- fprintf(fp, " PG_reserved: %lx\n", vt->PG_reserved); -- fprintf(fp, " PG_slab: %ld (%lx)\n", vt->PG_slab, -- (ulong)1 << vt->PG_slab); -- fprintf(fp, " PG_head_tail_mask: %lx\n", vt->PG_head_tail_mask); -+ fprintf(fp, " nr_bad_slab_caches: %d\n", vt->nr_bad_slab_caches); -+ if (!vt->nr_bad_slab_caches) -+ fprintf(fp, " bad_slab_caches: (unused)\n"); -+ else { -+ for (i = 0; i < vt->nr_bad_slab_caches; i++) { -+ fprintf(fp, " bad_slab_caches[%d]: %lx\n", -+ i, vt->bad_slab_caches[i]); -+ } -+ } - fprintf(fp, " paddr_prlen: %d\n", vt->paddr_prlen); - fprintf(fp, " numnodes: %d\n", vt->numnodes); - fprintf(fp, " nr_zones: %d\n", vt->nr_zones); -@@ -11824,6 +12100,21 @@ dump_vm_table(int verbose) - for (i = 0; i < vt->nr_vm_event_items; i++) - fprintf(fp, " [%d] %s\n", i, vt->vm_event_items[i]); - -+ fprintf(fp, " PG_reserved: %lx\n", vt->PG_reserved); -+ fprintf(fp, " PG_slab: %ld (%lx)\n", vt->PG_slab, -+ (ulong)1 << vt->PG_slab); -+ fprintf(fp, " PG_head_tail_mask: %lx\n", vt->PG_head_tail_mask); -+ -+ fprintf(fp, " nr_pageflags: %d\n", vt->nr_pageflags); -+ fprintf(fp, " pageflags_data: %s\n", -+ vt->nr_pageflags ? "" : "(not used)"); -+ for (i = 0; i < vt->nr_pageflags; i++) { -+ fprintf(fp, " %s[%d] %08lx: %s\n", -+ i < 10 ? " " : "", i, -+ vt->pageflags_data[i].mask, -+ vt->pageflags_data[i].name); -+ } -+ - dump_vma_cache(VERBOSE); - } - ---- crash-7.0.2/filesys.c 2013-10-25 15:28:55.920879569 -0400 -+++ crash-7.0.3/filesys.c 2013-10-25 10:09:39.568757187 -0400 -@@ -727,8 +727,10 @@ get_proc_version(void) - return FALSE; - - if (fread(&kt->proc_version, sizeof(char), -- BUFSIZE-1, version) <= 0) -+ BUFSIZE-1, version) <= 0) { -+ fclose(version); - return FALSE; -+ } - - fclose(version); - ---- crash-7.0.2/help.c 2013-10-25 15:28:55.954879567 -0400 -+++ crash-7.0.3/help.c 2013-10-24 15:32:58.495826737 -0400 -@@ -1083,10 +1083,16 @@ NULL - char *help_p[] = { - "p", - "print the value of an expression", --"[-x|-d][-u] expression", -+"[-x|-d][-u] [expression | symbol[:cpuspec]]", - " This command passes its arguments on to gdb \"print\" command for evaluation.", - "", --" expression The expression to be evaluated.", -+" expression an expression to be evaluated.", -+" symbol a kernel symbol.", -+" :cpuspec CPU specification for a per-cpu symbol:", -+" : CPU of the currently selected task.", -+" :a[ll] all CPUs.", -+" :#[-#][,...] CPU list(s), e.g. \"1,3,5\", \"1-3\",", -+" or \"1,3,5-7,10\".", - " -x override default output format with hexadecimal format.", - " -d override default output format with decimal format.", - " -u the expression evaluates to a user address reference.", -@@ -1144,6 +1150,39 @@ char *help_p[] = { - " swap_address = 0x0, ", - " segments = 0x0", - " }", -+"", -+" If a per-cpu symbol is entered as a argument, its data type", -+" and all of its per-cpu addresses are displayed:", -+" ", -+" %s> p irq_stat", -+" PER-CPU DATA TYPE:", -+" irq_cpustat_t irq_stat;", -+" PER-CPU ADDRESSES:", -+" [0]: ffff88021e211540", -+" [1]: ffff88021e251540", -+" [2]: ffff88021e291540", -+" [3]: ffff88021e2d1540", -+" ", -+" To display the contents a per-cpu symbol for CPU 1, append", -+" a cpu-specifier:", -+" ", -+" %s> p irq_stat:1", -+" per_cpu(irq_stat, 1) = $29 = {", -+" __softirq_pending = 0, ", -+" __nmi_count = 209034, ", -+" apic_timer_irqs = 597509876, ", -+" irq_spurious_count = 0, ", -+" icr_read_retry_count = 2, ", -+" x86_platform_ipis = 0, ", -+" apic_perf_irqs = 209034, ", -+" apic_irq_work_irqs = 0, ", -+" irq_resched_count = 264922233, ", -+" irq_call_count = 7036692, ", -+" irq_tlb_count = 4750442, ", -+" irq_thermal_count = 0, ", -+" irq_threshold_count = 0", -+" }", -+" ", - NULL - }; - -@@ -2841,7 +2880,7 @@ char *help_irq[] = { - " irq stats of all cpus will be displayed.", - " -c cpu only usable with the -s option, dump the irq stats of the ", - " specified cpu[s]; cpu can be specified as \"1,3,5\", \"1-3\",", --" or \"1,3,5-7,10\".", -+" \"1,3,5-7,10\", \"all\", or \"a\" (shortcut for \"all\").", - "\nEXAMPLES", - " Display the relevant data for IRQ 18 from a pre-2.6.37 kernel:\n", - " %s> irq 18", -@@ -4092,8 +4131,8 @@ NULL - char *help_struct[] = { - "struct", - "structure contents", --"struct_name[.member[,member]][-o][-l offset][-rfuxdp][address | symbol]\n" --" [count | -c count]", -+"struct_name[.member[,member]][-o][-l offset][-rfuxdp]\n" -+" [address | symbol][:cpuspec] [count | -c count]", - " This command displays either a structure definition, or a formatted display", - " of the contents of a structure at a specified address. When no address is", - " specified, the structure definition is shown along with the structure size.", -@@ -4127,6 +4166,11 @@ char *help_struct[] = { - " to an embedded list_head structure contained within the", - " target data structure, then the \"-l\" option must be used.", - " symbol symbolic reference to the address of a structure.", -+" :cpuspec CPU specification for a per-cpu address or symbol:", -+" : CPU of the currently selected task.", -+" :a[ll] all CPUs.", -+" :#[-#][,...] CPU list(s), e.g. \"1,3,5\", \"1-3\",", -+" or \"1,3,5-7,10\".", - " count count of structures to dump from an array of structures;", - " if used, this must be the last argument entered.", - " -c count \"-c\" is only required if \"count\" is not the last argument", -@@ -4363,6 +4407,59 @@ char *help_struct[] = { - " [ffff8100145d20b8] struct list_head run_list;", - " [ffff8100145d20c8] struct prio_array *array;", - " ...", -+" ", -+" For an example of displaying per-cpu variables, consider the", -+" struct hd_struct.dkstats member, which is a percpu pointer to", -+" a disk_stats structure:", -+"", -+" %s> struct hd_struct.dkstats ", -+" struct hd_struct {", -+" [1232] struct disk_stats *dkstats;", -+" }", -+"", -+" Taking an hd_struct at address ffff8802450e2848, display all", -+" of the per-cpu disk_stats structures that it references:", -+" ", -+" %s> struct hd_struct.dkstats ffff8802450e2848", -+" dkstats = 0x60fdb48026c8", -+" %s> struct disk_stats 0x60fdb48026c8:a", -+" [0]: ffffe8fefe6026c8", -+" struct disk_stats {", -+" sectors = {451376, 80468}, ", -+" ios = {6041, 971}, ", -+" merges = {386, 390}, ", -+" ticks = {194877, 56131}, ", -+" io_ticks = 12371, ", -+" time_in_queue = 309163", -+" }", -+" [1]: ffffe8fefe8026c8", -+" struct disk_stats {", -+" sectors = {0, 0}, ", -+" ios = {0, 0}, ", -+" merges = {7, 242}, ", -+" ticks = {0, 0}, ", -+" io_ticks = 23, ", -+" time_in_queue = 581", -+" }", -+" [2]: ffffe8fefea026c8", -+" struct disk_stats {", -+" sectors = {0, 0}, ", -+" ios = {0, 0}, ", -+" merges = {4, 112}, ", -+" ticks = {0, 0}, ", -+" io_ticks = 11, ", -+" time_in_queue = 305", -+" }", -+" [3]: ffffe8fefec026c8", -+" struct disk_stats {", -+" sectors = {0, 0}, ", -+" ios = {0, 0}, ", -+" merges = {5, 54}, ", -+" ticks = {0, 0}, ", -+" io_ticks = 17, ", -+" time_in_queue = 41", -+" }", -+" ", - "\nNOTE", - " If the structure name does not conflict with any %s command name, the", - " \"struct\" command may be dropped. Accordingly, the examples above could", -@@ -4382,8 +4479,8 @@ NULL - char *help_union[] = { - "union", - "union contents", --"union_name[.member[,member]] [-o][-l offset][-rfuxdp] [address | symbol]\n" --" [count | -c count]", -+"union_name[.member[,member]] [-o][-l offset][-rfuxdp]\n" -+" [address | symbol][:cpuspec] [count | -c count]", - " This command displays either a union definition, or a formatted display", - " of the contents of a union at a specified address. When no address is", - " specified, the union definition is shown along with the union size.", -@@ -4418,6 +4515,11 @@ char *help_union[] = { - " to an embedded list_head structure contained within the", - " target union structure, then the \"-l\" option must be used.", - " symbol symbolic reference to the address of a union.", -+" :cpuspec CPU specification for a per-cpu address or symbol:", -+" : CPU of the currently selected task.", -+" :a[ll] all CPUs.", -+" :#[-#][,...] CPU list(s), e.g. \"1,3,5\", \"1-3\",", -+" or \"1,3,5-7,10\".", - " count count of unions to dump from an array of unions; if used,", - " this must be the last argument entered.", - " -c count \"-c\" is only required if \"count\" is not the last argument", -@@ -5433,30 +5535,26 @@ char *help_kmem[] = { - " ", - " Dump the mem_map[] array:\n", - " %s> kmem -p", --" PAGE PHYSICAL MAPPING INDEX CNT FLAGS", --" ffffea0000000000 0 0 0 0 0", --" ffffea0000000038 1000 0 0 1 400", --" ffffea0000000070 2000 0 0 1 400", --" ffffea00000000a8 3000 0 0 1 400", --" ffffea00000000e0 4000 0 0 1 400", --" ffffea0000000118 5000 0 0 1 400", --" ffffea0000000150 6000 0 0 1 400", --" ffffea0000000188 7000 0 0 1 80", --" ffffea00000001c0 8000 0 0 1 400", --" ffffea00000001f8 9000 0 0 1 80", --" ffffea0000000230 a000 0 0 1 80", --" ffffea0000000268 b000 ffff880012d9bd68 695b 1 2002c", --" ffffea00000002a0 c000 0 0 1 80", --" ffffea00000002d8 d000 ffff88002a9ee210 9 1 2002c", --" ffffea0000000310 e000 ffff880010b265d8 33c 1 2002c", --" ffffea0000000348 f000 ffff88001404dd68 2d1 2 868", --" ffffea0000000380 10000 ffff88001404dd68 2d6 2 868", --" ffffea00000003b8 11000 ffff88001404dd68 2d7 2 868", --" ffffea00000003f0 12000 ffff88001404dd68 2d8 2 868", --" ffffea0000000428 13000 ffff88001404dd68 2d9 2 868", --" ffffea0000000460 14000 ffff88001404dd68 2da 2 868", --" ffffea0000000498 15000 ffff88001404dd68 2db 2 868", --" ffffea00000004d0 16000 ffff88001404dd68 2dc 2 868", -+" PAGE PHYSICAL MAPPING INDEX CNT FLAGS", -+" f5c51200 10000 0 0 1 80 slab", -+" f5c51220 11000 0 0 1 80 slab", -+" f5c51240 12000 0 0 1 80 slab", -+" f5c51260 13000 0 0 1 80 slab", -+" f5c51280 14000 0 0 1 80 slab", -+" f5c512a0 15000 0 0 1 80 slab", -+" f5c512c0 16000 0 0 1 80 slab", -+" f5c512e0 17000 0 0 1 80 slab", -+" f5c51300 18000 0 0 1 80 slab", -+" f5c51320 19000 0 0 1 80 slab", -+" f5c51340 1a000 0 0 1 80 slab", -+" f5c51360 1b000 0 0 1 80 slab", -+" f5c51380 1c000 e6c6a754 13b67 2 868 uptodate,lru,active,private", -+" f5c513a0 1d000 0 0 1 80 slab", -+" f5c513c0 1e000 0 0 1 80 slab", -+" f5c513e0 1f000 0 0 1 80 slab", -+" f5c51400 20000 e6c6a754 13bbb 2 868 uptodate,lru,active,private", -+" f5c51420 21000 0 0 1 80 slab", -+" f5c51440 22000 0 0 1 80 slab", - " ...", - " ", - " Use the commands above with a page pointer or a physical address argument:\n", -@@ -5469,12 +5567,14 @@ char *help_kmem[] = { - " 2 16k c02eb01c ", - " c40425b0 (c40425b0 is 1st of 4 pages) ", - " ", --" %s> kmem -p c035de00", --" PAGE PHYSICAL INODE OFFSET CNT FLAGS", --" c035de00 50c0000 0 129000 0 uptodate\n", --" %s> kmem -p 50c0000", --" PAGE PHYSICAL INODE OFFSET CNT FLAGS", --" c035de00 50c0000 0 129000 0 uptodate\n", -+" %s> kmem -p c25a9c00", -+" PAGE PHYSICAL MAPPING INDEX CNT FLAGS", -+" c25a9c00 1fe0000 f429d2e4 21fe3eb 2 800828 uptodate,lru,private", -+" ", -+" %s> kmem -p 1fe0000", -+" PAGE PHYSICAL MAPPING INDEX CNT FLAGS", -+" c25a9c00 1fe0000 f429d2e4 21fe3eb 2 800828 uptodate,lru,private", -+" ", - " Display the mapped memory regions allocated by vmalloc():\n", - " %s> kmem -v", - " VMAP_AREA VM_STRUCT ADDRESS RANGE SIZE", ---- crash-7.0.2/task.c 2013-10-25 15:28:55.949879567 -0400 -+++ crash-7.0.3/task.c 2013-10-17 14:42:50.532672513 -0400 -@@ -474,7 +474,7 @@ task_init(void) - tt->this_task = pid_to_task(active_pid); - } - else { -- if (KDUMP_DUMPFILE()) -+ if (KDUMP_DUMPFILE() && !(pc->flags2 & QEMU_MEM_DUMP)) - map_cpus_to_prstatus(); - else if (ELF_NOTES_VALID() && DISKDUMP_DUMPFILE()) - map_cpus_to_prstatus_kdump_cmprs(); -@@ -4873,10 +4873,10 @@ task_mm(ulong task, int fill) - char * - task_cpu(int processor, char *buf, int verbose) - { -- if (processor < NO_PROC_ID) -+ if (processor < NR_CPUS) - sprintf(buf, "%d", processor); -- if (processor == NO_PROC_ID) -- sprintf(buf, verbose ? "NO_PROC_ID" : "-"); -+ else -+ sprintf(buf, verbose ? "(unknown)" : "?"); - - return buf; - } ---- crash-7.0.2/kernel.c 2013-10-25 15:28:55.958879567 -0400 -+++ crash-7.0.3/kernel.c 2013-10-25 10:13:04.143747815 -0400 -@@ -5377,7 +5377,6 @@ cmd_irq(void) - int i, c; - int nr_irqs; - ulong *cpus; -- int len; - int show_intr, choose_cpu; - char buf[10]; - char arg_buf[BUFSIZE]; -@@ -5485,9 +5484,7 @@ cmd_irq(void) - error(FATAL, "cannot determine number of IRQs\n"); - - if (show_intr) { -- if ((len = STRUCT_SIZE("cpumask_t")) < 0) -- len = DIV_ROUND_UP(kt->cpus, BITS_PER_LONG) * sizeof(ulong); -- cpus = (ulong *)GETBUF(len); -+ cpus = get_cpumask_buf(); - - if (choose_cpu) { - make_cpumask(arg_buf, cpus, FAULT_ON_ERROR, NULL); -@@ -5648,6 +5645,7 @@ generic_dump_irq(int irq) - ulong tmp1, tmp2; - - handler = UNINITIALIZED; -+ action = 0; - - irq_desc_addr = get_irq_desc_addr(irq); - if (!irq_desc_addr && symbol_exists("irq_desc_ptrs")) { -@@ -8398,6 +8396,7 @@ static void add_ikconfig_entry(char *lin - static int setup_ikconfig(char *config) - { - char *ent, *tokptr; -+ struct ikconfig_list *new; - - ikconfig_all = calloc(1, sizeof(struct ikconfig_list) * IKCONFIG_MAX); - if (!ikconfig_all) { -@@ -8424,8 +8423,9 @@ static int setup_ikconfig(char *config) - free(ikconfig_all); - return 0; - } -- ikconfig_all = realloc(ikconfig_all, -- sizeof(struct ikconfig_list) * kt->ikconfig_ents); -+ if ((new = realloc(ikconfig_all, -+ sizeof(struct ikconfig_list) * kt->ikconfig_ents))) -+ ikconfig_all = new; - - return 1; - } ---- crash-7.0.2/gdb_interface.c 2013-10-25 15:28:55.936879568 -0400 -+++ crash-7.0.3/gdb_interface.c 2013-10-15 15:55:20.440389792 -0400 -@@ -357,8 +357,8 @@ gdb_interface(struct gnu_request *req) - restart(0); - - if (!req->fp) { -- req->fp = pc->flags & RUNTIME ? fp : -- CRASHDEBUG(1) ? fp : pc->nullfp; -+ req->fp = ((pc->flags & RUNTIME) || (pc->flags2 & ALLOW_FP)) ? -+ fp : CRASHDEBUG(1) ? fp : pc->nullfp; - } - - pc->cur_req = req; ---- crash-7.0.2/configure.c 2013-10-25 15:28:55.956879567 -0400 -+++ crash-7.0.3/configure.c 2013-10-25 10:09:47.567756821 -0400 -@@ -790,7 +790,7 @@ make_rh_rpm_package(char *package, int r - break; - } - } -- fclose(fp); -+ pclose(fp); - - if (!cur) { - fprintf(stderr, "cannot get version from \"crash -v\"\n"); ---- crash-7.0.2/net.c 2013-10-25 15:28:55.923879569 -0400 -+++ crash-7.0.3/net.c 2013-10-22 09:42:52.103705675 -0400 -@@ -1,8 +1,8 @@ - /* net.c - core analysis suite - * - * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc. -- * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 David Anderson -- * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Red Hat, Inc. All rights reserved. -+ * Copyright (C) 2002-2013 David Anderson -+ * Copyright (C) 2002-2013 Red Hat, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by -@@ -231,10 +231,22 @@ net_init(void) - } else if ((MEMBER_OFFSET("inet_sock", "sk") == 0) && - (MEMBER_OFFSET("sock", "__sk_common") == 0)) { - MEMBER_OFFSET_INIT(inet_opt_daddr, "sock_common", "skc_daddr"); -+ if (INVALID_MEMBER(inet_opt_daddr)) -+ ANON_MEMBER_OFFSET_INIT(inet_opt_daddr, "sock_common", -+ "skc_daddr"); - MEMBER_OFFSET_INIT(inet_opt_rcv_saddr, "sock_common", "skc_rcv_saddr"); -+ if (INVALID_MEMBER(inet_opt_rcv_saddr)) -+ ANON_MEMBER_OFFSET_INIT(inet_opt_rcv_saddr, "sock_common", -+ "skc_rcv_saddr"); - MEMBER_OFFSET_INIT(inet_opt_dport, "inet_sock", "inet_dport"); -+ if (INVALID_MEMBER(inet_opt_dport)) -+ ANON_MEMBER_OFFSET_INIT(inet_opt_dport, "sock_common", -+ "skc_dport"); - MEMBER_OFFSET_INIT(inet_opt_sport, "inet_sock", "inet_sport"); - MEMBER_OFFSET_INIT(inet_opt_num, "inet_sock", "inet_num"); -+ if (INVALID_MEMBER(inet_opt_num)) -+ ANON_MEMBER_OFFSET_INIT(inet_opt_num, "sock_common", -+ "skc_num"); - } - } - ---- crash-7.0.2/s390x.c 2013-10-25 15:28:55.928879568 -0400 -+++ crash-7.0.3/s390x.c 2013-10-10 14:57:54.080339089 -0400 -@@ -590,9 +590,12 @@ static int swap_entry(ulong entry) - if (THIS_KERNEL_VERSION < LINUX(2,6,19)) { - if ((entry & 0x601ULL) == 0x600ULL) - return 1; -- } else { -+ } if (THIS_KERNEL_VERSION < LINUX(3,12,0)) { - if ((entry & 0x403ULL) == 0x403ULL) - return 1; -+ } else { -+ if ((entry & 0x603ULL) == 0x402ULL) -+ return 1; - } - return 0; - } ---- crash-7.0.2/x86_64.c 2013-10-25 15:28:55.928879568 -0400 -+++ crash-7.0.3/x86_64.c 2013-10-17 09:25:14.265545546 -0400 -@@ -7251,6 +7251,9 @@ x86_64_get_framesize(struct bt_info *bt, - } - } - -+ if ((sp->value >= kt->init_begin) && (sp->value < kt->init_end)) -+ return 0; -+ - framesize = max = 0; - max_instructions = textaddr - sp->value; - instr = arg = -1; ---- crash-7.0.2/remote.c 2013-10-25 15:28:55.935879568 -0400 -+++ crash-7.0.3/remote.c 2013-10-25 10:09:51.680756632 -0400 -@@ -1116,8 +1116,10 @@ daemon_proc_version(char *buf) - return FALSE; - - if (fread(buf, sizeof(char), -- BUFSIZE-1, pipe) <= 0) -+ BUFSIZE-1, pipe) <= 0) { -+ pclose(pipe); - return FALSE; -+ } - - pclose(pipe); - ---- crash-7.0.2/va_server.c 2013-10-25 15:28:55.939879568 -0400 -+++ crash-7.0.3/va_server.c 2013-10-25 10:09:58.528756319 -0400 -@@ -313,6 +313,7 @@ int read_map(char *crash_file) - ret = fseek(vas_file_p, (long)0, SEEK_SET); - if(ret == -1) { - printf("va_server: unable to fseek, err = %d\n", ferror(vas_file_p)); -+ free(disk_hdr); - return -1; - } - items = fread((void *)disk_hdr, 1, Page_Size, vas_file_p); ---- crash-7.0.2/va_server_v1.c 2013-10-25 15:28:55.935879568 -0400 -+++ crash-7.0.3/va_server_v1.c 2013-10-25 10:10:02.032756158 -0400 -@@ -308,6 +308,7 @@ int read_map_v1(int blk_pos) - ret = fseek(vas_file_p, (long)(blk_pos*Page_Size), SEEK_SET); - if(ret == -1) { - console("va_server: unable to fseek, err = %d\n", ferror(vas_file_p)); -+ free(disk_hdr); - return -1; - } - items = fread((void *)disk_hdr, 1, Page_Size, vas_file_p); ---- crash-7.0.2/symbols.c 2013-10-25 15:28:55.956879567 -0400 -+++ crash-7.0.3/symbols.c 2013-10-24 15:33:12.359826102 -0400 -@@ -72,7 +72,10 @@ struct elf_common; - static void Elf32_Sym_to_common(Elf32_Sym *, struct elf_common *); - static void Elf64_Sym_to_common(Elf64_Sym *, struct elf_common *); - static void cmd_datatype_common(ulong); --static int display_per_cpu_info(struct syment *); -+static void do_datatype_addr(struct datatype_member *, ulong, int, -+ ulong, char **, int); -+static void process_gdb_output(char *, unsigned, const char *, int); -+static int display_per_cpu_info(struct syment *, int, char *); - static struct load_module *get_module_percpu_sym_owner(struct syment *); - static int is_percpu_symbol(struct syment *); - static void dump_percpu_symbols(struct load_module *); -@@ -116,6 +119,8 @@ static int show_member_offset(FILE *, st - #define IN_STRUCT (0x40000) - #define DATATYPE_QUERY (0x80000) - #define ANON_MEMBER_QUERY (0x100000) -+#define SHOW_RAW_DATA (0x200000) -+#define DEREF_POINTERS (0x400000) - - #define INTEGER_TYPE (UINT8|INT8|UINT16|INT16|UINT32|INT32|UINT64|INT64) - -@@ -132,6 +137,7 @@ static void dump_datatype_flags(ulong, F - static long anon_member_offset(char *, char *); - static int gdb_whatis(char *); - static void do_datatype_declaration(struct datatype_member *, ulong); -+static int member_to_datatype(char *, struct datatype_member *, ulong); - - #define DEBUGINFO_ERROR_MESSAGE1 \ - "the use of a System.map file requires that the accompanying namelist\nargument is a kernel file built with the -g CFLAG. The namelist argument\nsupplied in this case is a debuginfo file, which must be accompanied by the\nkernel file from which it was derived.\n" -@@ -5704,13 +5710,13 @@ dereference_pointer(ulong addr, struct d - static void - cmd_datatype_common(ulong flags) - { -- int i, c; -+ int c; - ulong addr, aflag; -+ char *cpuspec; -+ ulong *cpus; - struct syment *sp; -- int rawdata; -- long len; - ulong list_head_offset; -- int count, pflag; -+ int count; - int argc_members; - int optind_save; - unsigned int radix, restore_radix; -@@ -5721,19 +5727,19 @@ cmd_datatype_common(ulong flags) - - dm = &datatype_member; - count = 0xdeadbeef; -- rawdata = 0; - aflag = addr = 0; - list_head_offset = 0; - argc_members = 0; - radix = restore_radix = 0; - separator = members = NULL; -- pflag = 0; -+ cpuspec = NULL; -+ cpus = NULL; - - while ((c = getopt(argcnt, args, "pxdhfuc:rvol:")) != EOF) { - switch (c) - { - case 'p': -- pflag++; -+ flags |= DEREF_POINTERS; - break; - - case 'd': -@@ -5756,7 +5762,7 @@ cmd_datatype_common(ulong flags) - break; - - case 'r': -- rawdata = 1; -+ flags |= SHOW_RAW_DATA; - break; - - case 'v': -@@ -5816,11 +5822,22 @@ cmd_datatype_common(ulong flags) - if (aflag && (count != 0xdeadbeef)) - error(FATAL, "too many arguments!\n"); - -+ if (!aflag) { -+ cpuspec = strchr(args[optind], ':'); -+ if (cpuspec) -+ *cpuspec++ = NULLCHAR; -+ } -+ - if (clean_arg() && IS_A_NUMBER(args[optind])) { - if (aflag) - count = stol(args[optind], - FAULT_ON_ERROR, NULL); -- else { -+ else if (cpuspec) { -+ if (pc->curcmd_flags & MEMTYPE_FILEADDR) -+ error(FATAL, "-f option cannot be used with percpu\n"); -+ addr = htol(args[optind], FAULT_ON_ERROR, NULL); -+ aflag++; -+ } else { - if (pc->curcmd_flags & MEMTYPE_FILEADDR) - pc->curcmd_private = stoll(args[optind], - FAULT_ON_ERROR, NULL); -@@ -5835,6 +5852,12 @@ cmd_datatype_common(ulong flags) - aflag++; - } - } else if ((sp = symbol_search(args[optind]))) { -+ if (cpuspec && !is_percpu_symbol(sp)) { -+ error(WARNING, -+ "%s is not percpu; cpuspec ignored.\n", -+ sp->name); -+ cpuspec = NULL; -+ } - addr = sp->value; - aflag++; - } else { -@@ -5846,6 +5869,14 @@ cmd_datatype_common(ulong flags) - } - } - -+ if (cpuspec) { -+ cpus = get_cpumask_buf(); -+ if (STREQ(cpuspec, "")) -+ SET_BIT(cpus, CURRENT_CONTEXT()->processor); -+ else -+ make_cpumask(cpuspec, cpus, FAULT_ON_ERROR, NULL); -+ } -+ - optind = optind_save; - - if (count == 0xdeadbeef) -@@ -5853,7 +5884,7 @@ cmd_datatype_common(ulong flags) - else if (!aflag) - error(FATAL, "no kernel virtual address argument entered\n"); - -- if (pflag && !aflag) -+ if ((flags & DEREF_POINTERS) && !aflag) - error(FATAL, "-p option requires address argument\n"); - - if (list_head_offset) -@@ -5878,6 +5909,15 @@ cmd_datatype_common(ulong flags) - DATATYPE_QUERY|ANON_MEMBER_QUERY|RETURN_ON_ERROR) < 1)) - error(FATAL, "invalid data structure reference: %s\n", structname); - -+ if (! (flags & (STRUCT_REQUEST|UNION_REQUEST)) ) { -+ flags |= dm->type; -+ if (!(flags & (UNION_REQUEST|STRUCT_REQUEST))) -+ error(FATAL, "invalid argument"); -+ } else if ( (flags &(STRUCT_REQUEST|UNION_REQUEST)) != dm->type) { -+ error(FATAL, "data type mismatch: %s is not a %s\n", -+ dm->name, flags & UNION_REQUEST ? "union" : "struct"); -+ } -+ - if ((argc_members > 1) && !aflag) { - error(INFO, flags & SHOW_OFFSET ? - "-o option not valid with multiple member format\n" : -@@ -5891,7 +5931,52 @@ cmd_datatype_common(ulong flags) - error(FATAL, - "-o option not valid with multiple member format\n"); - -- len = dm->size; -+ set_temporary_radix(radix, &restore_radix); -+ -+ /* -+ * No address was passed -- dump the structure/member declaration. -+ */ -+ if (!aflag) { -+ if (argc_members && -+ !member_to_datatype(memberlist[0], dm, -+ ANON_MEMBER_QUERY)) -+ error(FATAL, "invalid data structure reference: %s.%s\n", -+ dm->name, memberlist[0]); -+ do_datatype_declaration(dm, flags | (dm->flags & TYPEDEF)); -+ } else if (cpus) { -+ for (c = 0; c < kt->cpus; c++) { -+ ulong cpuaddr; -+ -+ if (!NUM_IN_BITMAP(cpus, c)) -+ continue; -+ -+ cpuaddr = addr + kt->__per_cpu_offset[c]; -+ fprintf(fp, "[%d]: %lx\n", c, cpuaddr); -+ do_datatype_addr(dm, cpuaddr , count, -+ flags, memberlist, argc_members); -+ } -+ } else -+ do_datatype_addr(dm, addr, count, flags, -+ memberlist, argc_members); -+ -+ restore_current_radix(restore_radix); -+ -+freebuf: -+ if (argc_members) { -+ FREEBUF(structname); -+ FREEBUF(members); -+ } -+ -+ if (cpus) -+ FREEBUF(cpus); -+} -+ -+static void -+do_datatype_addr(struct datatype_member *dm, ulong addr, int count, -+ ulong flags, char **memberlist, int argc_members) -+{ -+ int i, c; -+ long len = dm->size; - - if (count < 0) { - addr -= len * abs(count); -@@ -5908,83 +5993,44 @@ cmd_datatype_common(ulong flags) - i = 0; - do { - if (argc_members) { -- *separator = '.'; -- strcpy(separator+1, memberlist[i]); -- } -- -- switch (arg_to_datatype(structname, dm, -- ANON_MEMBER_QUERY|RETURN_ON_ERROR)) -- { -- case 0: error(FATAL, "invalid data structure reference: %s\n", -- structname); -- break; -- case 1: break; -- case 2: if (rawdata) -+ if (!member_to_datatype(memberlist[i], dm, -+ ANON_MEMBER_QUERY)) -+ error(FATAL, "invalid data structure reference: %s.%s\n", -+ dm->name, memberlist[i]); -+ if (flags & SHOW_RAW_DATA) - error(FATAL, -- "member-specific output not allowed with -r\n"); -- break; -+ "member-specific output not allowed with -r\n"); - } - -- if (!(dm->flags & TYPEDEF)) { -- if (flags &(STRUCT_REQUEST|UNION_REQUEST) ) { -- if ((flags & (STRUCT_REQUEST|UNION_REQUEST)) != dm->type) -- goto freebuf; -- } else -- flags |= dm->type; -- } -- -- /* -- * No address was passed -- dump the structure/member declaration. -- */ -- if (!aflag || (aflag && (flags & SHOW_OFFSET))) { -- if (aflag) -- dm->vaddr = addr; -- set_temporary_radix(radix, &restore_radix); -- do_datatype_declaration(dm, flags | (dm->flags & TYPEDEF)); -- restore_current_radix(restore_radix); -- goto freebuf; -- } -- -- if (!(flags & (UNION_REQUEST|STRUCT_REQUEST))) -- error(FATAL, "invalid argument"); -- - /* -- * Display data. -+ * Display member addresses or data - */ -- if (rawdata) -+ if (flags & SHOW_OFFSET) { -+ dm->vaddr = addr; -+ do_datatype_declaration(dm, flags | (dm->flags & TYPEDEF)); -+ } else if (flags & SHOW_RAW_DATA) - raw_data_dump(addr, len, flags & STRUCT_VERBOSE); -- else if (pflag && !dm->member) { -- set_temporary_radix(radix, &restore_radix); -+ else if ((flags & DEREF_POINTERS) && !dm->member) { - print_struct_with_dereference(addr, dm, flags); -- restore_current_radix(restore_radix); - } else { - if (dm->member) - open_tmpfile(); - -- set_temporary_radix(radix, &restore_radix); -- - if (flags & UNION_REQUEST) - print_union(dm->name, addr); - else if (flags & STRUCT_REQUEST) - print_struct(dm->name, addr); - - if (dm->member) { -- if (!(pflag && -+ if (!((flags & DEREF_POINTERS) && - dereference_pointer(addr, dm, flags))) - parse_for_member(dm, PARSE_FOR_DATA); - close_tmpfile(); - } - -- restore_current_radix(restore_radix); - } - } while (++i < argc_members); - } -- --freebuf: -- if (argc_members) { -- FREEBUF(structname); -- FREEBUF(members); -- } - } - - -@@ -6108,13 +6154,7 @@ arg_to_datatype(char *s, struct datatype - if (!both) - return 1; - -- dm->member = p1+1; -- -- if ((dm->member_offset = MEMBER_OFFSET(dm->name, dm->member)) >= 0) -- return 2; -- -- if ((flags & ANON_MEMBER_QUERY) && -- ((dm->member_offset = ANON_MEMBER_OFFSET(dm->name, dm->member)) >= 0)) -+ if (member_to_datatype(p1 + 1, dm, flags)) - return 2; - - datatype_member_fatal: -@@ -6137,6 +6177,21 @@ datatype_member_fatal: - return (error(FATAL, "invalid argument: %s\n", s)); - } - -+static int -+member_to_datatype(char *s, struct datatype_member *dm, ulong flags) -+{ -+ dm->member = s; -+ -+ if ((dm->member_offset = MEMBER_OFFSET(dm->name, s)) >= 0) -+ return TRUE; -+ -+ if ((flags & ANON_MEMBER_QUERY) && -+ ((dm->member_offset = ANON_MEMBER_OFFSET(dm->name, s)) >= 0)) -+ return TRUE; -+ -+ return FALSE; -+} -+ - /* - * debug routine -- not called on purpose by anybody. - */ -@@ -6388,13 +6443,12 @@ cmd_p(void) - { - int c; - struct syment *sp, *percpu_sp; -- unsigned radix, restore_radix; -- int leader, do_load_module_filter, success; -+ unsigned radix; -+ int do_load_module_filter; - char buf1[BUFSIZE]; -- char buf2[BUFSIZE]; -- char *p1; -+ char *cpuspec; - -- leader = do_load_module_filter = radix = restore_radix = 0; -+ do_load_module_filter = radix = 0; - - while ((c = getopt(argcnt, args, "dhxu")) != EOF) { - switch(c) -@@ -6427,33 +6481,57 @@ cmd_p(void) - if (argerrs || !args[optind]) - cmd_usage(pc->curcmd, SYNOPSIS); - -+ cpuspec = strrchr(args[optind], ':'); -+ if (cpuspec) -+ *cpuspec++ = NULLCHAR; -+ -+ sp = NULL; - if ((sp = symbol_search(args[optind])) && !args[optind+1]) { - if ((percpu_sp = per_cpu_symbol_search(args[optind])) && -- display_per_cpu_info(percpu_sp)) -+ display_per_cpu_info(percpu_sp, radix, cpuspec)) - return; -- sprintf(buf2, "%s = ", args[optind]); -- leader = strlen(buf2); - if (module_symbol(sp->value, NULL, NULL, NULL, *gdb_output_radix)) - do_load_module_filter = TRUE; - } else if ((percpu_sp = per_cpu_symbol_search(args[optind])) && -- display_per_cpu_info(percpu_sp)) -+ display_per_cpu_info(percpu_sp, radix, cpuspec)) - return; - else if (st->flags & LOAD_MODULE_SYMS) - do_load_module_filter = TRUE; - -+ if (cpuspec) { -+ if (sp) -+ error(WARNING, "%s is not percpu; cpuspec ignored.\n", -+ sp->name); -+ else -+ /* maybe a valid C expression (e.g. ':') */ -+ *(cpuspec-1) = ':'; -+ } -+ -+ process_gdb_output(concat_args(buf1, 0, TRUE), radix, -+ sp ? sp->name : NULL, do_load_module_filter); -+} -+ -+static void -+process_gdb_output(char *gdb_request, unsigned radix, -+ const char *leader, int do_load_module_filter) -+{ -+ unsigned restore_radix; -+ int success; -+ char buf1[BUFSIZE]; -+ char *p1; -+ - if (leader || do_load_module_filter) - open_tmpfile(); - - set_temporary_radix(radix, &restore_radix); - -- success = gdb_pass_through(concat_args(buf1, 0, TRUE), NULL, -- GNU_RETURN_ON_ERROR); -+ success = gdb_pass_through(gdb_request, NULL, GNU_RETURN_ON_ERROR); - - if (success && (leader || do_load_module_filter)) { - int firstline; - - if (leader) { -- fprintf(pc->saved_fp, "%s", buf2); -+ fprintf(pc->saved_fp, "%s = ", leader); - fflush(pc->saved_fp); - } - -@@ -6482,8 +6560,41 @@ cmd_p(void) - restore_current_radix(restore_radix); - - if (!success) -- error(FATAL, "gdb request failed: %s\n", -- concat_args(buf1, 0, TRUE)); -+ error(FATAL, "gdb request failed: %s\n", gdb_request); -+} -+ -+/* -+ * Get the type of an expression using gdb's "whatis" command. -+ * The returned string is dynamically allocated, and it should -+ * be passed to FREEBUF() when no longer needed. -+ * Return NULL if the type cannot be determined. -+ */ -+static char * -+expr_type_name(const char *expr) -+{ -+ char buf[BUFSIZE], *p; -+ -+ open_tmpfile(); -+ sprintf(buf, "whatis %s", expr); -+ if (!gdb_pass_through(buf, fp, GNU_RETURN_ON_ERROR)) { -+ close_tmpfile(); -+ return NULL; -+ } -+ -+ rewind(pc->tmpfile); -+ while (fgets(buf, BUFSIZE, pc->tmpfile) && !STRNEQ(buf, "type = ")) -+ ; -+ p = feof(pc->tmpfile) ? NULL : buf + strlen("type = "); -+ close_tmpfile(); -+ -+ if (p) { -+ size_t len = strlen(clean_line(p)); -+ /* GDB reports unknown types as <...descriptive text...> */ -+ if (p[0] == '<' && p[len-1] == '>') -+ return NULL; -+ return strcpy(GETBUF(len + 1), p); -+ } -+ return NULL; - } - - /* -@@ -6491,30 +6602,73 @@ cmd_p(void) - * the addresses of each its per-cpu instances. - */ - static int --display_per_cpu_info(struct syment *sp) -+display_per_cpu_info(struct syment *sp, int radix, char *cpuspec) - { -+ ulong *cpus; - int c; - ulong addr; - char buf[BUFSIZE]; -+ char leader[sizeof("&per_cpu(") + strlen(sp->name) + -+ sizeof(", " STR(UINT_MAX) ")")]; -+ char *typename; -+ int do_load_module_filter; - - if (((kt->flags & (SMP|PER_CPU_OFF)) != (SMP|PER_CPU_OFF)) || - (!is_percpu_symbol(sp)) || - !((sp->type == 'd') || (sp->type == 'D') || (sp->type == 'V'))) - return FALSE; - -- fprintf(fp, "PER-CPU DATA TYPE:\n "); -- sprintf(buf, "whatis %s", sp->name); -- if (!gdb_pass_through(buf, pc->nullfp, GNU_RETURN_ON_ERROR)) -- fprintf(fp, "[undetermined type] %s;\n", sp->name); -- else -- whatis_variable(sp); -+ if (cpuspec) { -+ cpus = get_cpumask_buf(); -+ if (STREQ(cpuspec, "")) -+ SET_BIT(cpus, CURRENT_CONTEXT()->processor); -+ else -+ make_cpumask(cpuspec, cpus, FAULT_ON_ERROR, NULL); -+ } else -+ cpus = NULL; -+ -+ typename = expr_type_name(sp->name); -+ -+ if (!cpus) { -+ fprintf(fp, "PER-CPU DATA TYPE:\n "); -+ if (!typename) -+ fprintf(fp, "[undetermined type] %s;\n", sp->name); -+ else -+ whatis_variable(sp); -+ -+ fprintf(fp, "PER-CPU ADDRESSES:\n"); -+ } -+ -+ do_load_module_filter = -+ module_symbol(sp->value, NULL, NULL, NULL, *gdb_output_radix); - -- fprintf(fp, "PER-CPU ADDRESSES:\n"); - for (c = 0; c < kt->cpus; c++) { -+ if (cpus && !NUM_IN_BITMAP(cpus, c)) -+ continue; - addr = sp->value + kt->__per_cpu_offset[c]; -- fprintf(fp, " [%d]: %lx\n", c, addr); -+ if (!cpus) -+ fprintf(fp, " [%d]: %lx\n", c, addr); -+ else if (typename) { -+ snprintf(buf, sizeof buf, "p *(%s*) 0x%lx", -+ typename, addr); -+ sprintf(leader, "per_cpu(%s, %u)", -+ sp->name, c); -+ process_gdb_output(buf, radix, leader, -+ do_load_module_filter); -+ } else { -+ snprintf(buf, sizeof buf, "p (void*) 0x%lx", addr); -+ sprintf(leader, "&per_cpu(%s, %u)", -+ sp->name, c); -+ process_gdb_output(buf, radix, leader, -+ do_load_module_filter); -+ } - } - -+ if (typename) -+ FREEBUF(typename); -+ if (cpus) -+ FREEBUF(cpus); -+ - return TRUE; - } - -@@ -6859,6 +7013,10 @@ dump_datatype_flags(ulong flags, FILE *o - fprintf(ofp, "%sDATATYPE_QUERY", others++ ? "|" : ""); - if (flags & ANON_MEMBER_QUERY) - fprintf(ofp, "%sANON_MEMBER_QUERY", others++ ? "|" : ""); -+ if (flags & SHOW_RAW_DATA) -+ fprintf(ofp, "%sSHOW_RAW_DATA", others++ ? "|" : ""); -+ if (flags & DEREF_POINTERS) -+ fprintf(ofp, "%sDEREF_POINTERS", others++ ? "|" : ""); - fprintf(ofp, ")\n"); - } - -@@ -7890,11 +8048,18 @@ dump_offset_table(char *spec, ulong make - OFFSET(page_objects)); - fprintf(fp, " page_slab: %ld\n", - OFFSET(page_slab)); -+ fprintf(fp, " page_slab_page: %ld\n", -+ OFFSET(page_slab_page)); - fprintf(fp, " page_first_page: %ld\n", - OFFSET(page_first_page)); - fprintf(fp, " page_freelist: %ld\n", - OFFSET(page_freelist)); - -+ fprintf(fp, " trace_print_flags_mask: %ld\n", -+ OFFSET(trace_print_flags_mask)); -+ fprintf(fp, " trace_print_flags_name: %ld\n", -+ OFFSET(trace_print_flags_name)); -+ - fprintf(fp, " swap_info_struct_swap_file: %ld\n", - OFFSET(swap_info_struct_swap_file)); - fprintf(fp, " swap_info_struct_swap_vfsmnt: %ld\n", -@@ -9021,6 +9186,7 @@ dump_offset_table(char *spec, ulong make - fprintf(fp, "\n size_table:\n"); - fprintf(fp, " page: %ld\n", SIZE(page)); - fprintf(fp, " page_flags: %ld\n", SIZE(page_flags)); -+ fprintf(fp, " trace_print_flags: %ld\n", SIZE(trace_print_flags)); - fprintf(fp, " free_area_struct: %ld\n", - SIZE(free_area_struct)); - fprintf(fp, " free_area: %ld\n", ---- crash-7.0.2/diskdump.c 2013-10-25 15:28:55.941879568 -0400 -+++ crash-7.0.3/diskdump.c 2013-10-23 09:12:15.913831516 -0400 -@@ -40,11 +40,13 @@ struct diskdump_data { - struct disk_dump_sub_header *sub_header; - struct kdump_sub_header *sub_header_kdump; - -+ unsigned long long max_mapnr; /* 64bit max_mapnr */ -+ - size_t data_offset; - int block_size; - int block_shift; - char *bitmap; -- int bitmap_len; -+ off_t bitmap_len; - char *dumpable_bitmap; - int byte, bit; - char *compressed_page; /* copy of compressed page data */ -@@ -170,9 +172,9 @@ add_diskdump_data(char* name) - dd->filename = name; - - if (CRASHDEBUG(1)) -- fprintf(fp, "%s: start_pfn=%lu, end_pfn=%lu\n", name, -- dd->sub_header_kdump->start_pfn, -- dd->sub_header_kdump->end_pfn); -+ fprintf(fp, "%s: start_pfn=%llu, end_pfn=%llu\n", name, -+ dd->sub_header_kdump->start_pfn_64, -+ dd->sub_header_kdump->end_pfn_64); - } - - static void -@@ -199,13 +201,13 @@ get_bit(char *map, int byte, int bit) - } - - static inline int --page_is_ram(unsigned int nr) -+page_is_ram(unsigned long nr) - { - return get_bit(dd->bitmap, nr >> 3, nr & 7); - } - - static inline int --page_is_dumpable(unsigned int nr) -+page_is_dumpable(unsigned long nr) - { - return dd->dumpable_bitmap[nr>>3] & (1 << (nr & 7)); - } -@@ -214,7 +216,7 @@ static inline int - dump_is_partial(const struct disk_dump_header *header) - { - return header->bitmap_blocks >= -- divideup(divideup(header->max_mapnr, 8), dd->block_size) * 2; -+ divideup(divideup(dd->max_mapnr, 8), dd->block_size) * 2; - } - - static int -@@ -321,6 +323,9 @@ x86_process_elf_notes(void *note_ptr, un - * [40] unsigned long size_note; / header_version 4 and later / - * [44] off_t offset_eraseinfo; / header_version 5 and later / - * [52] unsigned long size_eraseinfo; / header_version 5 and later / -+ * [56] unsigned long long start_pfn_64; / header_version 6 and later / -+ * [64] unsigned long long end_pfn_64; / header_version 6 and later / -+ * [72] unsigned long long max_mapnr_64; / header_version 6 and later / - * }; - * - * But when compiled on an ARM processor, each 64-bit "off_t" would be pushed -@@ -337,7 +342,10 @@ x86_process_elf_notes(void *note_ptr, un - * [40] off_t offset_note; / header_version 4 and later / - * [48] unsigned long size_note; / header_version 4 and later / - * [56] off_t offset_eraseinfo; / header_version 5 and later / -- * [62] unsigned long size_eraseinfo; / header_version 5 and later / -+ * [64] unsigned long size_eraseinfo; / header_version 5 and later / -+ * [72] unsigned long long start_pfn_64; / header_version 6 and later / -+ * [80] unsigned long long end_pfn_64; / header_version 6 and later / -+ * [88] unsigned long long max_mapnr_64; / header_version 6 and later / - * }; - * - */ -@@ -357,6 +365,10 @@ struct kdump_sub_header_ARM_target { - int pad3; - off_t offset_eraseinfo; /* header_version 5 and later */ - unsigned long size_eraseinfo; /* header_version 5 and later */ -+ int pad4; -+ unsigned long long start_pfn_64; /* header_version 6 and later */ -+ unsigned long long end_pfn_64; /* header_version 6 and later */ -+ unsigned long long max_mapnr_64; /* header_version 6 and later */ - }; - - static void -@@ -380,6 +392,15 @@ arm_kdump_header_adjust(int header_versi - kdsh->offset_eraseinfo = kdsh_ARM_target->offset_eraseinfo; - kdsh->size_eraseinfo = kdsh_ARM_target->size_eraseinfo; - } -+ if (header_version >= 6) { -+ kdsh->start_pfn_64 = kdsh_ARM_target->start_pfn_64; -+ kdsh->end_pfn_64 = kdsh_ARM_target->end_pfn_64; -+ kdsh->max_mapnr_64 = kdsh_ARM_target->max_mapnr_64; -+ } else { -+ kdsh->start_pfn_64 = kdsh_ARM_target->start_pfn; -+ kdsh->end_pfn_64 = kdsh_ARM_target->end_pfn; -+ kdsh->max_mapnr_64 = dd->max_mapnr; -+ } - } - #endif /* __i386__ && ARM */ - -@@ -390,7 +411,10 @@ read_dump_header(char *file) - struct disk_dump_sub_header *sub_header = NULL; - struct kdump_sub_header *sub_header_kdump = NULL; - size_t size; -- int bitmap_len; -+ off_t bitmap_len; -+ char *bufptr; -+ size_t len; -+ ssize_t bytes_read; - int block_size = (int)sysconf(_SC_PAGESIZE); - off_t offset; - const off_t failed = (off_t)-1; -@@ -516,6 +540,13 @@ restart: - } - } - dd->sub_header = sub_header; -+ -+ /* the 64bit max_mapnr only exists in sub-header of compressed -+ * kdump file, if it's not a compressed kdump file, we have to -+ * use the old 32bit max_mapnr in dumpfile header. -+ * max_mapnr may be truncated here. -+ */ -+ dd->max_mapnr = header->max_mapnr; - } else if (KDUMP_CMPRS_VALID()) { - if ((sub_header_kdump = malloc(block_size)) == NULL) - error(FATAL, "compressed kdump: cannot malloc sub_header_kdump buffer\n"); -@@ -540,8 +571,20 @@ restart: - #if defined(__i386__) && defined(ARM) - arm_kdump_header_adjust(header->header_version); - #endif -+ /* use 64bit max_mapnr in compressed kdump file sub-header */ -+ if (header->header_version >= 6) -+ dd->max_mapnr = dd->sub_header_kdump->max_mapnr_64; -+ else { -+ dd->sub_header_kdump->start_pfn_64 -+ = dd->sub_header_kdump->start_pfn; -+ dd->sub_header_kdump->end_pfn_64 -+ = dd->sub_header_kdump->end_pfn; -+ } - } - -+ if (header->header_version < 6) -+ dd->max_mapnr = header->max_mapnr; -+ - /* read memory bitmap */ - bitmap_len = block_size * header->bitmap_blocks; - dd->bitmap_len = bitmap_len; -@@ -571,10 +614,18 @@ restart: - DISKDUMP_VALID() ? "diskdump" : "compressed kdump"); - goto err; - } -- if (read(dd->dfd, dd->bitmap, bitmap_len) < bitmap_len) { -- error(INFO, "%s: cannot read memory bitmap\n", -- DISKDUMP_VALID() ? "diskdump" : "compressed kdump"); -- goto err; -+ bufptr = dd->bitmap; -+ len = bitmap_len; -+ while (len) { -+ bytes_read = read(dd->dfd, bufptr, len); -+ if (bytes_read < 0) { -+ error(INFO, "%s: cannot read memory bitmap\n", -+ DISKDUMP_VALID() ? "diskdump" -+ : "compressed kdump"); -+ goto err; -+ } -+ len -= bytes_read; -+ bufptr += bytes_read; - } - } - -@@ -679,13 +730,13 @@ restart: - } - - if (!is_split) { -- max_sect_len = divideup(header->max_mapnr, BITMAP_SECT_LEN); -+ max_sect_len = divideup(dd->max_mapnr, BITMAP_SECT_LEN); - pfn = 0; - dd->filename = file; - } - else { -- ulong start = sub_header_kdump->start_pfn; -- ulong end = sub_header_kdump->end_pfn; -+ unsigned long long start = sub_header_kdump->start_pfn_64; -+ unsigned long long end = sub_header_kdump->end_pfn_64; - max_sect_len = divideup(end - start + 1, BITMAP_SECT_LEN); - pfn = start; - } -@@ -727,8 +778,9 @@ pfn_to_pos(ulong pfn) - ulong p1, p2; - - if (KDUMP_SPLIT()) { -- p1 = pfn - dd->sub_header_kdump->start_pfn; -- p2 = round(p1, BITMAP_SECT_LEN) + dd->sub_header_kdump->start_pfn; -+ p1 = pfn - dd->sub_header_kdump->start_pfn_64; -+ p2 = round(p1, BITMAP_SECT_LEN) -+ + dd->sub_header_kdump->start_pfn_64; - } - else { - p1 = pfn; -@@ -1034,12 +1086,12 @@ read_diskdump(int fd, void *bufptr, int - if (KDUMP_SPLIT()) { - /* Find proper dd */ - int i; -- unsigned long start_pfn; -- unsigned long end_pfn; -+ unsigned long long start_pfn; -+ unsigned long long end_pfn; - - for (i=0; isub_header_kdump->start_pfn; -- end_pfn = dd_list[i]->sub_header_kdump->end_pfn; -+ start_pfn = dd_list[i]->sub_header_kdump->start_pfn_64; -+ end_pfn = dd_list[i]->sub_header_kdump->end_pfn_64; - if ((pfn >= start_pfn) && (pfn <= end_pfn)) { - dd = dd_list[i]; - break; -@@ -1058,14 +1110,14 @@ read_diskdump(int fd, void *bufptr, int - curpaddr = paddr & ~((physaddr_t)(dd->block_size-1)); - page_offset = paddr & ((physaddr_t)(dd->block_size-1)); - -- if ((pfn >= dd->header->max_mapnr) || !page_is_ram(pfn)) { -+ if ((pfn >= dd->max_mapnr) || !page_is_ram(pfn)) { - if (CRASHDEBUG(8)) { - fprintf(fp, "read_diskdump: SEEK_ERROR: " - "paddr/pfn: %llx/%lx ", - (ulonglong)paddr, pfn); -- if (pfn >= dd->header->max_mapnr) -- fprintf(fp, "max_mapnr: %x\n", -- dd->header->max_mapnr); -+ if (pfn >= dd->max_mapnr) -+ fprintf(fp, "max_mapnr: %llx\n", -+ dd->max_mapnr); - else - fprintf(fp, "!page_is_ram\n"); - } -@@ -1507,12 +1559,31 @@ __diskdump_memory_dump(FILE *fp) - fprintf(fp, " tv_usec: %lx\n", dh->timestamp.tv_usec); - fprintf(fp, " status: %x (", dh->status); - others = 0; -- if (dh->status & DUMP_HEADER_COMPLETED) -- fprintf(fp, "%sDUMP_HEADER_COMPLETED", others++ ? "|" : ""); -- if (dh->status & DUMP_HEADER_INCOMPLETED) -- fprintf(fp, "%sDUMP_HEADER_INCOMPLETED", others++ ? "|" : ""); -- if (dh->status & DUMP_HEADER_COMPRESSED) -- fprintf(fp, "%sDUMP_HEADER_COMPRESSED", others++ ? "|" : ""); -+ switch (dd->flags & (DISKDUMP_LOCAL|KDUMP_CMPRS_LOCAL)) -+ { -+ case DISKDUMP_LOCAL: -+ if (dh->status == DUMP_HEADER_COMPLETED) -+ fprintf(fp, "%sDUMP_HEADER_COMPLETED", -+ others++ ? "|" : ""); -+ else if (dh->status == DUMP_HEADER_INCOMPLETED) -+ fprintf(fp, "%sDUMP_HEADER_INCOMPLETED", -+ others++ ? "|" : ""); -+ else if (dh->status == DUMP_HEADER_COMPRESSED) -+ fprintf(fp, "%sDUMP_HEADER_COMPRESSED", -+ others++ ? "|" : ""); -+ break; -+ case KDUMP_CMPRS_LOCAL: -+ if (dh->status & DUMP_DH_COMPRESSED_ZLIB) -+ fprintf(fp, "%sDUMP_DH_COMPRESSED_ZLIB", -+ others++ ? "|" : ""); -+ if (dh->status & DUMP_DH_COMPRESSED_LZO) -+ fprintf(fp, "%sDUMP_DH_COMPRESSED_LZO", -+ others++ ? "|" : ""); -+ if (dh->status & DUMP_DH_COMPRESSED_SNAPPY) -+ fprintf(fp, "%sDUMP_DH_COMPRESSED_SNAPPY", -+ others++ ? "|" : ""); -+ break; -+ } - fprintf(fp, ")\n"); - fprintf(fp, " block_size: %d\n", dh->block_size); - fprintf(fp, " sub_hdr_size: %d\n", dh->sub_hdr_size); -@@ -1662,6 +1733,23 @@ __diskdump_memory_dump(FILE *fp) - dump_eraseinfo(fp); - } - } -+ if (dh->header_version >= 6) { -+ fprintf(fp, " start_pfn_64: "); -+ if (KDUMP_SPLIT()) -+ fprintf(fp, "%lld (0x%llx)\n", -+ kdsh->start_pfn_64, kdsh->start_pfn_64); -+ else -+ fprintf(fp, "(unused)\n"); -+ fprintf(fp, " end_pfn_64: "); -+ if (KDUMP_SPLIT()) -+ fprintf(fp, "%lld (0x%llx)\n", -+ kdsh->end_pfn_64, kdsh->end_pfn_64); -+ else -+ fprintf(fp, "(unused)\n"); -+ -+ fprintf(fp, " max_mapnr_64: %llu (0x%llx)\n", -+ kdsh->max_mapnr_64, kdsh->max_mapnr_64); -+ } - fprintf(fp, "\n"); - } else - fprintf(fp, "(n/a)\n\n"); -@@ -1670,7 +1758,8 @@ __diskdump_memory_dump(FILE *fp) - fprintf(fp, " block_size: %d\n", dd->block_size); - fprintf(fp, " block_shift: %d\n", dd->block_shift); - fprintf(fp, " bitmap: %lx\n", (ulong)dd->bitmap); -- fprintf(fp, " bitmap_len: %d\n", dd->bitmap_len); -+ fprintf(fp, " bitmap_len: %lld\n", (ulonglong)dd->bitmap_len); -+ fprintf(fp, " max_mapnr: %lld (0x%llx)\n", dd->max_mapnr, dd->max_mapnr); - fprintf(fp, " dumpable_bitmap: %lx\n", (ulong)dd->dumpable_bitmap); - fprintf(fp, " byte: %d\n", dd->byte); - fprintf(fp, " bit: %d\n", dd->bit); ---- crash-7.0.2/makedumpfile.c 2013-10-25 15:28:55.951879567 -0400 -+++ crash-7.0.3/makedumpfile.c 2013-10-25 10:10:07.615755902 -0400 -@@ -59,7 +59,7 @@ store_flat_data_array(char *file, struct - unsigned long long num_allocated = 0; - unsigned long long num_stored = 0; - unsigned long long size_allocated; -- struct flat_data *ptr = NULL, *cur; -+ struct flat_data *ptr = NULL, *cur, *new; - struct makedumpfile_data_header fdh; - - fd = open(file, O_RDONLY); -@@ -77,12 +77,13 @@ store_flat_data_array(char *file, struct - num_allocated += 100; - size_allocated = sizeof(struct flat_data) - * num_allocated; -- ptr = realloc(ptr, size_allocated); -- if (ptr == NULL) { -+ new = realloc(ptr, size_allocated); -+ if (new == NULL) { - error(INFO, - "unable to realloc flat_data structures\n"); - break; - } -+ ptr = new; - } - offset_fdh = lseek(fd, 0x0, SEEK_CUR); - ---- crash-7.0.2/unwind_arm.c 2013-10-25 15:28:55.938879568 -0400 -+++ crash-7.0.3/unwind_arm.c 2013-09-06 15:03:40.804904775 -0400 -@@ -325,7 +325,8 @@ init_module_unwind_tables(void) - hq_open(); - cnt = do_list(&ld); - if (cnt == -1) { -- error(WARNING, "UNWIND: failed to gather unwind_table list"); -+ error(WARNING, "UNWIND: failed to gather unwind_table list\n"); -+ hq_close(); - return FALSE; - } - table_list = (ulong *)GETBUF(cnt * sizeof(ulong)); ---- crash-7.0.2/sadump.c 2013-10-25 15:28:55.941879568 -0400 -+++ crash-7.0.3/sadump.c 2013-10-25 10:10:13.104755651 -0400 -@@ -18,6 +18,7 @@ - - #include "defs.h" - #include "sadump.h" -+#include /* htonl, htons */ - #include - - enum { -@@ -118,7 +119,7 @@ read_dump_header(char *file) - { - struct sadump_part_header *sph = NULL; - struct sadump_header *sh = NULL; -- struct sadump_disk_set_header *sdh = NULL; -+ struct sadump_disk_set_header *new, *sdh = NULL; - struct sadump_media_header *smh = NULL; - struct sadump_diskset_data *sd_list_len_0 = NULL; - size_t block_size = SADUMP_DEFAULT_BLOCK_SIZE; -@@ -127,7 +128,8 @@ read_dump_header(char *file) - uint32_t smram_cpu_state_size = 0; - ulong bitmap_len, dumpable_bitmap_len; - char *bitmap = NULL, *dumpable_bitmap = NULL, *page_buf = NULL; -- char guid1[33], guid2[33]; -+ char guid1[SADUMP_EFI_GUID_TEXT_REPR_LEN+1]; -+ char guid2[SADUMP_EFI_GUID_TEXT_REPR_LEN+1]; - - sph = malloc(block_size); - if (!sph) { -@@ -226,12 +228,13 @@ restart: - header_size = header_blocks * block_size; - - if (header_size > block_size) { -- sdh = realloc(sdh, header_size); -- if (!sdh) { -+ new = realloc(sdh, header_size); -+ if (!new) { - error(INFO, "sadump: cannot re-allocate disk " - "set buffer\n"); - goto err; - } -+ sdh = new; - } - - if (!read_device(sdh, header_size, &offset)) { -@@ -468,7 +471,8 @@ add_disk(char *file) - struct sadump_part_header *ph; - struct sadump_diskset_data *this_disk; - int diskid; -- char guid1[33], guid2[33]; -+ char guid1[SADUMP_EFI_GUID_TEXT_REPR_LEN+1]; -+ char guid2[SADUMP_EFI_GUID_TEXT_REPR_LEN+1]; - - diskid = sd->sd_list_len - 1; - this_disk = sd->sd_list[diskid]; -@@ -863,7 +867,7 @@ guid_to_str(efi_guid_t *guid, char *buf, - { - snprintf(buf, buflen, - "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", -- guid->data1, guid->data2, guid->data3, -+ htonl(guid->data1), htons(guid->data2), htons(guid->data3), - guid->data4[0], guid->data4[1], guid->data4[2], - guid->data4[3], guid->data4[4], guid->data4[5], - guid->data4[6], guid->data4[7]); -@@ -905,7 +909,7 @@ int sadump_memory_dump(FILE *fp) - struct sadump_header *sh; - struct sadump_media_header *smh; - int i, others; -- char guid[33]; -+ char guid[SADUMP_EFI_GUID_TEXT_REPR_LEN+1]; - - fprintf(fp, "sadump_data: \n"); - fprintf(fp, " filename: %s\n", sd->filename); ---- crash-7.0.2/defs.h 2013-10-25 15:28:55.937879568 -0400 -+++ crash-7.0.3/defs.h 2013-10-25 11:49:58.544481437 -0400 -@@ -59,7 +59,7 @@ - #define ATTRIBUTE_UNUSED __attribute__ ((__unused__)) - #endif - --#define BASELEVEL_REVISION "7.0.2" -+#define BASELEVEL_REVISION "7.0.3" - - #undef TRUE - #undef FALSE -@@ -503,6 +503,7 @@ struct program_context { - #define QEMU_MEM_DUMP (0x100ULL) - #define GET_LOG (0x200ULL) - #define VMCOREINFO (0x400ULL) -+#define ALLOW_FP (0x800ULL) - char *cleanup; - char *namelist_orig; - char *namelist_debug_orig; -@@ -1876,6 +1877,9 @@ struct offset_table { - long task_struct_thread_context_fp; - long task_struct_thread_context_sp; - long task_struct_thread_context_pc; -+ long page_slab_page; -+ long trace_print_flags_mask; -+ long trace_print_flags_name; - }; - - struct size_table { /* stash of commonly-used sizes */ -@@ -2016,6 +2020,7 @@ struct size_table { /* stash of - long hrtimer_clock_base; - long hrtimer_base; - long tnt; -+ long trace_print_flags; - }; - - struct array_table { -@@ -2183,6 +2188,13 @@ struct vm_table { /* kern - int cpu_slab_type; - int nr_vm_event_items; - char **vm_event_items; -+ int nr_bad_slab_caches; -+ ulong *bad_slab_caches; -+ int nr_pageflags; -+ struct pageflags_data { -+ ulong mask; -+ char *name; -+ } *pageflags_data; - }; - - #define NODES (0x1) -@@ -2211,6 +2223,7 @@ struct vm_table { /* kern - #define NODELISTS_IS_PTR (0x800000) - #define KMALLOC_COMMON (0x1000000) - #define USE_VMAP_AREA (0x2000000) -+#define PAGEFLAGS (0x4000000) - - #define IS_FLATMEM() (vt->flags & FLATMEM) - #define IS_DISCONTIGMEM() (vt->flags & DISCONTIGMEM) -@@ -4321,6 +4334,7 @@ int calculate(char *, ulong *, ulonglong - int endian_mismatch(char *, char, ulong); - uint16_t swap16(uint16_t, int); - uint32_t swap32(uint32_t, int); -+ulong *get_cpumask_buf(void); - int make_cpumask(char *, ulong *, int, int *); - size_t strlcpy(char *, char *, size_t); - struct rb_node *rb_first(struct rb_root *); ---- crash-7.0.2/diskdump.h 2013-10-25 15:28:56.133879559 -0400 -+++ crash-7.0.3/diskdump.h 2013-10-18 11:11:20.610295600 -0400 -@@ -42,7 +42,9 @@ struct disk_dump_header { - header in blocks */ - unsigned int bitmap_blocks; /* Size of Memory bitmap in - block */ -- unsigned int max_mapnr; /* = max_mapnr */ -+ unsigned int max_mapnr; /* = max_mapnr, OBSOLETE! -+ 32bit only, full 64bit -+ in sub header. */ - unsigned int total_ram_blocks;/* Number of blocks should be - written */ - unsigned int device_blocks; /* Number of total blocks in -@@ -61,14 +63,21 @@ struct kdump_sub_header { - unsigned long phys_base; - int dump_level; /* header_version 1 and later */ - int split; /* header_version 2 and later */ -- unsigned long start_pfn; /* header_version 2 and later */ -- unsigned long end_pfn; /* header_version 2 and later */ -+ unsigned long start_pfn; /* header_version 2 and later, -+ OBSOLETE! 32bit only, full 64bit -+ in start_pfn_64. */ -+ unsigned long end_pfn; /* header_version 2 and later, -+ OBSOLETE! 32bit only, full 64bit -+ in end_pfn_64. */ - off_t offset_vmcoreinfo; /* header_version 3 and later */ - unsigned long size_vmcoreinfo; /* header_version 3 and later */ - off_t offset_note; /* header_version 4 and later */ - unsigned long size_note; /* header_version 4 and later */ - off_t offset_eraseinfo; /* header_version 5 and later */ - unsigned long size_eraseinfo; /* header_version 5 and later */ -+ unsigned long long start_pfn_64; /* header_version 6 and later */ -+ unsigned long long end_pfn_64; /* header_version 6 and later */ -+ unsigned long long max_mapnr_64; /* header_version 6 and later */ - }; - - /* page flags */ ---- crash-7.0.2/lkcd_vmdump_v1.h 2013-10-25 15:28:55.935879568 -0400 -+++ crash-7.0.3/lkcd_vmdump_v1.h 2013-10-24 09:06:51.222888110 -0400 -@@ -117,10 +117,12 @@ typedef struct _dump_header_s { - #ifndef IA64 - #ifndef S390 - #ifndef S390X -+#ifndef ARM64 - struct pt_regs dh_regs; - #endif - #endif - #endif -+#endif - - /* the address of the current task */ - struct task_struct *dh_current_task; ---- crash-7.0.2/lkcd_vmdump_v2_v3.h 2013-10-25 15:28:55.938879568 -0400 -+++ crash-7.0.3/lkcd_vmdump_v2_v3.h 2013-10-24 09:13:13.588870592 -0400 -@@ -84,9 +84,11 @@ typedef struct _dump_header_asm_s { - /* the dump registers */ - #ifndef S390 - #ifndef S390X -+#ifndef ARM64 - struct pt_regs dha_regs; - #endif - #endif -+#endif - - } dump_header_asm_t; - ---- crash-7.0.2/sadump.h 2013-10-25 15:28:55.939879568 -0400 -+++ crash-7.0.3/sadump.h 2013-09-13 08:48:05.576229221 -0400 -@@ -41,6 +41,8 @@ typedef struct { - uint8_t data4[8]; - } efi_guid_t; - -+#define SADUMP_EFI_GUID_TEXT_REPR_LEN 36 -+ - struct sadump_part_header { - #define SADUMP_SIGNATURE1 0x75646173 - #define SADUMP_SIGNATURE2 0x0000706d ---- crash-7.0.2/extensions/snap.c 2013-10-25 15:28:55.943879568 -0400 -+++ crash-7.0.3/extensions/snap.c 2013-10-25 10:10:39.188754456 -0400 -@@ -416,7 +416,8 @@ generate_elf_header(int type, int fd, ch - } else if (machine_type("PPC64")) { - e_machine = EM_PPC64; - prstatus_len = sizeof(prstatus.ppc64); -- } -+ } else -+ return NULL; - - /* should be enought for the notes + roundup + two blocks */ - buffer = (char *)GETBUF(sizeof(Elf64_Ehdr) + -@@ -538,7 +539,7 @@ generate_elf_header(int type, int fd, ch - break; - } - -- l_offset += load[i].p_filesz; -+// l_offset += load[i].p_filesz; - offset += sizeof(Elf64_Phdr); - ptr += sizeof(Elf64_Phdr); - } ---- crash-7.0.2/extensions/trace.c 2013-10-25 15:28:55.944879568 -0400 -+++ crash-7.0.3/extensions/trace.c 2013-10-25 10:10:44.031754234 -0400 -@@ -1453,6 +1453,7 @@ static void ftrace_show(int argc, char * - if ((file = popen(trace_cmd, "r"))) { - ret = fread(buf, 1, sizeof(buf), file); - buf[ret] = 0; -+ pclose(file); - } - if (!strstr(buf, "trace-cmd version")) { - if (env_trace_cmd) ---- crash-7.0.3/defs.h.orig -+++ crash-7.0.3/defs.h -@@ -1880,6 +1880,8 @@ struct offset_table { - long page_slab_page; - long trace_print_flags_mask; - long trace_print_flags_name; -+ long task_struct_rss_stat; -+ long task_rss_stat_count; - }; - - struct size_table { /* stash of commonly-used sizes */ ---- crash-7.0.3/symbols.c.orig -+++ crash-7.0.3/symbols.c -@@ -7643,6 +7643,10 @@ dump_offset_table(char *spec, ulong make - OFFSET(task_struct_tgid)); - fprintf(fp, " task_struct_namespace: %ld\n", - OFFSET(task_struct_namespace)); -+ fprintf(fp, " task_struct_rss_stat: %ld\n", -+ OFFSET(task_struct_rss_stat)); -+ fprintf(fp, " task_rss_stat_count: %ld\n", -+ OFFSET(task_rss_stat_count)); - fprintf(fp, " task_struct_pids: %ld\n", - OFFSET(task_struct_pids)); - fprintf(fp, " task_struct_last_run: %ld\n", ---- crash-7.0.3/memory.c.orig -+++ crash-7.0.3/memory.c -@@ -4003,6 +4003,7 @@ void - get_task_mem_usage(ulong task, struct task_mem_usage *tm) - { - struct task_context *tc; -+ long rss = 0; - - BZERO(tm, sizeof(struct task_mem_usage)); - -@@ -4036,22 +4037,65 @@ get_task_mem_usage(ulong task, struct ta - filepages = 0; - anonpages = 1; - } -- tm->rss += ULONG(tt->mm_struct + -+ rss += LONG(tt->mm_struct + - OFFSET(mm_struct_rss_stat) + - OFFSET(mm_rss_stat_count) + -- (filepages * sizeof(ulong))); -- tm->rss += ULONG(tt->mm_struct + -+ (filepages * sizeof(long))); -+ rss += LONG(tt->mm_struct + - OFFSET(mm_struct_rss_stat) + - OFFSET(mm_rss_stat_count) + -- (anonpages * sizeof(ulong))); -+ (anonpages * sizeof(long))); - } -+ -+ /* Check whether SPLIT_RSS_COUNTING is enabled */ -+ if (VALID_MEMBER(task_struct_rss_stat)) { -+ int i, sync_rss; -+ ulong tgid; -+ struct task_context *tc1; -+ -+ tgid = task_tgid(task); -+ -+ tc1 = FIRST_CONTEXT(); -+ for (i = 0; i < RUNNING_TASKS(); i++, tc1++) { -+ if (task_tgid(tc1->task) != tgid) -+ continue; -+ -+ /* count 0 -> filepages */ -+ if (!readmem(tc1->task + -+ OFFSET(task_struct_rss_stat) + -+ OFFSET(task_rss_stat_count), KVADDR, -+ &sync_rss, -+ sizeof(int), -+ "task_struct rss_stat MM_FILEPAGES", -+ RETURN_ON_ERROR)) -+ continue; -+ -+ rss += sync_rss; -+ -+ /* count 1 -> anonpages */ -+ if (!readmem(tc1->task + -+ OFFSET(task_struct_rss_stat) + -+ OFFSET(task_rss_stat_count) + -+ sizeof(int), -+ KVADDR, &sync_rss, -+ sizeof(int), -+ "task_struct rss_stat MM_ANONPAGES", -+ RETURN_ON_ERROR)) -+ continue; -+ -+ rss += sync_rss; -+ } -+ } -+ - /* - * mm_struct._anon_rss and mm_struct._file_rss should exist. - */ - if (VALID_MEMBER(mm_struct_anon_rss)) -- tm->rss += ULONG(tt->mm_struct + OFFSET(mm_struct_anon_rss)); -+ rss += LONG(tt->mm_struct + OFFSET(mm_struct_anon_rss)); - if (VALID_MEMBER(mm_struct_file_rss)) -- tm->rss += ULONG(tt->mm_struct + OFFSET(mm_struct_file_rss)); -+ rss += LONG(tt->mm_struct + OFFSET(mm_struct_file_rss)); -+ -+ tm->rss = (unsigned long)rss; - } - tm->total_vm = ULONG(tt->mm_struct + OFFSET(mm_struct_total_vm)); - tm->pgd_addr = ULONG(tt->mm_struct + OFFSET(mm_struct_pgd)); ---- crash-7.0.3/task.c.orig -+++ crash-7.0.3/task.c -@@ -349,6 +349,11 @@ task_init(void) - MEMBER_OFFSET_INIT(task_struct_run_list, "task_struct", - "run_list"); - -+ MEMBER_OFFSET_INIT(task_struct_rss_stat, "task_struct", -+ "rss_stat"); -+ MEMBER_OFFSET_INIT(task_rss_stat_count, "task_rss_stat", -+ "count"); -+ - if ((tt->task_struct = (char *)malloc(SIZE(task_struct))) == NULL) - error(FATAL, "cannot malloc task_struct space."); - diff --git a/SOURCES/use_QEMU_registers_for_active_task_backtraces.patch b/SOURCES/use_QEMU_registers_for_active_task_backtraces.patch new file mode 100644 index 0000000..327ee92 --- /dev/null +++ b/SOURCES/use_QEMU_registers_for_active_task_backtraces.patch @@ -0,0 +1,213 @@ +commit b4af1d9b48998186aef8cd9abc47c6d59e36114e +Author: Dave Anderson +Date: Tue Dec 2 17:26:40 2014 -0500 + + Fix for finding the starting stack and instruction pointer hooks for + the active tasks in x86_64 ELF or compressed dumpfiles created by the + KVM "virsh dump --memory-only" facility. Without the patch, the + backtraces of active tasks may show an invalid starting frame that + indicates "__schedule". The fix displays the exception RIP and dumps + the register contents that are stored in the dumpfile header. If the + active task was operating in the kernel, the backtrace continues from + there; if the task was operating in user-space, the backtrace is + complete at that point. + (anderson@redhat.com) + +diff --git a/defs.h b/defs.h +index 2e52bc4..dc2d65a 100644 +--- a/defs.h ++++ b/defs.h +@@ -5547,6 +5547,7 @@ int write_proc_kcore(int, void *, int, ulong, physaddr_t); + int kcore_memory_dump(FILE *); + void dump_registers_for_qemu_mem_dump(void); + void kdump_backup_region_init(void); ++void display_regs_from_elf_notes(int, FILE *); + + /* + * ramdump.c +diff --git a/diskdump.c b/diskdump.c +index 3d33fdc..6b2aab5 100644 +--- a/diskdump.c ++++ b/diskdump.c +@@ -102,6 +102,9 @@ map_cpus_to_prstatus_kdump_cmprs(void) + int online, i, j, nrcpus; + size_t size; + ++ if (pc->flags2 & QEMU_MEM_DUMP_COMPRESSED) /* notes exist for all cpus */ ++ return; ++ + if (!(online = get_cpus_online()) || (online == kt->cpus)) + return; + +diff --git a/netdump.c b/netdump.c +index 903faa0..6029a54 100644 +--- a/netdump.c ++++ b/netdump.c +@@ -72,6 +72,9 @@ map_cpus_to_prstatus(void) + int online, i, j, nrcpus; + size_t size; + ++ if (pc->flags2 & QEMU_MEM_DUMP_ELF) /* notes exist for all cpus */ ++ return; ++ + if (!(online = get_cpus_online()) || (online == kt->cpus)) + return; + +@@ -2398,8 +2401,8 @@ get_regs_from_note(char *note, ulong *ip, ulong *sp) + return user_regs; + } + +-static void +-display_regs_from_elf_notes(int cpu) ++void ++display_regs_from_elf_notes(int cpu, FILE *ofp) + { + Elf32_Nhdr *note32; + Elf64_Nhdr *note64; +@@ -2408,13 +2411,16 @@ display_regs_from_elf_notes(int cpu) + int c, skipped_count; + + /* +- * NT_PRSTATUS notes are only related to online cpus, offline cpus +- * should be skipped. ++ * Kdump NT_PRSTATUS notes are only related to online cpus, ++ * so offline cpus should be skipped. + */ +- skipped_count = 0; +- for (c = 0; c < cpu; c++) { +- if (check_offline_cpu(c)) +- skipped_count++; ++ if (pc->flags2 & QEMU_MEM_DUMP_ELF) ++ skipped_count = 0; ++ else { ++ for (c = skipped_count = 0; c < cpu; c++) { ++ if (check_offline_cpu(c)) ++ skipped_count++; ++ } + } + + if ((cpu - skipped_count) >= nd->num_prstatus_notes) { +@@ -2433,7 +2439,7 @@ display_regs_from_elf_notes(int cpu) + len = roundup(len + note64->n_descsz, 4); + user_regs = ((char *)note64) + len - SIZE(user_regs_struct) - sizeof(long); + +- fprintf(fp, ++ fprintf(ofp, + " RIP: %016llx RSP: %016llx RFLAGS: %08llx\n" + " RAX: %016llx RBX: %016llx RCX: %016llx\n" + " RDX: %016llx RSI: %016llx RDI: %016llx\n" +@@ -2473,7 +2479,7 @@ display_regs_from_elf_notes(int cpu) + len = roundup(len + note32->n_descsz, 4); + user_regs = ((char *)note32) + len - SIZE(user_regs_struct) - sizeof(long); + +- fprintf(fp, ++ fprintf(ofp, + " EAX: %08x EBX: %08x ECX: %08x EDX: %08x\n" + " ESP: %08x EIP: %08x ESI: %08x EDI: %08x\n" + " CS: %04x DS: %04x ES: %04x FS: %04x\n" +@@ -2506,7 +2512,7 @@ display_regs_from_elf_notes(int cpu) + len = roundup(len + note64->n_namesz, 4); + len = roundup(len + note64->n_descsz, 4); + // user_regs = ((char *)note64) + len - SIZE(user_regs_struct) - sizeof(long); +- fprintf(fp, "display_regs_from_elf_notes: ARM64 register dump TBD\n"); ++ fprintf(ofp, "display_regs_from_elf_notes: ARM64 register dump TBD\n"); + } + } + +@@ -2519,7 +2525,7 @@ dump_registers_for_elf_dumpfiles(void) + error(FATAL, "-r option not supported for this dumpfile\n"); + + if (NETDUMP_DUMPFILE()) { +- display_regs_from_elf_notes(0); ++ display_regs_from_elf_notes(0, fp); + return; + } + +@@ -2530,7 +2536,7 @@ dump_registers_for_elf_dumpfiles(void) + } + + fprintf(fp, "%sCPU %d:\n", c ? "\n" : "", c); +- display_regs_from_elf_notes(c); ++ display_regs_from_elf_notes(c, fp); + } + } + +@@ -2556,7 +2562,8 @@ get_netdump_regs_x86_64(struct bt_info *bt, ulong *ripp, ulong *rspp) + bt->flags |= BT_DUMPFILE_SEARCH; + + if (((NETDUMP_DUMPFILE() || KDUMP_DUMPFILE()) && +- VALID_STRUCT(user_regs_struct) && (bt->task == tt->panic_task)) || ++ VALID_STRUCT(user_regs_struct) && ++ ((bt->task == tt->panic_task) || (pc->flags2 & QEMU_MEM_DUMP_ELF))) || + (KDUMP_DUMPFILE() && (kt->flags & DWARF_UNWIND) && + (bt->flags & BT_DUMPFILE_SEARCH))) { + if (nd->num_prstatus_notes > 1) +diff --git a/task.c b/task.c +index f5bbe64..147ff5c 100644 +--- a/task.c ++++ b/task.c +@@ -483,7 +483,7 @@ task_init(void) + tt->this_task = pid_to_task(active_pid); + } + else { +- if (KDUMP_DUMPFILE() && !(pc->flags2 & QEMU_MEM_DUMP_ELF)) ++ if (KDUMP_DUMPFILE()) + map_cpus_to_prstatus(); + else if (ELF_NOTES_VALID() && DISKDUMP_DUMPFILE()) + map_cpus_to_prstatus_kdump_cmprs(); +diff --git a/x86_64.c b/x86_64.c +index bbf1326..df6c561 100644 +--- a/x86_64.c ++++ b/x86_64.c +@@ -2963,11 +2963,13 @@ x86_64_low_budget_back_trace_cmd(struct bt_info *bt_in) + diskdump_display_regs(bt->tc->processor, ofp); + else if (SADUMP_DUMPFILE()) + sadump_display_regs(bt->tc->processor, ofp); ++ else if (pc->flags2 & QEMU_MEM_DUMP_ELF) ++ display_regs_from_elf_notes(bt->tc->processor, ofp); + return; + } else if ((bt->flags & BT_KERNEL_SPACE) && + (KVMDUMP_DUMPFILE() || + (ELF_NOTES_VALID() && DISKDUMP_DUMPFILE()) || +- SADUMP_DUMPFILE())) { ++ SADUMP_DUMPFILE() || (pc->flags2 & QEMU_MEM_DUMP_ELF))) { + fprintf(ofp, " [exception RIP: "); + if ((sp = value_search(bt->instptr, &offset))) { + fprintf(ofp, "%s", sp->name); +@@ -2983,6 +2985,9 @@ x86_64_low_budget_back_trace_cmd(struct bt_info *bt_in) + diskdump_display_regs(bt->tc->processor, ofp); + else if (SADUMP_DUMPFILE()) + sadump_display_regs(bt->tc->processor, ofp); ++ else if (pc->flags2 & QEMU_MEM_DUMP_ELF) ++ display_regs_from_elf_notes(bt->tc->processor, ofp); ++ + } else if (bt->flags & BT_START) { + x86_64_print_stack_entry(bt, ofp, level, + 0, bt->instptr); +@@ -4565,7 +4570,7 @@ skip_stage: + *rip = ur_rip; + *rsp = ur_rsp; + if (is_kernel_text(ur_rip) && +- (INSTACK(ur_rsp, bt) || ++ (INSTACK(ur_rsp, bt_in) || + in_alternate_stack(bt->tc->processor, ur_rsp))) + bt_in->flags |= BT_KERNEL_SPACE; + if (!is_kernel_text(ur_rip) && in_user_stack(bt->tc->task, ur_rsp)) +@@ -4596,14 +4601,14 @@ skip_stage: + ur_rip = ULONG(user_regs + OFFSET(user_regs_struct_rip)); + ur_rsp = ULONG(user_regs + OFFSET(user_regs_struct_rsp)); + if (!in_alternate_stack(bt->tc->processor, ur_rsp) && +- !stkptr_to_task(bt->task)) { ++ !stkptr_to_task(ur_rsp)) { + if (CRASHDEBUG(1)) + error(INFO, + "x86_64_get_dumpfile_stack_frame: " + "ELF mismatch: RSP: %lx task: %lx\n", + ur_rsp, bt->task); + } else { +- if (is_kernel_text(ur_rip) && (INSTACK(ur_rsp, bt) || ++ if (is_kernel_text(ur_rip) && (INSTACK(ur_rsp, bt_in) || + in_alternate_stack(bt->tc->processor, ur_rsp))) + bt_in->flags |= BT_KERNEL_SPACE; + if (!is_kernel_text(ur_rip) && in_user_stack(bt->tc->task, ur_rsp)) + diff --git a/SPECS/crash.spec b/SPECS/crash.spec index 82c68a8..1170f8b 100644 --- a/SPECS/crash.spec +++ b/SPECS/crash.spec @@ -3,24 +3,21 @@ # Summary: Kernel analysis utility for live systems, netdump, diskdump, kdump, LKCD or mcore dumpfiles Name: crash -Version: 7.0.2 -Release: 7%{?dist}.1 +Version: 7.0.9 +Release: 4%{?dist} License: GPLv3 Group: Development/Debuggers Source: http://people.redhat.com/anderson/crash-%{version}.tar.gz URL: http://people.redhat.com/anderson ExclusiveOS: Linux -ExclusiveArch: %{ix86} ia64 x86_64 ppc ppc64 s390 s390x %{arm} aarch64 +ExclusiveArch: %{ix86} ia64 x86_64 ppc ppc64 s390 s390x %{arm} aarch64 ppc64le Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot-%(%{__id_u} -n) BuildRequires: ncurses-devel zlib-devel lzo-devel bison snappy-devel Requires: binutils Patch0: lzo_snappy.patch -Patch1: rhel7.0_beta.patch -Patch2: kmem-S-CONFIG_SLUB.patch -Patch3: S390X_NR_CPUS.patch -Patch4: backtrace_fixes.patch -Patch5: ps-performance.patch -Patch6: fix-ps-performance-on-live-system.patch +Patch1: use_QEMU_registers_for_active_task_backtraces.patch +Patch2: bt-mislabeling.patch +Patch3: ppc64_bt_active_task.patch %description The core analysis suite is a self-contained tool that can be used to @@ -42,12 +39,9 @@ offered by Mission Critical Linux, or the LKCD kernel patch. %prep %setup -n %{name}-%{version} -q %patch0 -p1 -b lzo_snappy.patch -%patch1 -p1 -b rhel7.0_beta.patch -%patch2 -p1 -b kmem-S-CONFIG_SLUB.patch -%patch3 -p1 -b S390X_NR_CPUS.patch -%patch4 -p1 -b backtrace_fixes.patch -%patch5 -p1 -b ps-performance.patch -%patch6 -p1 -b fix-ps-performance-on-live-system.patch +%patch1 -p1 -b use_QEMU_registers_for_active_task_backtraces.patch +%patch2 -p1 -b bt-mislabeling.patch +%patch3 -p1 -b ppc64_bt_active_task.patch %build make RPMPKG="%{version}-%{release}" CFLAGS="%{optflags}" @@ -76,13 +70,42 @@ rm -rf %{buildroot} %{_includedir}/* %changelog -* Tue Sep 23 2014 Dave Anderson - 7.0.2-7 -- Fix ps performance patch regression on live systems. -- Resolves: rhbz#1142139 +* Mon Jan 26 2015 Dave Anderson - 7.0.9-4 + Fix ppc64 "bt" command for active tasks in compressed kdumps. + Resolves: rhbz#1184401 + +* Mon Jan 12 2015 Dave Anderson - 7.0.9-3 + Fix "bt" command mislabeling errors. + Resolves: rhbz#1179476 + +* Mon Dec 08 2014 Dave Anderson - 7.0.9-2 +- Use registers from QEMU-generated ELF and compressed kdump headers + for active task backtraces. +- Resolves: rhbz#1169555 -* Thu Sep 18 2014 Dave Anderson - 7.0.2-7 -- Z-stream fix for "ps sub-command shows massive performance degradation" -- Resolves: rhbz#1142139 +* Fri Nov 14 2014 Dave Anderson - 7.0.9-1 +- Rebase to upstream version 7.0.9. +- Resolves: rhbz#1110513 + +* Tue Sep 23 2014 Dave Anderson - 7.0.8-2 +- Fix ps performance patch regression on live systems. +- Resolves: rhbz#1134177 +- Minor build-related fixes for ppc64le. +- Resolves: rhbz#1123991 + +* Fri Sep 12 2014 Dave Anderson - 7.0.8-1 +- Rebase to upstream version 7.0.8. +- Resolves: rhbz#1110513 +- Fix to calculate the physical base address of dumpfiles created + by a "virsh dump" of an OVMF guest. +- Resolves: rhbz#1080698 +- Support for aarch64 architecture. +- Resolves: rhbz#1110551 +- Fix to prevent crash from spinning endlessly on a corrupted/truncated + dumpfile whose bitmap data is not wholly contained within the file. +- Resolves: rhbz#1114088 +- Support for ppc64le architecture. +- Resolves: rhbz#1123991 * Tue Jan 28 2014 Daniel Mach - 7.0.2-6 - Mass rebuild 2014-01-24