Index: crash-4.0-8.9-build/defs.h =================================================================== --- crash-4.0-8.9-build.orig/defs.h 2009-05-24 19:25:20.000000000 +0530 +++ crash-4.0-8.9-build/defs.h 2009-05-24 19:26:37.000000000 +0530 @@ -4133,6 +4133,8 @@ ulong xen_phys_start(void); int xen_major_version(void); int xen_minor_version(void); +int get_netdump_arch(void); +void* get_regs_from_elf_notes(struct task_context *tc); /* * diskdump.c Index: crash-4.0-8.9-build/extensions/local.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ crash-4.0-8.9-build/extensions/local.c 2009-05-25 02:23:57.000000000 +0530 @@ -0,0 +1,796 @@ +/* local.c - this implements command to display local variables and arguments + * for current stack frame. + * + * Copyright (c) International Business Machines Corp., 2001 + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <fcntl.h> +#include <dwarf.h> +#include <elfutils/libdw.h> +#include "defs.h" /* From the crash source top-level directory */ +#include "local/local.h" + +/* Main Function */ +void cmd_local(); + +/* Initializations functions */ +static int initial_setup(void); /* Does the initial Dwarf setup */ +static int open_file(void); /* Returns the file descriptor for the Executable */ +static int initialize_local(); +static int initialize_register(); + +/* x86 arch specific code */ +static ulong fetch_register_x86(int reg); +static int assign_register_x86(int reg, ulong value); +static int display_registers_x86(void); + +/* ppc64 arch specific code */ +static ulong fetch_register_ppc64(int reg); +static int assign_register_ppc64(int reg, ulong value); +static int display_registers_ppc64(void); + +/* x86_64 arch specific code */ +static ulong fetch_register_x86_64(int reg); +static int assign_register_x86_64(int reg, ulong value); +static int display_registers_x86_64(void); + +/* Dwarf routines */ +static void print_function_variables(); +static void print_variables(Dwarf_Die *); +static void print_variable(Dwarf_Die *, Dwarf_Die *); +static void get_function_dies(Dwarf_Die **, int *); +static ulong translate(Dwarf_Op *, size_t , ulong *,bool *); +static Dwarf_Op * get_location(Dwarf_Attribute *, Dwarf_Addr , size_t *); +static ulong variable_address(Dwarf_Die *, Dwarf_Die *, ulong *); + +/* generic functions */ +static int str_to_option(char *str); +static void read_vmcore(ulong , size_t, void *); + +static Elf *elf_descriptor; +static Dwarf *dbg; +static int fd; +char *help_local[]; + +#define DISPLAY_ARGS 0x00000001 +#define DISPLAY_LOCALS 0x00000002 +#define STACK_UNWIND_UP 0x00000004 +#define STACK_UNWIND_DOWN 0x00000008 +#define DISPLAY_REGS 0x00000010 + +struct local_context *local = NULL; +static struct command_table_entry command_table[] = { + { "local", cmd_local, help_local, 0 }, /* One or more commands, */ + { NULL } /* terminated by NULL, */ +}; + +/* + * The _init() function is called if the shared object is loaded. + * If desired, performs initialization here. + */ +int +_init() /* Register the command set. */ +{ + register_extension(command_table); + if (initial_setup() && initialize_local()) + return 1; + else + return -1; +} + +static int +initialize_local() +{ + if(local){ + free(local->regs); + local->regs = NULL; + free(local); + local = NULL; + } + local = calloc(1, sizeof(struct local_context)); + local->tc = CURRENT_CONTEXT(); + if(KDUMP_DUMPFILE() || NETDUMP_DUMPFILE()){ + if(!initialize_register()) + return 0; + } + else{ + error(FATAL, + "Support for only KDUMP/NETDUMPs is available"); + return 0; + } + return 1; +} + +static int initialize_register() +{ + void *pt_regs; + pt_regs = get_regs_from_elf_notes(local->tc); + switch(get_netdump_arch()) + { + case EM_386: + local->regs = calloc(1, sizeof(struct pt_regs_x86)); + if(!local->regs){ + fprintf(fp, "\n Memory allocation failed"); + return 0; + } + memcpy(local->regs, pt_regs, sizeof(struct pt_regs_x86)); + local->pc = ((struct pt_regs_x86 *)local->regs)->ip; + local->fetch_register = fetch_register_x86; + local->assign_register = assign_register_x86; + local->display_registers = display_registers_x86; + break; + case EM_PPC64: + local->regs = calloc(1, sizeof(struct pt_regs_ppc64)); + if(!local->regs){ + fprintf(fp, "\n Memory allocation failed"); + return 0; + } + memcpy(local->regs, pt_regs, sizeof(struct pt_regs_ppc64)); + local->pc = ((struct pt_regs_ppc64 *)local->regs)->nip; + local->fetch_register = fetch_register_ppc64; + local->assign_register = assign_register_ppc64; + local->display_registers = display_registers_ppc64; + break; + case EM_X86_64: + local->regs = calloc(1, sizeof(struct pt_regs_x86_64)); + if(!local->regs){ + fprintf(fp, "\n Memory allocation failed"); + return 0; + } + memcpy(local->regs, pt_regs, sizeof(struct pt_regs_x86_64)); + local->pc = ((struct pt_regs_x86_64 *)local->regs)->ip; + local->fetch_register = fetch_register_x86_64; + local->assign_register = assign_register_x86_64; + local->display_registers = display_registers_x86_64; + break; + default: + error(FATAL, + "Support for ELF machine type %d not available", + get_netdump_arch()); + return 0; + } + return 1; +} + +int +static initial_setup(void) +{ + + Elf_Cmd elf_cmd = ELF_C_READ; + Dwarf_Cmd dwarf_cmd = DWARF_C_READ; + + if (elf_version(EV_CURRENT) == EV_NONE) { + error(FATAL, + "libelf.a out of date \n"); + return 0; + } + + fd = open_file(); + if (fd < 0) + return 0; + + elf_descriptor = elf_begin(fd, elf_cmd, (Elf *) 0); + + dbg = dwarf_begin_elf(elf_descriptor, dwarf_cmd, NULL); + if (!dbg) { + error(FATAL, + "Failed to get dwarf header error %s", + dwarf_errmsg(dwarf_errno())); + return 0; + } + return 1; +} + +/* + * Reads the vmlinux exe file and returns a file descriptor to calling function + */ +static int +open_file() +{ + extern struct program_context *pc; + + if (pc->namelist_debug) + fd = open(pc->namelist_debug, O_RDONLY); + else + fd = open(pc->namelist, O_RDONLY); + return fd; +} + +/* + * The _fini() function is called if the shared object is unloaded. + * If desired, performs cleanups here. + */ +int +_fini() +{ + if(local){ + if (local->regs){ + free(local->regs); + local->regs = NULL; + } + free(local); + local = NULL; + } + elf_end(elf_descriptor); + close(fd); + return 1; +} + +/* + * This function displays the local variables and argument information + * It takes input like 1. params, locals, up and down + */ +void +cmd_local() +{ + int c; + extern struct program_context *pc; + if (local->tc != CURRENT_CONTEXT()) + initialize_local(); + while ((c = getopt(argcnt, args, "")) != EOF) { + switch(c) + { + default: + argerrs++; + break; + } + } + if(argerrs) + cmd_usage(pc->curcmd,SYNOPSIS); + + while(args[optind]){ + switch(str_to_option(args[optind])) + { + case STACK_UNWIND_UP: + local->flags = STACK_UNWIND_UP; + /* Not implemented */ + break; + case STACK_UNWIND_DOWN: + local->flags = STACK_UNWIND_DOWN; + /* Not implemented */ + break; + case DISPLAY_LOCALS: + fprintf(fp, "display locals"); + local->flags = DISPLAY_LOCALS; + print_function_variables(); + break; + case DISPLAY_ARGS: + fprintf(fp, "display args"); + local->flags = DISPLAY_ARGS; + print_function_variables(); + break; + case DISPLAY_REGS: + local->flags = DISPLAY_REGS; + local->display_registers(); + break; + + default: + cmd_usage(pc->curcmd,SYNOPSIS); + } + ++optind; + } +} + +static int +str_to_option(char *str) +{ + if(STREQ(str,"params")) + return DISPLAY_ARGS; + else if(STREQ(str, "locals")) + return DISPLAY_LOCALS; + else if(STREQ(str, "up")) + return STACK_UNWIND_UP; + else if(STREQ(str,"down")) + return STACK_UNWIND_DOWN; + else if(STREQ(str,"display")) + return DISPLAY_REGS; + else + return 0; +} + +static int display_registers_x86(void) +{ + struct pt_regs_x86 *pt_regs; + pt_regs = (struct pt_regs_x86 *)local->regs; + fprintf(fp, "\n IP: \t%lx ", local->pc); + fprintf(fp, "\n ax: \t%lx ", pt_regs->ax); + fprintf(fp, "\n bx: \t%lx ", pt_regs->bx); + fprintf(fp, "\n cx: \t%lx ", pt_regs->cx); + fprintf(fp, "\n dx: \t%lx ", pt_regs->dx); + fprintf(fp, "\n sp: \t%lx ", pt_regs->sp); + fprintf(fp, "\n bp: \t%lx ", pt_regs->bp); + fprintf(fp, "\n si: \t%lx ", pt_regs->si); + fprintf(fp, "\n di: \t%lx ", pt_regs->di); + fprintf(fp, "\n cs: \t%lx ", pt_regs->cs); + fprintf(fp, "\n oirg_ax: \t%lx ", pt_regs->orig_ax); + fprintf(fp, "\n flags: \t%lx ", pt_regs->flags); + fprintf(fp, "\n ip: \t%lx ", pt_regs->ip); + fprintf(fp, "\n"); + return 0; +} + +static int display_registers_x86_64(void) +{ + struct pt_regs_x86_64 *pt_regs; + pt_regs = (struct pt_regs_x86_64 *)local->regs; + fprintf(fp, "\n IP: \t%lx ", local->pc); + fprintf(fp, "\n ax: \t%lx ", pt_regs->ax); + fprintf(fp, "\n bx: \t%lx ", pt_regs->bx); + fprintf(fp, "\n cx: \t%lx ", pt_regs->cx); + fprintf(fp, "\n dx: \t%lx ", pt_regs->dx); + fprintf(fp, "\n sp: \t%lx ", pt_regs->sp); + fprintf(fp, "\n bp: \t%lx ", pt_regs->bp); + fprintf(fp, "\n si: \t%lx ", pt_regs->si); + fprintf(fp, "\n di: \t%lx ", pt_regs->di); + fprintf(fp, "\n cs: \t%lx ", pt_regs->cs); + fprintf(fp, "\n oirg_ax: \t%lx ", pt_regs->orig_ax); + fprintf(fp, "\n flags: \t%lx ", pt_regs->flags); + fprintf(fp, "\n ip: \t%lx ", pt_regs->ip); + fprintf(fp, "\n r8: \t%lx ", pt_regs->r8); + fprintf(fp, "\n r9: \t%lx ", pt_regs->r9); + fprintf(fp, "\n r10: \t%lx ", pt_regs->r10); + fprintf(fp, "\n r11: \t%lx ", pt_regs->r11); + fprintf(fp, "\n r12: \t%lx ", pt_regs->r12); + fprintf(fp, "\n r13: \t%lx ", pt_regs->r13); + fprintf(fp, "\n"); + return 0; +} + +static int display_registers_ppc64(void) +{ + int i; + struct pt_regs_ppc64 *reg; + reg = local->regs; + for(i=0;i<32;i++) + fprintf(fp, "\n reg[%d]\t %lx", i+1,reg->gpr[i]); + return 0; +} +static void +print_function_variables() +{ + Dwarf_Die *scopes; + int nscopes; + int index; + + scopes = NULL; + get_function_dies(&scopes,&nscopes); + for(index = 0; index < nscopes; index++){ + switch(dwarf_tag(&scopes[index])){ + case DW_TAG_subprogram: + case DW_TAG_entry_point: + case DW_TAG_inlined_subroutine: + print_variables(&scopes[index]); + break; + default: + break; + } + } +} + +static void +get_function_dies(Dwarf_Die **scopes, int *nscopes) +{ + Dwarf_Die result_cu; + Dwarf_Die *cu_die; + Dwarf_Addr addr = local->pc; + + cu_die = dwarf_addrdie(dbg, addr, &result_cu); + if (!cu_die) + error(FATAL, + "\nunable to get the compiler Unit for the address: %p", addr); + *nscopes = dwarf_getscopes(cu_die, addr, scopes); + if((*nscopes) < 0) + error(FATAL, + "\nunable to get the function die at address %p", addr); +} + +static void +print_variables(Dwarf_Die *fun_die) +{ + Dwarf_Die result; + if (dwarf_child (fun_die, &result) == 0) + do{ + switch (dwarf_tag (&result)) + { + case DW_TAG_variable: + if(local->flags & DISPLAY_LOCALS) + print_variable(fun_die, &result); + break; + case DW_TAG_formal_parameter: + if(local->flags & DISPLAY_ARGS) + print_variable(fun_die, &result); + break; + default: + break; + } + }while(dwarf_siblingof(&result,&result) == 0); +} + +int var_type (Dwarf_Die *typedie, char space) +{ + int tag; + Dwarf_Attribute attr_mem; + Dwarf_Die die_mem; + Dwarf_Die *die; + const char *name; + int size = 0; + + if (typedie == NULL) + fprintf (fp,"%c<no type>", space); + else + { + name = dwarf_diename (typedie); + if (name != NULL) + fprintf (fp, "%c%c%s", space, space, name); + + die = dwarf_formref_die (dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem), &die_mem); + + tag = dwarf_tag (typedie); + name = dwarf_diename (die); + + if (name) + fprintf(fp, "\t%c%c%s\t", space, space, dwarf_diename (die)); + + switch (tag) + { + case DW_TAG_pointer_type: + size = dwarf_bytesize(die); + fputc('*', fp); + break; + case DW_TAG_array_type: + fprintf (fp, "[]"); + break; + case DW_TAG_const_type: + fprintf (fp, " const"); + break; + case DW_TAG_volatile_type: + fprintf (fp, " volatile"); + size = dwarf_bytesize(die); + break; + case DW_TAG_base_type: + break; + default: + fprintf (fp, "%c<unknown %#x>", space, tag); + break; + } + } + return size; +} + +static void +print_variable(Dwarf_Die *fun_die, Dwarf_Die *var_die) +{ + size_t size; + ulong var_addr = 0; + ulong value = 0; + int pointer_desize; + Dwarf_Attribute attr_mem; + Dwarf_Die typedie_mem; + + fprintf(fp,"\n %s\t", dwarf_diename(var_die)); + + Dwarf_Die *typedie = dwarf_formref_die (dwarf_attr_integrate (var_die, DW_AT_type, &attr_mem), &typedie_mem); + + pointer_desize = var_type (typedie, '\t'); + size = dwarf_bytesize(typedie); + var_addr = variable_address (fun_die,var_die, &value); + if (!var_addr && !value) { + fprintf(fp, "\t Dwarf information not available"); + return; + } + + if(!value && var_addr) { + if (size != ULONG_MAX) + read_vmcore(var_addr,size, &value); + else + read_vmcore(var_addr,pointer_desize, &value); + + if (pointer_desize && size != ULONG_MAX) { + char ch; + char *p = (char *)value; + short int s; + int i; + ulong l; + + fprintf(fp, "0x%lx: ", value); + switch (pointer_desize) { + case 1: /* char * */ + do { + read_vmcore((ulong)p++, 1, &ch); + fputc(ch, fp); + } while(ch!='\0'); + break; + case 2: /* short int * */ + read_vmcore(value, 2, &s); + fprintf(fp, "%d\n", s); + break; + case 8: /* long * */ + read_vmcore(value, 2, &l); + fprintf(fp, "%ld\n", l); + break; + case 4: /* int * */ + read_vmcore(value, 4, &i); + fprintf(fp, "%d\n", i); + break; + } + } else + fprintf(fp,"\tvalue:%ld",value); + + } else + fprintf(fp,"\tvalue:%ld",value); + +} + +static void +read_vmcore(ulong addr, size_t size, void *value) +{ + if (readmem(addr, KVADDR, value, size, "read_vmcore", RETURN_ON_ERROR) == FALSE) + fprintf(fp, "read_vmcore error\n"); + +} + +static ulong +variable_address(Dwarf_Die *fun_die, Dwarf_Die *var_die, ulong *value) +{ + size_t len; + Dwarf_Op *locexpr; + bool need_fb = false; + Dwarf_Attribute fb_attr, loc_attr; + Dwarf_Addr addr = local->pc; + ulong var_addr = 0; + if(!dwarf_attr_integrate(var_die, DW_AT_location, &loc_attr)) + goto out; + + locexpr = get_location(&loc_attr, addr, &len); + if (!locexpr) + goto out; + + var_addr = translate(locexpr, len, value, &need_fb); + if (need_fb) { + if(!dwarf_attr_integrate(fun_die, DW_AT_frame_base, &fb_attr)) + goto out; + locexpr = get_location(&fb_attr, addr, &len); + if (!locexpr) + goto out; + + var_addr += translate(locexpr, len, value, 0); + } + return var_addr; + out: + return 0; +} + +static ulong +translate(Dwarf_Op *locexpr, size_t len, ulong *value ,bool *need_fb) +{ + int i; + unsigned int reg; + unsigned long loc = 0; + unsigned long offset = 0; + for (i=0; i<len; i++) { + switch (locexpr[i].atom) { + case DW_OP_reg0 ... DW_OP_reg31: + reg = locexpr[i].atom - DW_OP_reg0; + goto op_reg; + case DW_OP_regx: + reg = locexpr[i].number; + op_reg: + *value = local->fetch_register(reg); + break; + case DW_OP_fbreg: + *need_fb = true; + loc = locexpr[i].number; + break; + case DW_OP_addr: + loc = locexpr[i].number; + break; + case DW_OP_breg0 ... DW_OP_breg31: + reg = locexpr[i].atom - DW_OP_breg0; + offset = locexpr[i].number; + loc = local->fetch_register(reg) + offset; + break; + case DW_OP_bregx: + reg = locexpr[i].number; + offset = locexpr[i].number2; + loc = local->fetch_register(reg) + offset; + break; + default: + error(FATAL, + "unprocessed OpCode in translate()"); + break; + } + } + return loc; +} + +static ulong +fetch_register_x86(int reg) +{ + struct pt_regs_x86 *pt_regs; + pt_regs = (struct pt_regs_x86 *)local->regs; + + switch(reg){ + case 0: return pt_regs->ax; + case 1: return pt_regs->cx; + case 2: return pt_regs->dx; + case 3: return pt_regs->bx; + case 4: return pt_regs->sp; + case 5: return pt_regs->bp; + case 6: return pt_regs->si; + case 7: return pt_regs->di; + default: + error(FATAL, + "unhandled x86 register %d", reg); + } + return 0; +} + + +static int +assign_register_x86(int reg, ulong value) +{ + struct pt_regs_x86 *pt_regs; + pt_regs = (struct pt_regs_x86 *)local->regs; + + switch(reg){ + case 0: pt_regs->ax = value;break; + case 1: pt_regs->cx = value;break; + case 2: pt_regs->dx = value;break; + case 3: pt_regs->bx = value;break; + case 4: pt_regs->sp = value;break; + case 5: pt_regs->bp = value;break; + case 6: pt_regs->si = value;break; + case 7: pt_regs->di = value;break; + default: + error(FATAL, + "unhandled x86 register %d", reg); + return 0; + } + return 1; +} + +static ulong +fetch_register_x86_64(int reg) +{ + struct pt_regs_x86_64 *pt_regs; + pt_regs = (struct pt_regs_x86_64 *)local->regs; + + switch(reg){ + case 0: return pt_regs->ax; + case 1: return pt_regs->dx; + case 2: return pt_regs->cx; + case 3: return pt_regs->bx; + case 4: return pt_regs->si; + case 5: return pt_regs->di; + case 6: return pt_regs->bp; + case 7: return pt_regs->sp; + case 8: return pt_regs->r8; + case 9: return pt_regs->r9; + case 10: return pt_regs->r10; + case 11: return pt_regs->r11; + case 12: return pt_regs->r12; + case 13: return pt_regs->r13; + case 14: return pt_regs->r14; + case 15: return pt_regs->r15; + default: + error(FATAL, + "fetch_register_x86_64: unhandled x86_64 register %d", reg); + } + return 0; +} + +static int +assign_register_x86_64(int reg, ulong value) +{ + struct pt_regs_x86_64 *pt_regs; + pt_regs = (struct pt_regs_x86_64 *)local->regs; + + switch(reg){ + case 0: pt_regs->ax = value;break; + case 1: pt_regs->dx = value;break; + case 2: pt_regs->cx = value;break; + case 3: pt_regs->bx = value;break; + case 4: pt_regs->si = value;break; + case 5: pt_regs->di = value;break; + case 6: pt_regs->bp = value;break; + case 7: pt_regs->sp = value;break; + case 8: pt_regs->r8 = value;break; + case 9: pt_regs->r9 = value;break; + case 10: pt_regs->r10 = value;break; + case 11: pt_regs->r11 = value;break; + case 12: pt_regs->r12 = value;break; + case 13: pt_regs->r13 = value;break; + case 14: pt_regs->r14 = value;break; + case 15: pt_regs->r15 = value;break; + default: + error(FATAL, + "assign_register_x86_64: unhandled x86_64 register %d", reg); + return 0; + } + return 1; +} + +static ulong +fetch_register_ppc64(int reg) +{ + struct pt_regs_ppc64 *regs; + regs = (struct pt_regs_ppc64 *)local->regs; + if (reg >= 32) + error(FATAL, "fetch_register_ppc64 unknown reg %d\n", reg); + return (ulong)regs->gpr[reg]; +} + +static int +assign_register_ppc64(int reg, ulong value ) +{ + struct pt_regs_ppc64 *regs; + regs = (struct pt_regs_ppc64 *)local->regs; + if (reg >= 32){ + error(FATAL, "assign_register_ppc64 unknown reg %d\n", reg); + return 0; + } + regs->gpr[reg] = value; + return 1; +} + +static Dwarf_Op * +get_location(Dwarf_Attribute *location, Dwarf_Addr addr, size_t *len) +{ + Dwarf_Op *expr; + switch(dwarf_getlocation_addr(location, addr, &expr,len,1)) + { + case 1: + if( *len != 0) + break; + case 0: + default: + return NULL; + } + return expr; +} + + +/* + * NAME + * local - Displays local variables + * + * SYNOPSIS + * local params locals ... + * + * DESCRIPTION + * This command displays local variables for a functions. + * + * EXAMPLE + * + * crash> local <locals|params> + * + */ + +char *help_local[] = { + "local", /* command name */ + "displays local variables in current context", /* short description */ + " This command displays local variables as well as parameters.", + "\nEXAMPLE", + " crash> local <locals|params>", + NULL +}; Index: crash-4.0-8.9-build/extensions/local.mk =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ crash-4.0-8.9-build/extensions/local.mk 2009-05-25 02:23:57.000000000 +0530 @@ -0,0 +1,14 @@ +all: local.so + +CFLAGS += -O3 -g -fPIC -Wall +ifeq ($(TARGET), PPC64) + CFLAGS += -m64 +endif + +all: local.so + +local.so: defs.h local.c local/local.h + gcc -nostartfiles -shared $(CFLAGS) -rdynamic -o $@ local.c -ldw -D$(TARGET) + +clean: + rm -rf local.o local.so Index: crash-4.0-8.9-build/netdump.c =================================================================== --- crash-4.0-8.9-build.orig/netdump.c 2009-05-24 19:25:20.000000000 +0530 +++ crash-4.0-8.9-build/netdump.c 2009-05-25 02:24:50.000000000 +0530 @@ -31,6 +31,10 @@ static void get_netdump_regs_ppc64(struct bt_info *, ulong *, ulong *); static physaddr_t xen_kdump_p2m(physaddr_t); static void check_dumpfile_size(char *); +static void* get_ppc64_regs_from_elf_notes(struct task_context *tc); +static void* get_x86_regs_from_elf_notes(struct task_context *tc); +static void* get_x86_64_regs_from_elf_notes(struct task_context *tc); + #define ELFSTORE 1 #define ELFREAD 0 @@ -567,6 +571,18 @@ return (VMCORE_VALID() ? 0 : 0); } +int get_netdump_arch(void) +{ + int e_machine; + if (nd->elf32) + e_machine = nd->elf32->e_machine; + else if(nd->elf64) + e_machine = nd->elf64->e_machine; + else + e_machine = EM_NONE; + + return e_machine; +} /* * The netdump server will eventually use the NT_TASKSTRUCT section * to pass the task address. Until such time, look at the ebp of the @@ -2250,6 +2266,116 @@ machdep->get_stack_frame(bt, eip, esp); } +void* get_regs_from_elf_notes(struct task_context *tc) +{ + switch(get_netdump_arch()) + { + case EM_386: + return get_x86_regs_from_elf_notes(tc); + case EM_PPC64: + return get_ppc64_regs_from_elf_notes(tc); + case EM_X86_64: + return get_x86_64_regs_from_elf_notes(tc); + default: + error(FATAL, + "Support for ELF machine type %d not available", + get_netdump_arch()); + return NULL; + } +} + +static void* get_x86_regs_from_elf_notes(struct task_context *tc) +{ + Elf32_Nhdr *note; + size_t len; + char *pt_regs; + ulong regs_size; + + if((tc->task == tt->panic_task) || + (is_task_active(tc->task))){ + if (nd->num_prstatus_notes > 1) + note = (Elf32_Nhdr *) + nd->nt_prstatus_percpu[tc->processor]; + else + note = (Elf64_Nhdr *)nd->nt_prstatus; + + len = sizeof(Elf32_Nhdr); + len = roundup(len + note->n_namesz, 4); + pt_regs = (void *)((char *)note + len + + MEMBER_OFFSET("elf_prstatus", "pr_reg")); + /* NEED TO BE FIXED: Hack to get the proper alignment */ + pt_regs +=4; + } + else + error(FATAL, "\n cannot determine register set for the task %s" + "bailing out\n ", tc->comm); + return pt_regs; + +} + + + +static void* get_x86_64_regs_from_elf_notes(struct task_context *tc) +{ + Elf64_Nhdr *note; + size_t len; + char *pt_regs; + ulong regs_size; + + if((tc->task == tt->panic_task) || + (is_task_active(tc->task))){ + if (nd->num_prstatus_notes > 1) + note = (Elf64_Nhdr *) + nd->nt_prstatus_percpu[tc->processor]; + else + note = (Elf64_Nhdr *)nd->nt_prstatus; + + len = sizeof(Elf64_Nhdr); + len = roundup(len + note->n_namesz, 4); + pt_regs = (void *)((char *)note + len + + MEMBER_OFFSET("elf_prstatus", "pr_reg")); + } + else + error(FATAL, "\n cannot determine register set for the task %s" + "bailing out\n ", tc->comm); + return pt_regs; + +} +static void* get_ppc64_regs_from_elf_notes(struct task_context *tc) +{ + Elf64_Nhdr *note; + size_t len; + void* pt_regs = NULL; + extern struct vmcore_data *nd; + if ((tc->task == tt->panic_task) || + (is_task_active(tc->task) && nd->num_prstatus_notes > 1)) { + /* + * Registers are saved during the dump process for the + * panic task. Whereas in kdump, regs are captured for all + * CPUs if they responded to an IPI. + */ + if (nd->num_prstatus_notes > 1) { + if (tc->processor >= nd->num_prstatus_notes) + error(FATAL, "cannot determine NT_PRSTATUS ELF note " + "for %s task: %lx\n", (tc->task == tt->panic_task) ? + "panic" : "active", tc->task); + note = (Elf64_Nhdr *) + nd->nt_prstatus_percpu[tc->processor]; + } else + note = (Elf64_Nhdr *)nd->nt_prstatus; + + len = sizeof(Elf64_Nhdr); + len = roundup(len + note->n_namesz, 4); + pt_regs = (void *)((char *)note + len + + MEMBER_OFFSET("elf_prstatus", "pr_reg")); + } + else + error(FATAL, "\n cannot determine register set for the task %s" + "bailing out\n ", tc->comm); + return pt_regs; +} + + int is_partial_netdump(void) { Index: crash-4.0-8.9-build/extensions/local/local.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ crash-4.0-8.9-build/extensions/local/local.h 2009-05-25 02:23:57.000000000 +0530 @@ -0,0 +1,89 @@ +/* local.h - this has primary declaration as used by local + * + * Copyright (c) International Business Machines Corp., 2001 + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +struct local_context { + struct task_context *tc; + void *regs; + unsigned long pc; + ulong flags; + ulong (*fetch_register)(int n); + int (*assign_register)(int n, ulong value); + int (*display_registers)(void); +}; + +struct pt_regs_ppc64 { + long gpr[32]; + long nip; + long msr; + long orig_gpr3; /* Used for restarting system calls */ + long ctr; + long link; + long xer; + long ccr; + long mq; /* 601 only (not used at present) */ + /* Used on APUS to hold IPL value. */ + long trap; /* Reason for being here */ + long dar; /* Fault registers */ + long dsisr; + long result; /* Result of a system call */ +}; + +struct pt_regs_x86 { + unsigned long bx; + unsigned long cx; + unsigned long dx; + unsigned long si; + unsigned long di; + unsigned long bp; + unsigned long ax; + unsigned long ds; + unsigned long es; + unsigned long fs; + unsigned long orig_ax; + unsigned long ip; + unsigned long cs; + unsigned long flags; + unsigned long sp; + unsigned long ss; +}; + +struct pt_regs_x86_64 { + unsigned long r15; + unsigned long r14; + unsigned long r13; + unsigned long r12; + unsigned long bp; + unsigned long bx; + unsigned long r11; + unsigned long r10; + unsigned long r9; + unsigned long r8; + unsigned long ax; + unsigned long cx; + unsigned long dx; + unsigned long si; + unsigned long di; + unsigned long orig_ax; + unsigned long ip; + unsigned long cs; + unsigned long flags; + unsigned long sp; + unsigned long ss; +};
-- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility