[Crash-utility] [Patch 1/2] Request data structures of particular size. Crash part.

Alexandr Terekhov Alexandr_Terekhov at epam.com
Wed Apr 6 08:15:41 UTC 2016


--- crash-7.1.4/defs.h	2015-12-16 18:59:36.000000000 +0300
+++ crash-7.1.4.test/defs.h	2016-04-04 09:46:42.615294482 +0300
@@ -6235,7 +6237,7 @@
  *  gdb/symtab.c
  */
 extern void gdb_command_funnel(struct gnu_request *);
-
+extern int search_matched_struct_symbols (const char *, int, int, const char ***, int **);
 /*
  *  gdb/symfile.c
  */
--- crash-7.1.4/help.c	2015-12-16 18:59:36.000000000 +0300
+++ crash-7.1.4.test/help.c	2016-04-01 13:08:48.878755448 +0300
@@ -3461,9 +3461,9 @@
 char *help_whatis[] = {
 "whatis",
 "search symbol table for data or type information",
-"[struct | union | typedef | symbol] ",
+"[[-c] [struct | union | typedef | symbol]] | [[-f field] -r range] ",
 "  This command displays the definition of structures, unions, typedefs or",
-"  text/data symbols.\n",
+"  text/data symbols, or fulfil a search of structure with particular size.\n",
 "    struct  a structure name. The output is the same as if the \"struct\"",
 "            command was used.",
 "     union  a union name. The output is the same as if the \"union\" command",
@@ -3473,6 +3473,10 @@
 "            was used. If the typedef is a primitive datatype, the one-line",
 "            declaration is displayed.",
 "    symbol  a kernel symbol.  ",
+"  -f field  The field type (or substring of type name) which the structure",
+"            should contain",
+"  -r range  The range or the exact size of the structure we're looking for.",
+
 "\nEXAMPLES",
 "   Display the definition of a linux_binfmt structure:\n", 
 "    %s> whatis linux_binfmt",
@@ -3514,7 +3518,29 @@
 "  Display definition of a kdev_t typedef:\n",
 "    %s> whatis kdev_t",
 "    typedef short unsigned int kdev_t;",
-"    SIZE: 2  (0x2)",
+"    SIZE: 2  (0x2)\n",
+"  Find all structures which have size exactly 192 bytes:\n",
+"    %s> whatis -r 192",
+"    192	apic",
+"    192	ata_eh_context",
+"    192	cper_sec_proc_generic",
+"    192	cpuinfo_x86",
+"    192	pebs_record_hsw\n",
+"  Find all structures which have size from 190 up to 200 bytes and which",
+"  contain member of type '*list*'\n",
+"    %s> whatis -r 190-200 -f list",
+"    196	kioctx",
+"    200	scsi_transport_template",
+"  The structure `kioctx` really has members of types hlist_node and list_head.",
+"  However, the last structure is more subtle. It contains field of type",
+"  list_head within itself.",
+"  That is:",
+"  scsi_transport_template` contains member of type `transport_container`,",
+"  which has member of type attribute_container. The last one, in its turn,", 
+"  contains list_head which has poiners to list_head.",
+"  This is the exact place where algorithm triggers. It delves into the",
+"  structure _only_ if the particular member is a structure, not a pointer.",
+"  If it is a pointer, we only match name of type against the given pattern.",
 NULL               
 };

--- crash-7.1.4/symbols.c	2015-12-16 18:59:36.000000000 +0300
+++ crash-7.1.4.test/symbols.c	2016-04-04 10:12:40.271317840 +0300
@@ -33,6 +33,8 @@
 static int compare_syms(const void *, const void *);
 static int compare_mods(const void *, const void *);
 static int compare_prios(const void *v1, const void *v2);
+static int compare_size_name(const void *, const void *);
+void request_types(int, int, const char *);
 static asection *get_kernel_section(char *);
 static char * get_section(ulong vaddr, char *buf);
 static void symbol_dump(ulong, char *);
@@ -5976,6 +5977,16 @@
 	return TRUE;
 }
 
+static int
+compare_size_name(const void *va, const void *vb) {
+	const struct { const char *n; int s; } *a = va, *b = vb;
+
+	if (a->s == b->s)
+		return strcmp(a->n, b->n);
+	else
+		return a->s < b->s ? -1 : 1;
+}
+
 static void 
 cmd_datatype_common(ulong flags)
 {
@@ -6529,6 +6540,38 @@
 	fprintf(ofp, "\n");
 }
 
+void
+request_types(int lowest, int highest, const char *field)
+{
+	const char **out_name = NULL;
+	int i, c;
+	int *out_size = NULL;
+	struct { const char *n; int s; } *struct_output;
+
+	if (lowest == UNUSED || highest == UNUSED)
+		error(FATAL, "You should specify range\n");
+
+	c = search_matched_struct_symbols(field, lowest, highest,
+		&out_name, &out_size);
+
+	struct_output = malloc(sizeof(*struct_output) * c);
+	if (!struct_output)
+		error(FATAL, "cannot malloc struct_output\n");
+
+	for (i = 0; i < c; i++) {
+		struct_output[i].n = out_name[i];
+		struct_output[i].s = out_size[i];
+	}
+
+	qsort(struct_output, c, sizeof(*struct_output), compare_size_name);
+
+	for (i = 0; i < c; i++)
+		fprintf(fp, "%d\t%s\n", struct_output[i].s, struct_output[i].n);
+
+	free(struct_output);
+	return;	
+}
+
 /*
  *  This command displays the definition of structures, unions, typedefs or
  *  text/data symbols:  
@@ -6543,33 +6587,59 @@
  *     declaration is displayed.
  *  5. For a kernel symbol name, the output is the same as if the "sym" command
  *     was used.
+ *  6. If the -r and optional -f are given, then the structures/unions of
+ *     specified size will be searched.
  */
 void
 cmd_whatis(void)
 {
         struct datatype_member datatype_member, *dm;
 	struct syment *sp;
-        char buf[BUFSIZE];
+
+	const char *field = NULL;
+	char buf[BUFSIZE], *pl = buf, *ph;;
 	long len;
-	int c;
+	int c, lowest, highest;
         ulong flags;
 
         dm = &datatype_member;
 	flags = 0;
+	lowest = highest = UNUSED;
 
-        while ((c = getopt(argcnt, args, "o")) != EOF) {
+        while ((c = getopt(argcnt, args, "of:r:")) != EOF) {
                 switch(c)
                 {
 		case 'o':
 			flags |= SHOW_OFFSET;
 			break;
 
+		case 'f':
+			field = optarg;
+			break;
+
+		case 'r':
+			strncpy(buf, optarg, 15);
+			if ((ph = strstr(buf, "-")) != NULL)
+				*(ph++) = '\0';
+
+			highest = lowest = stol(pl, FAULT_ON_ERROR, NULL);
+
+			if (ph)
+				highest = stol(ph, FAULT_ON_ERROR, NULL);
+
+			break;
+
                 default:
                         argerrs++;
                         break;
                 }
         }
 
+        if (!argerrs && lowest != UNUSED && highest != UNUSED) {
+                request_types(lowest, highest, field);
+                return;
+        }
+
         if (argerrs || !args[optind])
                 cmd_usage(pc->curcmd, SYNOPSIS);
 




More information about the Crash-utility mailing list