--- crash-4.0-3.8/symbols.c	2006-10-20 21:46:27.000000000 +0200
+++ crash-4.0-3.8-patch/symbols.c	2006-10-22 21:41:10.000000000 +0200
@@ -61,6 +61,7 @@
 struct elf_common;
 static void Elf32_Sym_to_common(Elf32_Sym *, struct elf_common *); 
 static void Elf64_Sym_to_common(Elf64_Sym *, struct elf_common *); 
+static void do_pointer(ulong);
 
 
 #define KERNEL_SECTIONS  (void *)(1)
@@ -3951,22 +3952,55 @@
 void
 cmd_struct(void)
 {
+	do_pointer(STRUCT_REQUEST);
+}
+/*
+ * This command displays either a union definition, or a formatted display
+ * of the contents of a union at a specified address.  If no address is
+ * specified, the union size and the file in which the union is defined
+ * are also displayed.  A union member may be appended to the union
+ * name (in a "union.member" format) in order to limit the scope of the data 
+ * displayed to that particular member.  Structure data is shown in hexadecimal
+ * format.  The raw data in a union may be dumped with the -r flag.
+ */
+void
+cmd_union(void)
+{
+	do_pointer(UNION_REQUEST);
+}
+
+/*
+ *  After determining what type of data type follows the *, this routine
+ *  has the identical functionality as cmd_struct() or cmd_union().
+ */
+void
+cmd_pointer(void)
+{
+	do_pointer(0);
+}
+static void 
+do_pointer(ulong flags)
+{
 	int c;
 	ulong addr, aflag;
 	struct syment *sp;
 	int rawdata;
 	long len;
-	ulong flags;
 	ulong list_head_offset;
 	int count;
-        struct datatype_member struct_member, *sm;
+        struct datatype_member datatype_member, *dm;
 
-        sm = &struct_member;
+        dm = &datatype_member;
 	count = 1;
 	rawdata = 0;
 	aflag = 0;
-	list_head_offset = 0;
-	flags = STRUCT_REQUEST;
+        list_head_offset=0;
+
+        int i, argc_members=0, optind_save;
+        char *p1, *p2;
+        char *structname, *members;
+        char *arglist[MAXARGS];
+
 
         while ((c = getopt(argcnt, args, "c:rvol:")) != EOF) {
                 switch(c)
@@ -3986,16 +4020,14 @@
 		case 'o':
 			flags |= SHOW_OFFSET;
 			break;
-
 		case 'l':
                         if (IS_A_NUMBER(optarg))
                                 list_head_offset = stol(optarg,
                                         FAULT_ON_ERROR, NULL);
                         else if (arg_to_datatype(optarg,
-                                sm, RETURN_ON_ERROR) > 1)
-                                list_head_offset = sm->member_offset;
+                                dm, RETURN_ON_ERROR) > 1)
+                                list_head_offset = dm->member_offset;
 			break;
-
 		default:
 			argerrs++;
 			break;
@@ -4005,21 +4037,18 @@
 	if (argerrs || !args[optind])
 		cmd_usage(pc->curcmd, SYNOPSIS);
 
