[PATCH 1/3] Display local variables & function parameters

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




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

[Index of Archives]     [Fedora Development]     [Fedora Desktop]     [Fedora SELinux]     [Yosemite News]     [KDE Users]     [Fedora Tools]

 

Powered by Linux