--- 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
};