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 -- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility