--- 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.