-	if ((arg_to_datatype(args[optind++], sm, FAULT_ON_ERROR) > 1) && 
-	    rawdata)
-        	error(FATAL, "member-specific output not allowed with -r\n");
-
-	if ((len = sm->size) < 0) {
-		error(INFO, "structure not found: %s\n", sm->name);
-		cmd_usage(pc->curcmd, SYNOPSIS); 
-	}
-	
-	if (!args[optind]) {
-		do_datatype_declaration(sm, flags | (sm->flags & TYPEDEF));
+        if ((count_chars(args[optind], ',')+1) > MAXARGS) {
+                error(INFO,
+                        "too many arguments in comma-separated list!\n");
 		return;
 	}
 
-	while (args[optind]) {
+	optind_save = optind;
+
+        /*
+         *  Take care of address and count (array).
+         */
+	while (args[++optind]) {
 		if (clean_arg() && IS_A_NUMBER(args[optind])) { 
 			if (aflag) 
 				count = stol(args[optind], 
@@ -4041,90 +4070,52 @@
 	                fprintf(fp, "possible aternatives:\n");
 	                if (!symbol_query(args[optind], "  ", NULL))
 	                   	fprintf(fp, "  (none found)\n");
-			return;
+			goto freebuf;
 		}
-		optind++;
 	}
 
-	if (!aflag)
+	optind = optind_save;
+
+        if (args[optind+1] && !aflag) 
 		error(FATAL, "no kernel virtual address argument entered\n");
 
 	if (list_head_offset)
 		addr -= list_head_offset;
 
-	if (count < 0) {
-		addr -= len * abs(count);
-		addr += len;
-	}
-
-	for (c =  0; c < abs(count); c++, addr += len) {
-		if (rawdata) 
-			raw_data_dump(addr, len, flags & STRUCT_VERBOSE);
-		else {
-			if (sm->member) 
-				open_tmpfile();
-
-			print_struct(sm->name, addr);
 
-			if (sm->member) {
-				parse_for_member(sm, PARSE_FOR_DATA);
-				close_tmpfile();
-			}
-		}
+        p2= strstr(args[optind],".");
+        /*
+         * Condition true only if we find "." and we have at least one charactere after ".".
+         * IE : "task_struct.pid,tgid" or "task_struct.p" (error in this last case).
+         * "task_struct" and "task_struct." (error in this last case) with else case.
+        */
+        if(p2 && *(++p2)){
+                structname = GETBUF(strlen(args[optind])+1);
+                strcpy(structname, args[optind]);
+                p1 = strstr(structname, ".")+1;
+                members = GETBUF(strlen(args[optind])+1);
+                strcpy(members, p2);
+                replace_string(members, ",", ' ');
+                argc_members = parse_line(members, arglist);
+		if (argc_members >1 &&  (flags&SHOW_OFFSET)) {
+                	error(INFO,
+                        	"multi-members not yet supported with option  -o!\n");
+			goto freebuf;
 	}
-}
-
-/*
- *  After determining what type of data type follows the *, this routine
- *  has the identical functionality as cmd_struct() or cmd_union().
- */
-void 
-cmd_pointer(void)
-{
-	int c;
-	ulong addr, aflag;
-	struct syment *sp;
-	int rawdata;
-	long len;
-	ulong flags;
-	int count;
-        struct datatype_member datatype_member, *dm;
-
-        dm = &datatype_member;
-	rawdata = 0;
-	flags = 0;
-	aflag = 0;
-	count = 1;
-
-        while ((c = getopt(argcnt, args, "c:rvo")) != EOF) {
-                switch(c)
-		{
-                case 'c':
-                        count = atoi(optarg);
-                        break;
-
-		case 'r':
-			rawdata = 1;
-			break;
-
-		case 'v':
-			flags |= STRUCT_VERBOSE;
-			break;
-
-		case 'o':
-			flags |= SHOW_OFFSET;
-			break;
+        } else
+                structname = args[optind];
 
-		default:
-			argerrs++;
-			break;
-		}
+       	for (c =  0; c < abs(count); c++, addr += len) {
+		i=0;
+        	do {
+                	if(argc_members) {
+                        	*(p1-1)='.'; /* Because arg_to_datatype(). */
+                        	*p1 = NULLCHAR;
+                        	strcat(structname, arglist[i]);
 	}
 
-	if (argerrs || !args[optind])
-		cmd_usage(pc->curcmd, SYNOPSIS);
 
-	if ((arg_to_datatype(args[optind++], dm, FAULT_ON_ERROR) > 1) && 
+			if ((arg_to_datatype(structname, dm, FAULT_ON_ERROR) > 1) && 
 	     rawdata)
         	error(FATAL, "member-specific output not allowed with -r\n");
 
@@ -4132,53 +4123,37 @@
 		error(INFO, "structure or union not found: %s\n", dm->name);
 		cmd_usage(pc->curcmd, SYNOPSIS);
 	}
-
+			if (! (dm->flags & TYPEDEF)){
+				if (flags &(STRUCT_REQUEST|UNION_REQUEST) ) {
+					if ((flags & (STRUCT_REQUEST|UNION_REQUEST))!= dm->type) 
+						goto freebuf;
+				} else
 	flags |= dm->type;
-
-	if (!args[optind]) {
-		do_datatype_declaration(dm, flags | (dm->flags & TYPEDEF));
-                return;
 	}
 
-	while (args[optind]) {
-		if (clean_arg() && IS_A_NUMBER(args[optind])) { 
-                        if (aflag)
-                                count = stol(args[optind],
-                                        FAULT_ON_ERROR, NULL);
-                        else {
-                                if (!IS_KVADDR(addr = htol(args[optind],
-                                    FAULT_ON_ERROR, NULL)))
-                                        error(FATAL,
-                                        "invalid kernel virtual address: %s\n",
-                                                args[optind]);
-                                aflag++;
-                        }
-		}
-	        else if ((sp = symbol_search(args[optind]))) {
-	                addr = sp->value;
-			aflag++;
-	        } else {
-			fprintf(fp, "symbol not found: %s\n", args[optind]);
-	                fprintf(fp, "possible aternatives:\n");
-	                if (!symbol_query(args[optind], "  ", NULL))
-	                   	fprintf(fp, "  (none found)\n");
-			return;
-		}
-		optind++;
+			/* 
+	 		*  No address was passed.
+	 		*/
+
+			if (!args[optind+1]) {
+				do_datatype_declaration(dm, flags | (dm->flags & TYPEDEF));
+				if(argc_members >1)
+					error(INFO, "multi-members not yet supported in this context!\n");
+				goto freebuf;
 	}
 
 	if (!(flags & (UNION_REQUEST|STRUCT_REQUEST)))
 		error(FATAL, "invalid argument!");
 
-        if (!aflag) 
-                error(FATAL, "no kernel virtual address argument entered\n");
+
 
 	if (count < 0) {
 		addr -= len * abs(count);
 		addr += len;
 	}
-
-        for (c =  0; c < abs(count); c++, addr += len) {
+			/*
+		 	*  Display data.
+		 	*/
                 if (rawdata)
                         raw_data_dump(addr, len, flags & STRUCT_VERBOSE);
                 else {
@@ -4195,144 +4170,17 @@
                                 close_tmpfile();
                         }
                 }
+		} while (++i < argc_members );
+		fprintf(fp,"\n");
         }
-}
-
-/*
- * This command displays either a union definition, or a formatted display
- * of the contents of a union at a specified address.  If no address is
- * specified, the union size and the file in which the union is defined
- * are also displayed.  A union member may be appended to the union
- * name (in a "union.member" format) in order to limit the scope of the data 
- * displayed to that particular member.  Structure data is shown in hexadecimal
- * format.  The raw data in a union may be dumped with the -r flag.
- */
-void
-cmd_union(void)
-{
-	int c;
-	ulong addr, aflag;
-	struct syment *sp;
-	int rawdata;
-	long len;
-	ulong flags;
-	int count;
-        struct datatype_member union_member, *um;
-	ulong list_head_offset;
-
-        um = &union_member;
-	count = 1;
-	rawdata = 0;
-	aflag = 0;
-	list_head_offset = 0;
-	flags = UNION_REQUEST;
-
-        while ((c = getopt(argcnt, args, "c:rvol:")) != EOF) {
-                switch(c)
-		{
-		case 'c':
-			count = atoi(optarg);
-			break;
-
-		case 'r':
-			rawdata = 1;
-			break;
-
-		case 'v':
-			flags |= STRUCT_VERBOSE;
-			break;
-
-		case 'o':
-			flags |= SHOW_OFFSET;
-			break;
-
-                case 'l':
-                        if (IS_A_NUMBER(optarg))
-                                list_head_offset = stol(optarg,
-                                        FAULT_ON_ERROR, NULL);
-                        else if (arg_to_datatype(optarg,
-                                um, RETURN_ON_ERROR) > 1)
-                                list_head_offset = um->member_offset;
-                        break;
-
-		default:
-			argerrs++;
-			break;
-		}
-	}
-
-	if (argerrs || !args[optind])
-		cmd_usage(pc->curcmd, SYNOPSIS);
-
-	if ((arg_to_datatype(args[optind++], um, FAULT_ON_ERROR) > 1) && 
-	     rawdata)
-        	error(FATAL, "member-specific output not allowed with -r\n");
-
-	if ((len = um->size) < 0)  {
-		error(INFO, "union not found: %s\n", um->name);
-		cmd_usage(pc->curcmd, SYNOPSIS);
-	}
-	
-	if (!args[optind]) {
-		do_datatype_declaration(um, flags | (um->flags & TYPEDEF));
-                return;
-	}
-
-	while (args[optind]) {
-		if (clean_arg() && IS_A_NUMBER(args[optind])) { 
-                        if (aflag)
-                                count = stol(args[optind],
-                                        FAULT_ON_ERROR, NULL);
-                        else {
-                                if (!IS_KVADDR(addr = htol(args[optind],
-                                    FAULT_ON_ERROR, NULL)))
-                                        error(FATAL,
-                                        "invalid kernel virtual address: %s\n",
-                                                args[optind]);
-                                aflag++;
-                        }
-		}
-	        else if ((sp = symbol_search(args[optind]))) {
-	                addr = sp->value;
-			aflag++;
-		} else {
-			fprintf(fp, "symbol not found: %s\n", args[optind]);
-	                fprintf(fp, "possible aternatives:\n");
-	                if (!symbol_query(args[optind], "  ", NULL))
-	                   	fprintf(fp, "  (none found)\n");
-			return;
-		}
-		optind++;
-	}
-
-        if (!aflag) 
-                error(FATAL, "no kernel virtual address argument entered\n");
-
-	if (list_head_offset)
-		addr -= list_head_offset;
-
-	if (count < 0) {
-		addr -= len * abs(count);
-		addr += len;
-	}
-
-	for (c = 0; c < abs(count); c++, addr += len) {
-		if (rawdata) 
-			raw_data_dump(addr, len, flags & STRUCT_VERBOSE);
-		else {
-			if (um->member)
-				open_tmpfile();
-
-			print_union(um->name, addr);
-
-			if (um->member) {
-				parse_for_member(um, PARSE_FOR_DATA);
-				close_tmpfile();
-			}
-		}
+freebuf:
+        if(argc_members){
+                FREEBUF(structname);
+                FREEBUF(members);
 	}
 }
 
+
 /*
  *  Generic function for dumping data structure declarations, with a small
  *  fixup for typedefs, sizes and member offsets.
