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