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

Alexandr Terekhov Alexandr_Terekhov at epam.com
Thu Apr 14 07:16:18 UTC 2016


Hello Dave,

I've rewritten the mentioned logic, now crash communicates with gdb by means of gdb_interface.

--- gdb-7.6.orig/gdb/symtab.c	2016-03-23 11:43:09.000000000 +0300
+++ gdb-7.6/gdb/symtab.c	2016-04-13 09:50:53.597120297 +0300
@@ -5140,6 +5140,9 @@
 static void gdb_set_crash_block(struct gnu_request *);
 void gdb_command_funnel(struct gnu_request *);
 
+static long lookup_struct_contents(struct gnu_request *);
+static void iterate_datatypes (struct gnu_request *);
+
 struct objfile *gdb_kernel_objfile = { 0 };
 
 static ulong gdb_merge_flags = 0;
@@ -5242,6 +5245,14 @@
 			req->flags |= GNU_COMMAND_FAILED;
 		break;
 
+	case GNU_LOOKUP_STRUCT_CONTENTS:
+		req->value = lookup_struct_contents(req);
+		break;
+
+	case GNU_GET_NEXT_DATATYPE:
+		iterate_datatypes(req);
+		break;
+
 	default:
 		req->flags |= GNU_COMMAND_FAILED;
 		break;
@@ -5779,4 +5790,144 @@
 	else
 		return NULL;
 }
+
+static long
+lookup_struct_contents(struct gnu_request *req)
+{
+  int i;
+  long r;
+  struct field *f;
+  struct main_type *m;
+  const char *n;
+  struct main_type *top_m = (struct main_type *)req->addr;
+#if defined(GDB_5_3) || defined(GDB_6_0) || defined(GDB_6_1) || defined(GDB_7_0)
+  char *type_name = req->typename;
+#else
+  char *type_name = req->type_name;
+#endif
+
+  if (!top_m || !type_name)
+    return 1;
+
+  for (i = 0; i < top_m->nfields; i++)
+    {
+      f = top_m->flds_bnds.fields + i;
+      if (!f->type)
+        continue;
+      m = f->type->main_type;
+
+      // If the field is an array, check the target type -
+      // it might be structure, or might not be.
+      // - struct request_sock *syn_table[0];
+      //   here m->target_type->main_type->code is expected
+      //   to be TYPE_CODE_PTR
+      // - struct list_head vec[TVN_SIZE];
+      //   here m->target_type->main_type->code should be
+      //   TYPE_CODE_STRUCT
+      if (m->code == TYPE_CODE_ARRAY && m->target_type)
+        m = m->target_type->main_type;
+
+      /* Here is a recursion.
+       * If we have struct variable (not pointer),
+       * scan this inner structure
+       */
+      if (m->code == TYPE_CODE_STRUCT) {
+        req->addr = (ulong)m;
+        r = lookup_struct_contents(req);
+        req->addr = (ulong)top_m;
+        if (r)
+          return 1;
+      }
+
+      if (m->code == TYPE_CODE_PTR && m->target_type)
+        m = m->target_type->main_type;
+      if (m->name)
+        n = m->name;
+      else if (m->tag_name)
+        n = m->tag_name;
+      else
+        continue;
+
+      if (strstr(n, type_name))
+        return 1;
+    }
+
+  return 0;
+}
+
+static void
+iterate_datatypes (struct gnu_request *req)
+{
+  static struct block_iterator bi; // Keeping this static will simplify code
+  struct block *b;
+  int do_return = 0;
+  struct {
+    char          fi, i;
+    struct symtab   *st;
+    struct symbol  *sym;
+    struct objfile   *o;
+  } *gi = (void *)req->addr2; /*Global iterator */
+
+  if (gi->fi)
+    return;
+
+  if (gi->o == NULL)
+    {
+      gi->o     = current_program_space->objfiles;
+      gi->st    = NULL;
+      do_return = 1;  // The initial case - we don't need to make next step.
+    }
+
+  for (; gi->o; gi->o = gi->o->next, gi->st = NULL)
+    {
+      if (gi->st == NULL)
+        {
+          // Symtab `st` is nullified for every objfile
+          if (gi->o->sf)
+            gi->o->sf->qf->expand_all_symtabs(gi->o);
+          gi->st = gi->o->symtabs;
+          gi->sym = NULL;
+        }
+
+      for (; gi->st; gi->st = gi->st->next, gi->i = -1)
+        {
+          if (!gi->st->primary)
+            continue;
+
+          if (gi->i == -1)
+            {
+              gi->i = GLOBAL_BLOCK;
+              gi->sym = NULL;
+            }
+          for (; gi->i <= STATIC_BLOCK; gi->i++, gi->sym = NULL)
+            {
+              if (!gi->sym)
+                {
+                  b = BLOCKVECTOR_BLOCK(BLOCKVECTOR(gi->st), gi->i);
+                  gi->sym = block_iterator_first(b, &bi);
+                }
+              for (; gi->sym; gi->sym = block_iterator_next(&bi))
+                {
+                  QUIT;
+
+                  if (SYMBOL_CLASS (gi->sym) != LOC_TYPEDEF)
+                    continue;
+
+                  // Iteration 1 (do_return == 0): initialization
+                  // Iteration 2 (do_return == 1): iterate symbol
+                  if (do_return++ == 0)
+                    continue;
+
+                  // Yield the current symbol and its size
+                  req->addr     = (ulong)(gi->sym->type->main_type);
+                  req->name     = (char *)(gi->sym->ginfo.name);
+                  req->length   = gi->sym->type->length;
+
+                  return;
+                }
+            }
+        }
+    }
+  gi->fi = 1;
+}
 #endif




More information about the Crash-utility mailing list