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

Alexandr Terekhov Alexandr_Terekhov at epam.com
Thu Apr 14 07:17:29 UTC 2016


--- crash-7.1.4.orig/defs.h	2015-12-16 18:59:36.000000000 +0300
+++ crash-7.1.4/defs.h	2016-04-12 15:39:58.149121279 +0300
@@ -4116,25 +4116,27 @@
 /*
  *  GNU commands
  */
-#define GNU_DATATYPE_INIT        (1)
-#define GNU_DISASSEMBLE          (2)
-#define GNU_GET_LINE_NUMBER      (3)
-#define GNU_PASS_THROUGH         (4)
-#define GNU_GET_DATATYPE         (5)
-#define GNU_COMMAND_EXISTS       (6)
-#define GNU_STACK_TRACE          (7)
-#define GNU_ALPHA_FRAME_OFFSET   (8)
-#define GNU_FUNCTION_NUMARGS     (9)
-#define GNU_RESOLVE_TEXT_ADDR    (10)
-#define GNU_ADD_SYMBOL_FILE      (11)
-#define GNU_DELETE_SYMBOL_FILE   (12)
-#define GNU_VERSION              (13)
-#define GNU_PATCH_SYMBOL_VALUES  (14)
-#define GNU_GET_SYMBOL_TYPE      (15)
-#define GNU_USER_PRINT_OPTION 	 (16)
-#define GNU_SET_CRASH_BLOCK      (17)
-#define GNU_GET_FUNCTION_RANGE   (18)
-#define GNU_DEBUG_COMMAND       (100)
+#define GNU_DATATYPE_INIT           (1)
+#define GNU_DISASSEMBLE             (2)
+#define GNU_GET_LINE_NUMBER         (3)
+#define GNU_PASS_THROUGH            (4)
+#define GNU_GET_DATATYPE            (5)
+#define GNU_COMMAND_EXISTS          (6)
+#define GNU_STACK_TRACE             (7)
+#define GNU_ALPHA_FRAME_OFFSET      (8)
+#define GNU_FUNCTION_NUMARGS        (9)
+#define GNU_RESOLVE_TEXT_ADDR       (10)
+#define GNU_ADD_SYMBOL_FILE         (11)
+#define GNU_DELETE_SYMBOL_FILE      (12)
+#define GNU_VERSION                 (13)
+#define GNU_PATCH_SYMBOL_VALUES     (14)
+#define GNU_GET_SYMBOL_TYPE         (15)
+#define GNU_USER_PRINT_OPTION 	    (16)
+#define GNU_SET_CRASH_BLOCK         (17)
+#define GNU_GET_FUNCTION_RANGE      (18)
+#define GNU_GET_NEXT_DATATYPE       (19)
+#define GNU_LOOKUP_STRUCT_CONTENTS  (20)
+#define GNU_DEBUG_COMMAND           (100)
 /*
  *  GNU flags
  */
--- crash-7.1.4.orig/symbols.c	2015-12-16 18:59:36.000000000 +0300
+++ crash-7.1.4/symbols.c	2016-04-12 15:38:52.497120294 +0300
@@ -33,6 +33,9 @@
 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 *);
+static void append_struct_symbol (void *,  struct gnu_request *);
+static void request_types(int, int, char *);
 static asection *get_kernel_section(char *);
 static char * get_section(ulong vaddr, char *buf);
 static void symbol_dump(ulong, char *);
@@ -5976,6 +5979,16 @@
 	return TRUE;
 }
 
+static int
+compare_size_name(const void *va, const void *vb) {
+	const struct { char *n; ulong 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 +6542,75 @@
 	fprintf(ofp, "\n");
 }
 
+static void
+append_struct_symbol (void *pout,  struct gnu_request *r)
+{
+	struct {
+		int sz, idx;
+		struct { char *n; int s; } *st;
+	} *output = pout;
+	int i, s;
+
+	for (i = 0; i < output->idx; i++)
+		if (output->st[i].n == r->name)
+			break;
+
+	if (i < output->idx) // We've already collected this type
+		return;
+
+	if (output->idx == output->sz) {
+		s = sizeof(*(output->st)) * output->sz;
+		output->st = (void *)resizebuf((void *)output->st, s, s * 3);
+		output->sz *= 3;
+	}
+	output->st[output->idx].n = r->name;
+	output->st[output->idx].s = (int)(r->length);
+	output->idx++;
+}
+
+static void
+request_types(int lowest, int highest, char *type_name)
+{
+	struct gnu_request request = {0};
+	struct {
+		int sz, idx;
+		struct { char *n; int s; } *st;
+	} output = {0, 0, NULL};
+	struct { char fi, i; void * p[3]; } iter = { 0 };
+
+	int i;
+
+	output.st = (void *)GETBUF(16 * sizeof(*(output.st)));
+	output.sz = 16;
+	request.addr2   = (ulong)&iter;
+#if defined(GDB_5_3) || defined(GDB_6_0) || defined(GDB_6_1) || defined(GDB_7_0)
+	req->typename = type_name;
+#else
+	request.type_name = type_name;
+#endif
+
+	while (!iter.fi) {
+		request.command = GNU_GET_NEXT_DATATYPE;
+		gdb_interface(&request);
+		if (!(lowest <= request.length && request.length <= highest))
+			continue;
+
+		request.command = GNU_LOOKUP_STRUCT_CONTENTS;
+		gdb_interface(&request);
+		if (!request.value)
+			continue;
+
+		append_struct_symbol(&output, &request);		
+	}
+
+	qsort(output.st, output.idx, sizeof(*output.st), compare_size_name);
+
+	for (i = 0; i < output.idx; i++)
+		fprintf(fp, "%d\t%s\n", output.st[i].s, output.st[i].n);
+
+	FREEBUF(output.st);
+}
+
 /*
  *  This command displays the definition of structures, unions, typedefs or
  *  text/data symbols:  
@@ -6543,33 +6625,58 @@
  *     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];
+
+	char buf[BUFSIZE], *pl = buf, *ph, *field = NULL;
 	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);
 
--- crash-7.1.4.orig/help.c	2015-12-16 18:59:36.000000000 +0300
+++ crash-7.1.4/help.c	2016-04-06 11:09:24.896859034 +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               
 };
 




More information about the Crash-utility mailing list