--- crash-5.0.0/memory.c 2010-02-17 16:24:14.000000000 -0500 +++ crash-5.0.1/memory.c 2010-01-19 11:27:26.000000000 -0500 @@ -1,8 +1,8 @@ /* memory.c - core analysis suite * * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc. - * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 David Anderson - * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Red Hat, Inc. All rights reserved. + * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 David Anderson + * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Red Hat, Inc. All rights reserved. * Copyright (C) 2002 Silicon Graphics, Inc. * * This program is free software; you can redistribute it and/or modify @@ -142,6 +142,7 @@ static int vm_area_page_dump(ulong, ulong, ulong, ulong, void *, struct reference *); static int dump_swap_info(ulong, ulong *, ulong *); +static void swap_info_init(void); static char *get_swapdev(ulong, char *); static void fill_swap_info(ulong); static char *vma_file_offset(ulong, ulong, char *); @@ -319,6 +320,8 @@ MEMBER_OFFSET_INIT(swap_info_struct_prio, "swap_info_struct", "prio"); MEMBER_OFFSET_INIT(swap_info_struct_max, "swap_info_struct", "max"); MEMBER_OFFSET_INIT(swap_info_struct_pages, "swap_info_struct", "pages"); + MEMBER_OFFSET_INIT(swap_info_struct_inuse_pages, "swap_info_struct", + "inuse_pages"); MEMBER_OFFSET_INIT(swap_info_struct_old_block_size, "swap_info_struct", "old_block_size"); MEMBER_OFFSET_INIT(block_device_bd_inode, "block_device", "bd_inode"); @@ -6697,7 +6700,7 @@ pages_to_size(totalswap_pages - totalused_pages, buf), pct); } else - error(INFO, "swap_info[%ld].swap_map at %lx is unaccessible\n", + error(INFO, "swap_info[%ld].swap_map at %lx is inaccessible\n", totalused_pages, totalswap_pages); dump_zone_page_usage(); @@ -7525,6 +7528,7 @@ int nr_node_ids; if ((THIS_KERNEL_VERSION < LINUX(2,6,22)) || + !(vt->flags & PERCPU_KMALLOC_V2_NODES) || !kernel_symbol_exists("cache_cache") || !MEMBER_EXISTS("kmem_cache", "buffer_size")) return; @@ -7541,7 +7545,6 @@ MEMBER_OFFSET("kmem_cache", "buffer_size")); if (buffer_size < SIZE(kmem_cache_s)) { - ASSIGN_SIZE(kmem_cache_s) = buffer_size; if (kernel_symbol_exists("nr_node_ids")) { get_symbol_data("nr_node_ids", sizeof(int), @@ -7551,6 +7554,14 @@ } else vt->kmem_cache_len_nodes = 1; + if (buffer_size >= (uint)(OFFSET(kmem_cache_s_lists) + + (sizeof(void *) * vt->kmem_cache_len_nodes))) + ASSIGN_SIZE(kmem_cache_s) = buffer_size; + else + error(WARNING, + "questionable cache_cache.buffer_size: %d\n", + buffer_size); + if (CRASHDEBUG(1)) { fprintf(fp, "\nkmem_cache_downsize: SIZE(kmem_cache_s): %ld " @@ -10802,6 +10813,10 @@ fprintf(fp, "%sVM_EVENT", others++ ? "|" : "");\ if (vt->flags & PGCNT_ADJ) fprintf(fp, "%sPGCNT_ADJ", others++ ? "|" : "");\ + if (vt->flags & SWAPINFO_V1) + fprintf(fp, "%sSWAPINFO_V1", others++ ? "|" : "");\ + if (vt->flags & SWAPINFO_V2) + fprintf(fp, "%sSWAPINFO_V2", others++ ? "|" : "");\ if (vt->flags & VM_INIT) fprintf(fp, "%sVM_INIT", others++ ? "|" : "");\ @@ -11530,9 +11545,9 @@ int flags, swap_device, pages, prio, usedswap; ulong swap_file, max, swap_map, pct; ulong vfsmnt; - ulong swap_info; - ushort *map; - ulong totalswap, totalused; + ulong swap_info, swap_info_ptr; + ushort *smap; + ulong inuse_pages, totalswap, totalused; char buf[BUFSIZE]; if (!symbol_exists("nr_swapfiles")) @@ -11541,6 +11556,8 @@ if (!symbol_exists("swap_info")) error(FATAL, "swap_info doesn't exist in this kernel!\n"); + swap_info_init(); + swap_info = symbol_value("swap_info"); if (swapflags & VERBOSE) @@ -11549,8 +11566,18 @@ totalswap = totalused = 0; for (i = 0; i < vt->nr_swapfiles; i++, - swap_info += SIZE(swap_info_struct)) { - fill_swap_info(swap_info); + swap_info += (vt->flags & SWAPINFO_V1 ? + SIZE(swap_info_struct) : sizeof(void *))) { + if (vt->flags & SWAPINFO_V2) { + if (!readmem(swap_info, KVADDR, &swap_info_ptr, + sizeof(void *), "swap_info pointer", + QUIET|RETURN_ON_ERROR)) + continue; + if (!swap_info_ptr) + continue; + fill_swap_info(swap_info_ptr); + } else + fill_swap_info(swap_info); flags = INT(vt->swap_info_struct + OFFSET(swap_info_struct_flags)); @@ -11570,19 +11597,33 @@ totalswap += pages; pages <<= (PAGESHIFT() - 10); + inuse_pages = 0; - prio = INT(vt->swap_info_struct + - OFFSET(swap_info_struct_prio)); + if (MEMBER_SIZE("swap_info_struct", "prio") == sizeof(short)) + prio = SHORT(vt->swap_info_struct + + OFFSET(swap_info_struct_prio)); + else + prio = INT(vt->swap_info_struct + + OFFSET(swap_info_struct_prio)); if (MEMBER_SIZE("swap_info_struct", "max") == sizeof(int)) max = UINT(vt->swap_info_struct + - OFFSET(swap_info_struct_max)); + OFFSET(swap_info_struct_max)); else - max = ULONG(vt->swap_info_struct + - OFFSET(swap_info_struct_max)); + max = ULONG(vt->swap_info_struct + + OFFSET(swap_info_struct_max)); - swap_map = ULONG(vt->swap_info_struct + - OFFSET(swap_info_struct_swap_map)); + if (VALID_MEMBER(swap_info_struct_inuse_pages)) { + if (MEMBER_SIZE("swap_info_struct", "inuse_pages") == sizeof(int)) + inuse_pages = UINT(vt->swap_info_struct + + OFFSET(swap_info_struct_inuse_pages)); + else + inuse_pages = ULONG(vt->swap_info_struct + + OFFSET(swap_info_struct_inuse_pages)); + } + + swap_map = ULONG(vt->swap_info_struct + + OFFSET(swap_info_struct_swap_map)); if (swap_file) { if (VALID_MEMBER(swap_info_struct_swap_vfsmnt)) { @@ -11600,34 +11641,40 @@ } else sprintf(buf, "(unknown)"); - map = (ushort *)GETBUF(sizeof(ushort) * max); - - if (!readmem(swap_map, KVADDR, map, - sizeof(ushort) * max, "swap_info swap_map data", - RETURN_ON_ERROR|QUIET)) { - if (swapflags & RETURN_ON_ERROR) { - *totalswap_pages = swap_map; - *totalused_pages = i; - return FALSE; - } else - error(FATAL, - "swap_info[%d].swap_map at %lx is unaccessible\n", - i, swap_map); + smap = NULL; + if (vt->flags & SWAPINFO_V1) { + smap = (ushort *)GETBUF(sizeof(ushort) * max); + + if (!readmem(swap_map, KVADDR, smap, + sizeof(ushort) * max, "swap_info swap_map data", + RETURN_ON_ERROR|QUIET)) { + if (swapflags & RETURN_ON_ERROR) { + *totalswap_pages = swap_map; + *totalused_pages = i; + FREEBUF(smap); + return FALSE; + } else + error(FATAL, + "swap_info[%d].swap_map at %lx is inaccessible\n", + i, swap_map); + } } usedswap = 0; - for (j = 0; j < max; j++) { - switch (map[j]) - { - case SWAP_MAP_BAD: - case 0: - continue; - default: - usedswap++; - } - } - - FREEBUF(map); + if (smap) { + for (j = 0; j < max; j++) { + switch (smap[j]) + { + case SWAP_MAP_BAD: + case 0: + continue; + default: + usedswap++; + } + } + FREEBUF(smap); + } else + usedswap = inuse_pages; totalused += usedswap; usedswap <<= (PAGESHIFT() - 10); @@ -11648,6 +11695,41 @@ } /* + * Determine the swap_info_struct usage. + */ +static void +swap_info_init(void) +{ + struct gnu_request *req; + + if (vt->flags & (SWAPINFO_V1|SWAPINFO_V2)) + return; + + req = (struct gnu_request *)GETBUF(sizeof(struct gnu_request)); + + if ((get_symbol_type("swap_info", NULL, req) == TYPE_CODE_ARRAY) && + ((req->target_typecode == TYPE_CODE_PTR) || + (req->target_typecode == TYPE_CODE_STRUCT))) { + switch (req->target_typecode) + { + case TYPE_CODE_STRUCT: + vt->flags |= SWAPINFO_V1; + break; + case TYPE_CODE_PTR: + vt->flags |= SWAPINFO_V2; + break; + } + } else { + if (THIS_KERNEL_VERSION >= LINUX(2,6,33)) + vt->flags |= SWAPINFO_V2; + else + vt->flags |= SWAPINFO_V1; + } + + FREEBUF(req); +} + +/* * Translate a PTE into a swap device and offset string. */ char * @@ -11675,7 +11757,7 @@ get_swapdev(ulong type, char *buf) { unsigned int i, swap_info_len; - ulong swap_info, swap_file; + ulong swap_info, swap_info_ptr, swap_file; ulong vfsmnt; if (!symbol_exists("nr_swapfiles")) @@ -11684,6 +11766,8 @@ if (!symbol_exists("swap_info")) error(FATAL, "swap_info doesn't exist in this kernel!\n"); + swap_info_init(); + swap_info = symbol_value("swap_info"); swap_info_len = (i = ARRAY_LENGTH(swap_info)) ? @@ -11694,8 +11778,25 @@ if (type >= swap_info_len) return buf; - swap_info += (SIZE(swap_info_struct) * type); - fill_swap_info(swap_info); + switch (vt->flags & (SWAPINFO_V1|SWAPINFO_V2)) + { + case SWAPINFO_V1: + swap_info += type * SIZE(swap_info_struct); + fill_swap_info(swap_info); + break; + + case SWAPINFO_V2: + swap_info += type * sizeof(void *); + if (!readmem(swap_info, KVADDR, &swap_info_ptr, + sizeof(void *), "swap_info pointer", + RETURN_ON_ERROR|QUIET)) + return buf; + if (!swap_info_ptr) + return buf; + fill_swap_info(swap_info_ptr); + break; + } + swap_file = ULONG(vt->swap_info_struct + OFFSET(swap_info_struct_swap_file)); --- crash-5.0.0/kernel.c 2010-02-17 16:24:14.000000000 -0500 +++ crash-5.0.1/kernel.c 2010-01-12 16:52:16.000000000 -0500 @@ -1,8 +1,8 @@ /* kernel.c - core analysis suite * * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc. - * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 David Anderson - * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Red Hat, Inc. All rights reserved. + * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 David Anderson + * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 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 @@ -1534,7 +1534,8 @@ if (parse_line(buf2, arglist) < 3) continue; - if ((vaddr = htol(arglist[0], RETURN_ON_ERROR, NULL)) >= spn->value) + if ((vaddr = htol(strip_ending_char(arglist[0], ':'), + RETURN_ON_ERROR, NULL)) >= spn->value) continue; if (STREQ(arglist[2], "ud2a")) { @@ -4998,10 +4999,12 @@ "irqaction flags", FAULT_ON_ERROR); fprintf(fp, " flags: %lx\n", value); - readmem(action+OFFSET(irqaction_mask), KVADDR, - &tmp1, sizeof(void *), - "irqaction mask", FAULT_ON_ERROR); - fprintf(fp, " mask: %lx\n", tmp1); + if (VALID_MEMBER(irqaction_mask)) { + readmem(action+OFFSET(irqaction_mask), KVADDR, + &tmp1, sizeof(void *), + "irqaction mask", FAULT_ON_ERROR); + fprintf(fp, " mask: %lx\n", tmp1); + } readmem(action+OFFSET(irqaction_name), KVADDR, &tmp1, sizeof(void *), --- crash-5.0.0/x86.c 2010-02-17 16:24:14.000000000 -0500 +++ crash-5.0.1/x86.c 2010-01-25 16:22:24.000000000 -0500 @@ -1,8 +1,8 @@ /* x86.c - core analysis suite * * Portions Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc. - * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 David Anderson - * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 Red Hat, Inc. All rights reserved. + * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 David Anderson + * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 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 @@ -3901,7 +3901,7 @@ count = MAX(cpucount, kt->cpus); } - return count; + return MAX(count, get_highest_cpu_online()+1); } --- crash-5.0.0/ia64.c 2010-02-17 16:24:14.000000000 -0500 +++ crash-5.0.1/ia64.c 2010-01-25 16:24:33.000000000 -0500 @@ -1,8 +1,8 @@ /* ia64.c - core analysis suite * * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc. - * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 David Anderson - * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Red Hat, Inc. All rights reserved. + * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010 David Anderson + * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010 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 @@ -2277,7 +2277,7 @@ int cpus; if ((cpus = get_cpus_online())) - return cpus; + return MAX(cpus, get_highest_cpu_online()+1); else return kt->cpus; } --- crash-5.0.0/s390.c 2010-02-17 16:24:14.000000000 -0500 +++ crash-5.0.1/s390.c 2010-02-12 14:34:22.000000000 -0500 @@ -1,9 +1,9 @@ /* s390.c - core analysis suite * * Copyright (C) 2001, 2002 Mission Critical Linux, Inc. - * Copyright (C) 2002, 2003, 2004, 2005, 2006 David Anderson - * Copyright (C) 2002, 2003, 2004, 2005, 2006 Red Hat, Inc. All rights reserved. - * Copyright (C) 2005, 2006 Michael Holzheu, IBM Corporation + * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2009, 2010 David Anderson + * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2009, 2010 Red Hat, Inc. All rights reserved. + * Copyright (C) 2005, 2006, 2010 Michael Holzheu, IBM Corporation * * 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 @@ -67,6 +67,18 @@ static struct line_number_hook s390_line_number_hooks[]; static int s390_is_uvaddr(ulong, struct task_context *); +/* + * Initialize member offsets + */ +static void s390_offsets_init(void) +{ + if (MEMBER_EXISTS("_lowcore", "st_status_fixed_logout")) + MEMBER_OFFSET_INIT(s390_lowcore_psw_save_area, "_lowcore", + "st_status_fixed_logout"); + else + MEMBER_OFFSET_INIT(s390_lowcore_psw_save_area, "_lowcore", + "psw_save_area"); +} /* * Do all necessary machine-specific setup here. This is called several @@ -132,6 +144,7 @@ machdep->hz = HZ; machdep->section_size_bits = _SECTION_SIZE_BITS; machdep->max_physmem_bits = _MAX_PHYSMEM_BITS; + s390_offsets_init(); break; case POST_INIT: @@ -529,46 +542,17 @@ } /* - * returns true, if task currently is executed by a cpu + * returns true, if task of bt currently is executed by a cpu */ static int -s390_has_cpu(unsigned long task) +s390_has_cpu(struct bt_info *bt) { - if(VALID_MEMBER(task_struct_cpus_runnable)){ - /* Linux 2.4 */ - unsigned long cpus_runnable; - readmem(task+OFFSET(task_struct_cpus_runnable),KVADDR, - &cpus_runnable,sizeof(cpus_runnable), - "cpus_runnable", FAULT_ON_ERROR); - if(cpus_runnable != ~0U) - return TRUE; - else - return FALSE; - } else { - /* Linux 2.6 */ - unsigned long runqueue_addr, runqueue_offset; - unsigned long cpu_offset, per_cpu_offset_addr, running_task; - char *runqueue; - int cpu; - - cpu = s390_cpu_of_task(task); - runqueue = GETBUF(SIZE(runqueue)); - - runqueue_offset=symbol_value("per_cpu__runqueues"); - per_cpu_offset_addr=symbol_value("__per_cpu_offset"); - readmem(per_cpu_offset_addr + cpu * sizeof(long),KVADDR, - &cpu_offset, sizeof(long),"per_cpu_offset", - FAULT_ON_ERROR); - runqueue_addr=runqueue_offset + cpu_offset; - readmem(runqueue_addr,KVADDR,runqueue,SIZE(runqueue), - "runqueue", FAULT_ON_ERROR); - running_task = ULONG(runqueue + OFFSET(runqueue_curr)); - FREEBUF(runqueue); - if(running_task == task) - return TRUE; - else - return FALSE; - } + int cpu = bt->tc->processor; + + if (is_task_active(bt->task) && (kt->cpu_flags[cpu] & ONLINE)) + return TRUE; + else + return FALSE; } /* @@ -622,7 +606,7 @@ ksp = bt->stkptr; /* print lowcore and get async stack when task has cpu */ - if(s390_has_cpu(bt->task)){ + if(s390_has_cpu(bt)){ char lowcore[LOWCORE_SIZE]; unsigned long psw_flags; int cpu = s390_cpu_of_task(bt->task); @@ -632,8 +616,7 @@ return; } s390_get_lowcore(cpu,lowcore); - psw_flags = ULONG(lowcore + MEMBER_OFFSET("_lowcore", - "st_status_fixed_logout")); + psw_flags = ULONG(lowcore + OFFSET(s390_lowcore_psw_save_area)); if(psw_flags & 0x10000UL){ fprintf(fp,"Task runs in userspace\n"); s390_print_lowcore(lowcore,bt,0); @@ -675,7 +658,7 @@ stack = bt->stackbuf; stack_base = stack_start; } else if((backchain > async_start) && (backchain < async_end) - && s390_has_cpu(bt->task)){ + && s390_has_cpu(bt)){ stack = async_stack; stack_base = async_start; } else { @@ -755,7 +738,7 @@ char* ptr; unsigned long tmp[4]; - ptr = lc + MEMBER_OFFSET("_lowcore","st_status_fixed_logout"); + ptr = lc + OFFSET(s390_lowcore_psw_save_area); tmp[0]=ULONG(ptr); tmp[1]=ULONG(ptr + S390_WORD_SIZE); @@ -891,12 +874,12 @@ int r14_offset; char lowcore[LOWCORE_SIZE]; - if(s390_has_cpu(bt->task)) + if(s390_has_cpu(bt)) s390_get_lowcore(s390_cpu_of_task(bt->task),lowcore); /* get the stack pointer */ if(esp){ - if(s390_has_cpu(bt->task)){ + if(s390_has_cpu(bt)){ ksp = ULONG(lowcore + MEMBER_OFFSET("_lowcore", "gpregs_save_area") + (15 * S390_WORD_SIZE)); } else { @@ -914,10 +897,9 @@ if(!eip) return; - if(s390_has_cpu(bt->task) && esp){ - *eip = ULONG(lowcore + MEMBER_OFFSET("_lowcore", - "st_status_fixed_logout") + S390_WORD_SIZE) - & S390_ADDR_MASK; + if(s390_has_cpu(bt) && esp){ + *eip = ULONG(lowcore + OFFSET(s390_lowcore_psw_save_area) + + S390_WORD_SIZE) & S390_ADDR_MASK; } else { if(!STRUCT_EXISTS("stack_frame")){ r14_offset = 56; @@ -1004,7 +986,7 @@ int s390_get_smp_cpus(void) { - return get_cpus_online(); + return MAX(get_cpus_online(), get_highest_cpu_online()+1); } /* --- crash-5.0.0/s390x.c 2010-02-17 16:24:14.000000000 -0500 +++ crash-5.0.1/s390x.c 2010-02-12 14:36:19.000000000 -0500 @@ -1,9 +1,9 @@ /* s390.c - core analysis suite * * Copyright (C) 2001, 2002 Mission Critical Linux, Inc. - * Copyright (C) 2002, 2003, 2004, 2005, 2006 David Anderson - * Copyright (C) 2002, 2003, 2004, 2005, 2006 Red Hat, Inc. All rights reserved. - * Copyright (C) 2005, 2006 Michael Holzheu, IBM Corporation + * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2009, 2010 David Anderson + * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2009, 2010 Red Hat, Inc. All rights reserved. + * Copyright (C) 2005, 2006, 2010 Michael Holzheu, IBM Corporation * * 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 @@ -16,6 +16,7 @@ * GNU General Public License for more details. */ #ifdef S390X +#include #include "defs.h" #define S390X_WORD_SIZE 8 @@ -41,6 +42,86 @@ #define LOWCORE_SIZE 8192 /* + * S390 CPU timer ELF note + */ +#ifndef NT_S390_TIMER +#define NT_S390_TIMER 0x301 +#endif + +/* + * S390 TOD clock comparator ELF note + */ +#ifndef NT_S390_TODCMP +#define NT_S390_TODCMP 0x302 +#endif + +/* + * S390 TOD programmable register ELF note + */ +#ifndef NT_S390_TODPREG +#define NT_S390_TODPREG 0x303 +#endif + +/* + * S390 control registers ELF note + */ +#ifndef NT_S390_CTRS +#define NT_S390_CTRS 0x304 +#endif + +/* + * S390 prefix ELF note + */ +#ifndef NT_S390_PREFIX +#define NT_S390_PREFIX 0x305 +#endif + +/* + * S390x prstatus ELF Note + */ +struct s390x_nt_prstatus { + uint8_t pad1[32]; + uint32_t pr_pid; + uint8_t pad2[76]; + uint64_t psw[2]; + uint64_t gprs[16]; + uint32_t acrs[16]; + uint64_t orig_gpr2; + uint32_t pr_fpvalid; + uint8_t pad3[4]; +} __attribute__ ((packed)); + +/* + * S390x floating point register ELF Note + */ +#ifndef NT_FPREGSET +#define NT_FPREGSET 0x2 +#endif + +struct s390x_nt_fpregset { + uint32_t fpc; + uint32_t pad; + uint64_t fprs[16]; +} __attribute__ ((packed)); + +/* + * s390x CPU info + */ +struct s390x_cpu +{ + uint64_t gprs[16]; + uint64_t ctrs[16]; + uint32_t acrs[16]; + uint64_t fprs[16]; + uint32_t fpc; + uint64_t psw[2]; + uint32_t prefix; + uint64_t timer; + uint64_t todcmp; + uint32_t todpreg; +}; + +/* * declarations of static functions */ static void s390x_print_lowcore(char*, struct bt_info*,int); @@ -65,6 +146,131 @@ static struct line_number_hook s390x_line_number_hooks[]; static int s390x_is_uvaddr(ulong, struct task_context *); + +/* + * Initialize member offsets + */ +static void s390x_offsets_init(void) +{ + if (MEMBER_EXISTS("_lowcore", "st_status_fixed_logout")) + MEMBER_OFFSET_INIT(s390_lowcore_psw_save_area, "_lowcore", + "st_status_fixed_logout"); + else + MEMBER_OFFSET_INIT(s390_lowcore_psw_save_area, "_lowcore", + "psw_save_area"); +} + +static struct s390x_cpu *s390x_cpu_vec; +static int s390x_cpu_cnt; +/* + * Return s390x CPU data for backtrace + */ +static struct s390x_cpu *s390x_cpu_get(struct bt_info *bt) +{ + unsigned int cpu = bt->tc->processor; + unsigned long lowcore_ptr, prefix; + unsigned int i; + + lowcore_ptr = symbol_value("lowcore_ptr"); + readmem(lowcore_ptr + cpu * sizeof(long), KVADDR, + &prefix, sizeof(long), "lowcore_ptr", FAULT_ON_ERROR); + for (i = 0; i < s390x_cpu_cnt; i++) { + if (s390x_cpu_vec[i].prefix == prefix) + return &s390x_cpu_vec[i]; + } + error(FATAL, "cannot determine CPU for task: %lx\n", bt->task); + return NULL; +} + +/* + * ELF core dump fuctions for storing CPU data + */ +static void s390x_elf_nt_prstatus_add(struct s390x_cpu *cpu, + struct s390x_nt_prstatus *prstatus) +{ + memcpy(&cpu->psw, &prstatus->psw, sizeof(cpu->psw)); + memcpy(&cpu->gprs, &prstatus->gprs, sizeof(cpu->gprs)); + memcpy(&cpu->acrs, &prstatus->acrs, sizeof(cpu->acrs)); +} + +static void s390x_elf_nt_fpregset_add(struct s390x_cpu *cpu, + struct s390x_nt_fpregset *fpregset) +{ + memcpy(&cpu->fpc, &fpregset->fpc, sizeof(cpu->fpc)); + memcpy(&cpu->fprs, &fpregset->fprs, sizeof(cpu->fprs)); +} + +static void s390x_elf_nt_timer_add(struct s390x_cpu *cpu, void *desc) +{ + memcpy(&cpu->timer, desc, sizeof(cpu->timer)); +} + +static void s390x_elf_nt_todcmp_add(struct s390x_cpu *cpu, void *desc) +{ + memcpy(&cpu->todcmp, desc, sizeof(cpu->todcmp)); +} + +static void s390x_elf_nt_todpreg_add(struct s390x_cpu *cpu, void *desc) +{ + memcpy(&cpu->todpreg, desc, sizeof(cpu->todpreg)); +} + +static void s390x_elf_nt_ctrs_add(struct s390x_cpu *cpu, void *desc) +{ + memcpy(&cpu->ctrs, desc, sizeof(cpu->ctrs)); +} + +static void s390x_elf_nt_prefix_add(struct s390x_cpu *cpu, void *desc) +{ + memcpy(&cpu->prefix, desc, sizeof(cpu->prefix)); +} + +static void *get_elf_note_desc(Elf64_Nhdr *note) +{ + void *ptr = note; + + return ptr + roundup(sizeof(*note) + note->n_namesz, 4); +} + +static void s390x_elf_note_add(int elf_cpu_nr, void *note_ptr) +{ + Elf64_Nhdr *note = note_ptr; + struct s390x_cpu *cpu; + void *desc; + + desc = get_elf_note_desc(note); + if (elf_cpu_nr != s390x_cpu_cnt) { + s390x_cpu_cnt++; + s390x_cpu_vec = realloc(s390x_cpu_vec, + s390x_cpu_cnt * sizeof(*s390x_cpu_vec)); + if (!s390x_cpu_vec) + error(FATAL, "cannot malloc cpu space."); + } + cpu = &s390x_cpu_vec[s390x_cpu_cnt - 1]; + switch (note->n_type) { + case NT_PRSTATUS: + s390x_elf_nt_prstatus_add(cpu, desc); + break; + case NT_FPREGSET: + s390x_elf_nt_fpregset_add(cpu, desc); + break; + case NT_S390_TIMER: + s390x_elf_nt_timer_add(cpu, desc); + break; + case NT_S390_TODCMP: + s390x_elf_nt_todcmp_add(cpu, desc); + break; + case NT_S390_TODPREG: + s390x_elf_nt_todpreg_add(cpu, desc); + break; + case NT_S390_CTRS: + s390x_elf_nt_ctrs_add(cpu, desc); + break; + case NT_S390_PREFIX: + s390x_elf_nt_prefix_add(cpu, desc); + break; + } +} /* * Do all necessary machine-specific setup here. This is called several @@ -75,6 +281,9 @@ { switch (when) { + case SETUP_ENV: + machdep->dumpfile_init = s390x_elf_note_add; + break; case PRE_SYMTAB: machdep->verify_symbol = s390x_verify_symbol; if (pc->flags & KERNEL_DEBUG_QUERY) @@ -130,6 +339,7 @@ machdep->hz = HZ; machdep->section_size_bits = _SECTION_SIZE_BITS; machdep->max_physmem_bits = _MAX_PHYSMEM_BITS; + s390x_offsets_init(); break; case POST_INIT: @@ -188,6 +398,7 @@ fprintf(fp, " verify_paddr: generic_verify_paddr()\n"); fprintf(fp, " init_kernel_pgd: NULL\n"); fprintf(fp, " value_to_symbol: generic_machdep_value_to_symbol()\n"); + fprintf(fp, " dumpfile_init: s390x_elf_note_add()\n"); fprintf(fp, " line_number_hooks: s390x_line_number_hooks\n"); fprintf(fp, " last_pgd_read: %lx\n", machdep->last_pgd_read); fprintf(fp, " last_pmd_read: %lx\n", machdep->last_pmd_read); @@ -511,6 +722,7 @@ "Option '-e' is not implemented for this architecture\n")); } +#ifdef DEPRECATED /* * returns cpu number of task */ @@ -537,63 +749,57 @@ } return cpu; } +#endif /* - * returns true, if task currently is executed by a cpu + * returns true, if task of bt currently is executed by a cpu */ static int -s390x_has_cpu(unsigned long task) +s390x_has_cpu(struct bt_info *bt) { - if(VALID_MEMBER(task_struct_cpus_runnable)){ - /* Linux 2.4 */ - unsigned long cpus_runnable; - readmem(task+OFFSET(task_struct_cpus_runnable),KVADDR, - &cpus_runnable,sizeof(cpus_runnable), - "cpus_runnable", FAULT_ON_ERROR); - if(cpus_runnable != ~0ULL) - return TRUE; - else - return FALSE; - } else { - /* Linux 2.6 */ - unsigned long runqueue_addr, runqueue_offset; - unsigned long cpu_offset, per_cpu_offset_addr, running_task; - char *runqueue; - int cpu; - - cpu = s390x_cpu_of_task(task); - runqueue = GETBUF(SIZE(runqueue)); - - runqueue_offset=symbol_value("per_cpu__runqueues"); - per_cpu_offset_addr=symbol_value("__per_cpu_offset"); - readmem(per_cpu_offset_addr + cpu * sizeof(long),KVADDR, - &cpu_offset, sizeof(long),"per_cpu_offset", - FAULT_ON_ERROR); - runqueue_addr=runqueue_offset + cpu_offset; - readmem(runqueue_addr,KVADDR,runqueue,SIZE(runqueue), - "runqueue", FAULT_ON_ERROR); - running_task = ULONG(runqueue + OFFSET(runqueue_curr)); - FREEBUF(runqueue); - if(running_task == task) - return TRUE; - else - return FALSE; - } + int cpu = bt->tc->processor; + + if (is_task_active(bt->task) && (kt->cpu_flags[cpu] & ONLINE)) + return TRUE; + else + return FALSE; } /* * read lowcore for cpu */ static void -s390x_get_lowcore(int cpu, char* lowcore) +s390x_get_lowcore(struct bt_info *bt, char* lowcore) { unsigned long lowcore_array,lowcore_ptr; + struct s390x_cpu *s390x_cpu; + int cpu = bt->tc->processor; lowcore_array = symbol_value("lowcore_ptr"); readmem(lowcore_array + cpu * S390X_WORD_SIZE,KVADDR, &lowcore_ptr, sizeof(long), "lowcore_ptr", FAULT_ON_ERROR); readmem(lowcore_ptr, KVADDR, lowcore, LOWCORE_SIZE, "lowcore", FAULT_ON_ERROR); + + if (!s390x_cpu_vec) + return; + + /* Copy register information to defined places in lowcore */ + s390x_cpu = s390x_cpu_get(bt); + + memcpy(lowcore + 4864, &s390x_cpu->psw, sizeof(s390x_cpu->psw)); + memcpy(lowcore + 4736, &s390x_cpu->gprs, sizeof(s390x_cpu->gprs)); + memcpy(lowcore + 4928, &s390x_cpu->acrs, sizeof(s390x_cpu->acrs)); + + memcpy(lowcore + 4892, &s390x_cpu->fpc, sizeof(s390x_cpu->fpc)); + memcpy(lowcore + 4608, &s390x_cpu->fprs, sizeof(s390x_cpu->fprs)); + + memcpy(lowcore + 4888, &s390x_cpu->prefix, sizeof(s390x_cpu->prefix)); + memcpy(lowcore + 4992, &s390x_cpu->ctrs, sizeof(s390x_cpu->ctrs)); + + memcpy(lowcore + 4900, &s390x_cpu->todpreg, sizeof(s390x_cpu->todpreg)); + memcpy(lowcore + 4904, &s390x_cpu->timer, sizeof(s390x_cpu->timer)); + memcpy(lowcore + 4912, &s390x_cpu->todcmp, sizeof(s390x_cpu->todcmp)); } /* @@ -632,18 +838,17 @@ ksp = bt->stkptr; /* print lowcore and get async stack when task has cpu */ - if(s390x_has_cpu(bt->task)){ + if(s390x_has_cpu(bt)){ char lowcore[LOWCORE_SIZE]; unsigned long psw_flags; - int cpu = s390x_cpu_of_task(bt->task); if (ACTIVE()) { fprintf(fp,"(active)\n"); return; } - s390x_get_lowcore(cpu,lowcore); - psw_flags = ULONG(lowcore + MEMBER_OFFSET("_lowcore", - "st_status_fixed_logout")); + s390x_get_lowcore(bt, lowcore); + psw_flags = ULONG(lowcore + OFFSET(s390_lowcore_psw_save_area)); + if(psw_flags & 0x1000000000000ULL){ fprintf(fp,"Task runs in userspace\n"); s390x_print_lowcore(lowcore,bt,0); @@ -685,7 +890,7 @@ stack = bt->stackbuf; stack_base = stack_start; } else if((backchain > async_start) && (backchain < async_end) - && s390x_has_cpu(bt->task)){ + && s390x_has_cpu(bt)){ stack = async_stack; stack_base = async_start; } else { @@ -766,7 +971,7 @@ char* ptr; unsigned long tmp[4]; - ptr = lc + MEMBER_OFFSET("_lowcore","st_status_fixed_logout"); + ptr = lc + OFFSET(s390_lowcore_psw_save_area); tmp[0]=ULONG(ptr); tmp[1]=ULONG(ptr + S390X_WORD_SIZE); @@ -921,12 +1126,12 @@ int r14_offset; char lowcore[LOWCORE_SIZE]; - if(s390x_has_cpu(bt->task)) - s390x_get_lowcore(s390x_cpu_of_task(bt->task),lowcore); + if(s390x_has_cpu(bt)) + s390x_get_lowcore(bt, lowcore); /* get the stack pointer */ if(esp){ - if(s390x_has_cpu(bt->task)){ + if(s390x_has_cpu(bt)){ ksp = ULONG(lowcore + MEMBER_OFFSET("_lowcore", "gpregs_save_area") + (15 * S390X_WORD_SIZE)); } else { @@ -944,9 +1149,9 @@ if(!eip) return; - if(s390x_has_cpu(bt->task) && esp){ - *eip = ULONG(lowcore + MEMBER_OFFSET("_lowcore", - "st_status_fixed_logout") + S390X_WORD_SIZE); + if(s390x_has_cpu(bt) && esp){ + *eip = ULONG(lowcore + OFFSET(s390_lowcore_psw_save_area) + + S390X_WORD_SIZE); } else { if(!STRUCT_EXISTS("stack_frame")){ r14_offset = 112; @@ -1033,7 +1238,7 @@ int s390x_get_smp_cpus(void) { - return get_cpus_online(); + return MAX(get_cpus_online(), get_highest_cpu_online()+1); } /* --- crash-5.0.0/x86_64.c 2010-02-17 16:24:14.000000000 -0500 +++ crash-5.0.1/x86_64.c 2010-01-19 15:28:46.000000000 -0500 @@ -1,7 +1,7 @@ /* x86_64.c -- core analysis suite * - * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 David Anderson - * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Red Hat, Inc. All rights reserved. + * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 David Anderson + * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 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 @@ -794,15 +794,36 @@ int i, cpus, cpunumber; struct machine_specific *ms; - if (!(kt->flags & PER_CPU_OFF)) + ms = machdep->machspec; + + if (!(kt->flags & PER_CPU_OFF)) { + /* + * Presume kernel is !CONFIG_SMP. + */ + if (symbol_exists("per_cpu__irq_stack_union")) { + ms->stkinfo.ibase[0] = + symbol_value("per_cpu__irq_stack_union"); + if ((ms->stkinfo.isize = + MEMBER_SIZE("irq_stack_union", "irq_stack")) <= 0) + ms->stkinfo.isize = 16384; + } + if (DUMPFILE() && symbol_exists("per_cpu__current_task")) { + if (!(ms->current = calloc(kt->cpus, sizeof(ulong)))) + error(FATAL, + "cannot calloc" + " %d x86_64 current pointers!\n", + kt->cpus); + get_symbol_data("per_cpu__current_task", sizeof(ulong), + &ms->current[0]); + } + return; + } if (!symbol_exists("per_cpu__cpu_number") || !symbol_exists("per_cpu__irq_stack_union")) return; - ms = machdep->machspec; - for (i = cpus = 0; i < NR_CPUS; i++) { if (!readmem(symbol_value("per_cpu__cpu_number") + kt->__per_cpu_offset[i], --- crash-5.0.0/symbols.c 2010-02-17 16:24:14.000000000 -0500 +++ crash-5.0.1/symbols.c 2010-02-05 10:28:14.000000000 -0500 @@ -1,8 +1,8 @@ /* symbols.c - core analysis suite * * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc. - * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 David Anderson - * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Red Hat, Inc. All rights reserved. + * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 David Anderson + * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 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 @@ -1762,9 +1762,25 @@ nksyms = UINT(modbuf + OFFSET(module_num_symtab)); else nksyms = ULONG(modbuf + OFFSET(module_num_symtab)); + ksymtab = ULONG(modbuf + OFFSET(module_symtab)); + if (!IN_MODULE(ksymtab, lm)) { + error(WARNING, + "%s: module.symtab outside of module address space\n", + lm->mod_name); + FREEBUF(module_buf); + return 0; + } locsymtab = module_buf + (ksymtab - lm->mod_base); + kstrtab = ULONG(modbuf + OFFSET(module_strtab)); + if (!IN_MODULE(kstrtab, lm)) { + error(WARNING, + "%s: module.strtab outside of module address space\n", + lm->mod_name); + FREEBUF(module_buf); + return 0; + } locstrtab = module_buf + (kstrtab - lm->mod_base); for (i = 1; i < nksyms; i++) { /* ELF starts real symbols at 1 */ @@ -5247,7 +5263,7 @@ if (((kt->flags & (SMP|PER_CPU_OFF)) != (SMP|PER_CPU_OFF)) || (sp->value < symbol_value("__per_cpu_start")) || (sp->value >= symbol_value("__per_cpu_end")) || - !((sp->type == 'd') || (sp->type == 'D'))) + !((sp->type == 'd') || (sp->type == 'D') || (sp->type == 'V'))) return FALSE; fprintf(fp, "PER-CPU DATA TYPE:\n "); @@ -5403,7 +5419,7 @@ else sprintf(buf, "output *(struct %s *)0x%lx", s, addr); fprintf(fp, "struct %s ", s); - gdb_pass_through(buf, NULL, 0); + gdb_pass_through(buf, NULL, GNU_RETURN_ON_ERROR); fprintf(fp, "\n"); } @@ -5421,7 +5437,7 @@ else sprintf(buf, "output *(union %s *)0x%lx", s, addr); fprintf(fp, "union %s ", s); - gdb_pass_through(buf, NULL, 0); + gdb_pass_through(buf, NULL, GNU_RETURN_ON_ERROR); } /* @@ -6541,6 +6557,8 @@ OFFSET(swap_info_struct_max)); fprintf(fp, " swap_info_struct_pages: %ld\n", OFFSET(swap_info_struct_pages)); + fprintf(fp, " swap_info_struct_inuse_pages: %ld\n", + OFFSET(swap_info_struct_inuse_pages)); fprintf(fp, "swap_info_struct_old_block_size: %ld\n", OFFSET(swap_info_struct_old_block_size)); fprintf(fp, " block_device_bd_inode: %ld\n", @@ -7303,6 +7321,8 @@ OFFSET(pcpu_info_idle)); fprintf(fp, " vcpu_struct_rq: %ld\n", OFFSET(vcpu_struct_rq)); + fprintf(fp, " s390_lowcore_psw_save_area: %ld\n", + OFFSET(s390_lowcore_psw_save_area)); fprintf(fp, "\n size_table:\n"); fprintf(fp, " page: %ld\n", SIZE(page)); --- crash-5.0.0/netdump.c 2010-02-17 16:24:14.000000000 -0500 +++ crash-5.0.1/netdump.c 2010-02-12 14:23:52.000000000 -0500 @@ -213,6 +213,11 @@ goto bailout; break; + case EM_S390: + if (machine_type_mismatch(file, "S390X", NULL, + source_query)) + goto bailout; + break; case EM_386: if (machine_type_mismatch(file, "X86", NULL, source_query)) @@ -1990,6 +1995,9 @@ break; } + if (store && machine_type("S390X")) + machdep->dumpfile_init(nd->num_prstatus_notes, note); + uptr = (ulonglong *)(ptr + note->n_namesz); /* @@ -2082,6 +2090,9 @@ return get_netdump_regs_x86_64(bt, eip, esp); break; + case EM_S390: + machdep->get_stack_frame(bt, eip, esp); + break; default: error(FATAL, "support for ELF machine type %d not available\n", --- crash-5.0.0/xendump.c 2010-02-17 16:24:14.000000000 -0500 +++ crash-5.0.1/xendump.c 2010-02-04 15:04:52.000000000 -0500 @@ -123,8 +123,12 @@ clean_exit(1); } - BCOPY(xcp, &xd->xc_core.header, - sizeof(struct xc_core_header)); + xd->xc_core.header.xch_magic = xcp->xch_magic; + xd->xc_core.header.xch_nr_vcpus = xcp->xch_nr_vcpus; + xd->xc_core.header.xch_nr_pages = xcp->xch_nr_pages; + xd->xc_core.header.xch_ctxt_offset = (ulong)xcp->xch_ctxt_offset; + xd->xc_core.header.xch_index_offset = (ulong)xcp->xch_index_offset; + xd->xc_core.header.xch_pages_offset = (ulong)xcp->xch_pages_offset; xd->flags |= (XENDUMP_LOCAL | XC_CORE_ORIG | XC_CORE_P2M_CREATE); @@ -1036,13 +1040,13 @@ fprintf(fp, " xch_nr_pages: %d (0x%x)\n", xd->xc_core.header.xch_nr_pages, xd->xc_core.header.xch_nr_pages); - fprintf(fp, " xch_ctxt_offset: %d (0x%x)\n", + fprintf(fp, " xch_ctxt_offset: %ld (0x%lx)\n", xd->xc_core.header.xch_ctxt_offset, xd->xc_core.header.xch_ctxt_offset); - fprintf(fp, " xch_index_offset: %d (0x%x)\n", + fprintf(fp, " xch_index_offset: %ld (0x%lx)\n", xd->xc_core.header.xch_index_offset, xd->xc_core.header.xch_index_offset); - fprintf(fp, " xch_pages_offset: %d (0x%x)\n", + fprintf(fp, " xch_pages_offset: %ld (0x%lx)\n", xd->xc_core.header.xch_pages_offset, xd->xc_core.header.xch_pages_offset); @@ -2538,7 +2542,7 @@ if (STREQ(name, ".xen_prstatus")) xd->xc_core.header.xch_ctxt_offset = - (unsigned int)shdr.sh_offset; + (unsigned long)shdr.sh_offset; if (STREQ(name, ".xen_shared_info")) xd->xc_core.shared_info_offset = (off_t)shdr.sh_offset; @@ -2555,7 +2559,7 @@ if (STREQ(name, ".xen_pages")) xd->xc_core.header.xch_pages_offset = - (unsigned int)shdr.sh_offset; + (unsigned long)shdr.sh_offset; if (STREQ(name, ".xen_ia64_mapped_regs")) xd->xc_core.ia64_mapped_regs_offset = @@ -2638,7 +2642,7 @@ if (STREQ(name, ".xen_prstatus")) xd->xc_core.header.xch_ctxt_offset = - (unsigned int)shdr.sh_offset; + (unsigned long)shdr.sh_offset; if (STREQ(name, ".xen_shared_info")) xd->xc_core.shared_info_offset = (off_t)shdr.sh_offset; @@ -2655,7 +2659,7 @@ if (STREQ(name, ".xen_pages")) xd->xc_core.header.xch_pages_offset = - (unsigned int)shdr.sh_offset; + (unsigned long)shdr.sh_offset; if (STREQ(name, ".xen_ia64_mapped_regs")) xd->xc_core.ia64_mapped_regs_offset = --- crash-5.0.0/unwind.c 2010-02-17 16:24:14.000000000 -0500 +++ crash-5.0.1/unwind.c 2010-01-20 11:59:04.000000000 -0500 @@ -2081,10 +2081,11 @@ unw_switch_from_osinit_v3(struct unw_frame_info *info, struct bt_info *bt, char *type) { - unsigned long pt, sw, pid; + unsigned long pt, sw, sos, pid; char *p, *q; struct task_context *tc = NULL; struct bt_info clone_bt; + unsigned long kr_current, offset_kr; /* * The structure of INIT/MCA stack @@ -2107,6 +2108,7 @@ */ pt = ALIGN16(bt->task + IA64_STK_OFFSET - STRUCT_SIZE("pt_regs")); sw = ALIGN16(pt - STRUCT_SIZE("switch_stack")); + sos = ALIGN16(sw - STRUCT_SIZE("ia64_sal_os_state")); /* * 1. Try to find interrupted task from comm @@ -2122,6 +2124,51 @@ if (!bt->tc || !bt->tc->comm) goto find_exframe; + /* + * If comm is "INIT" or "MCA", it means original stack is not modified. + */ + if (STREQ(bt->tc->comm, type)) { + /* Get pid using ia64_sal_os_state */ + pid = 0; + offset_kr = MEMBER_OFFSET("ia64_sal_os_state", + "prev_IA64_KR_CURRENT"); + readmem(sos + offset_kr, KVADDR, &kr_current, sizeof(ulong), + "ia64_sal_os_state prev_IA64_KR_CURRENT", + FAULT_ON_ERROR); + readmem(kr_current + OFFSET(task_struct_pid), KVADDR, &pid, + sizeof(pid_t), "task_struct pid", FAULT_ON_ERROR); + + if (pid) + tc = pid_to_context(pid); + else { + tc = pid_to_context(0); + while (tc) { + if (tc != bt->tc && + tc->processor == bt->tc->processor) + break; + tc = tc->tc_next; + } + } + + if (tc) { + /* Clone bt_info and do backtrace */ + clone_bt_info(bt, &clone_bt, tc); + if (!BT_REFERENCE_CHECK(&clone_bt)) { + fprintf(fp, "(%s) INTERRUPTED TASK\n", type); + print_task_header(fp, tc, 0); + } + if (!user_mode(bt, pt)) + goto find_exframe; + else if (!BT_REFERENCE_CHECK(bt)) { + fprintf(fp, " #0 [interrupted in user space]\n"); + /* at least show the incomplete exception frame */ + bt->flags |= BT_INCOMPLETE_USER_EFRAME; + ia64_exception_frame(pt, bt); + } + } + return FALSE; + } + if ((p = strstr(bt->tc->comm, type))) { p += strlen(type); if (*p != ' ') --- crash-5.0.0/defs.h 2010-02-17 16:24:14.000000000 -0500 +++ crash-5.0.1/defs.h 2010-02-12 14:18:52.000000000 -0500 @@ -1,8 +1,8 @@ /* defs.h - core analysis suite * * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc. - * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 David Anderson - * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Red Hat, Inc. All rights reserved. + * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 David Anderson + * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Red Hat, Inc. All rights reserved. * Copyright (C) 2002 Silicon Graphics, Inc. * * This program is free software; you can redistribute it and/or modify @@ -792,6 +792,7 @@ void (*clear_machdep_cache)(void); int (*xen_kdump_p2m_create)(struct xen_kdump_data *); int (*in_alternate_stack)(int, ulong); + void (*dumpfile_init)(int, void *); }; /* @@ -1494,6 +1495,8 @@ long attribute_owner; long module_sect_attr_attr; long module_sections_attrs; + long swap_info_struct_inuse_pages; + long s390_lowcore_psw_save_area; }; struct size_table { /* stash of commonly-used sizes */ @@ -1791,6 +1794,8 @@ #define VM_EVENT (0x40000) #define PGCNT_ADJ (0x80000) #define VM_INIT (0x100000) +#define SWAPINFO_V1 (0x200000) +#define SWAPINFO_V2 (0x400000) #define IS_FLATMEM() (vt->flags & FLATMEM) #define IS_DISCONTIGMEM() (vt->flags & DISCONTIGMEM) --- crash-5.0.0/xendump.h 2010-02-17 16:24:14.000000000 -0500 +++ crash-5.0.1/xendump.h 2010-02-04 15:10:39.000000000 -0500 @@ -33,6 +33,20 @@ unsigned int xch_pages_offset; } xc_core_header_t; +/* + * Based upon the original xensource xc_core_header struct above, + * but with unsigned long offset values so that it can be used + * with the original dumpfile format and new ELF-style format. + */ +struct xen_core_header { + unsigned int xch_magic; + unsigned int xch_nr_vcpus; + unsigned int xch_nr_pages; + unsigned long xch_ctxt_offset; + unsigned long xch_index_offset; + unsigned long xch_pages_offset; +}; + struct pfn_offset_cache { off_t file_offset; ulong pfn; @@ -70,7 +84,7 @@ struct xc_core_data { int p2m_frames; ulong *p2m_frame_index_list; - struct xc_core_header header; + struct xen_core_header header; int elf_class; uint64_t format_version; off_t elf_strtab_offset; --- crash-5.0.0/unwind_x86_64.h 2010-02-17 16:24:14.000000000 -0500 +++ crash-5.0.1/unwind_x86_64.h 2010-01-26 10:03:44.000000000 -0500 @@ -61,7 +61,7 @@ #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) #define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)])) -#define BUILD_BUG_ON_ZERO(e) (sizeof(char[1 - 2 * !!(e)]) - 1) +#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); })) #define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f)) #define get_unaligned(ptr) (*(ptr)) //#define __get_user(x,ptr) __get_user_nocheck((x),(ptr),sizeof(*(ptr))) --- crash-5.0.0/gdb-7.0.patch 2010-02-17 16:24:14.000000000 -0500 +++ crash-5.0.1/gdb-7.0.patch 2010-02-08 16:04:55.000000000 -0500 @@ -435,7 +435,7 @@ { +#ifdef CRASH_MERGE + extern int gdb_readmem_callback(unsigned long, void *, int, int); -+ if (gdb_readmem_callback(memaddr, myaddr, len, 1)) ++ if (gdb_readmem_callback(memaddr, (void *)myaddr, len, 1)) + return 0; + else + return EIO; @@ -1133,6 +1133,15 @@ $(TUI)$(EXEEXT): tui-main.o libgdb.a $(ADD_DEPS) $(CDEPS) $(TDEPLIBS) rm -f $(TUI)$(EXEEXT) +@@ -1137,7 +1138,7 @@ $(TUI)$(EXEEXT): tui-main.o libgdb.a $(A + # Convenience rule to handle recursion. + $(LIBGNU) $(GNULIB_H): all-lib + all-lib: gnulib/Makefile +- @$(MAKE) $(FLAGS_TO_PASS) DO=all DODIRS=gnulib subdir_do ++ @$(MAKE) $(FLAGS_TO_PASS) DO=all DODIRS=gnulib subdir_do -s + .PHONY: all-lib + + # Create a library of the gdb object files and build GDB by linking @@ -1346,12 +1347,12 @@ $(srcdir)/copying.c: @MAINTAINER_MODE_TR mv $(srcdir)/copying.tmp $(srcdir)/copying.c @@ -1240,3 +1249,41 @@ LDFLAGS = @LDFLAGS@ LIBCFLAGS = $(CFLAGS) CXXFLAGS = @CXXFLAGS@ +--- gdb-7.0/libiberty/Makefile.in.orig ++++ gdb-7.0/libiberty/Makefile.in +@@ -167,7 +167,7 @@ REQUIRED_OFILES = \ + ./getopt.o ./getopt1.o ./getpwd.o ./getruntime.o \ + ./hashtab.o ./hex.o \ + ./lbasename.o ./lrealpath.o \ +- ./make-relative-prefix.o ./make-temp-file.o \ ++ ./make-relative-prefix.o ./make-temp-file.o ./mkstemps.o \ + ./objalloc.o ./obstack.o \ + ./partition.o ./pexecute.o ./physmem.o \ + ./pex-common.o ./pex-one.o @pexecute@ \ +@@ -188,7 +188,7 @@ CONFIGURED_OFILES = ./asprintf.o ./atexi + ./getcwd.o ./getpagesize.o ./gettimeofday.o \ + ./index.o ./insque.o \ + ./memchr.o ./memcmp.o ./memcpy.o ./memmem.o ./memmove.o \ +- ./mempcpy.o ./memset.o ./mkstemps.o \ ++ ./mempcpy.o ./memset.o \ + ./pex-djgpp.o ./pex-msdos.o \ + ./pex-unix.o ./pex-win32.o \ + ./putenv.o \ +--- gdb-7.0/gdb/symtab.c.orig ++++ gdb-7.0/gdb/symtab.c +@@ -867,6 +867,7 @@ find_pc_sect_psymtab (CORE_ADDR pc, stru + /* Try just the PSYMTABS_ADDRMAP mapping first as it has better granularity + than the later used TEXTLOW/TEXTHIGH one. */ + ++#ifndef __i386__ + ALL_OBJFILES (objfile) + if (objfile->psymtabs_addrmap != NULL) + { +@@ -901,6 +902,7 @@ find_pc_sect_psymtab (CORE_ADDR pc, stru + return pst; + } + } ++#endif + + /* Existing PSYMTABS_ADDRMAP mapping is present even for PARTIAL_SYMTABs + which still have no corresponding full SYMTABs read. But it is not