----- Original Message ----- > Dave, > > Here is the patch which add feature to whatis that would display full parameter name > when it detect the symbol is a function. > > And this patch already include previous fix for gdb_get_datatype, > please help review it. > > Thanks, > Lei When I attempt a "whatis <text-symbol>" on a module function prior to loading its module.ko file, your patch changes the command's behavior. For example, without your patch, it shows that the gdb request failed: crash> whatis call_transmit whatis: gdb request failed: whatis call_transmit crash> So I load the module, and try again: crash> mod -s sunrpc MODULE NAME SIZE OBJECT FILE ffffffffa0153ea0 sunrpc 255581 /lib/modules/3.7.9-104.fc17.x86_64/kernel/net/sunrpc/sunrpc.ko crash> whatis call_transmit void call_transmit(struct rpc_task *); crash> But with your patch, it fails quietly: crash> whatis call_transmit crash> And while it works most of the time: crash> mod -s sunrpc MODULE NAME SIZE OBJECT FILE ffffffffa0153ea0 sunrpc 255581 /lib/modules/3.7.9-104.fc17.x86_64/kernel/net/sunrpc/sunrpc.ko crash> whatis call_transmit void call_transmit(struct rpc_task * task); crash> if I do some other whatis/mod commands prior to it, I occasionally can get this to happen: crash> mod -s sunrpc MODULE NAME SIZE OBJECT FILE ffffffffa0153ea0 sunrpc 255581 /lib/modules/3.7.9-104.fc17.x86_64/kernel/net/sunrpc/sunrpc.ko crash> whatis call_transmit <segmentation violation in gdb> crash> The backtrace shows a SIGSEGV in your new gdb_function_nameargs() function: Program received signal SIGSEGV, Segmentation fault. gdb_function_nameargs (req=<optimized out>) at symtab.c:5263 5263 while ((BLOCK_FUNCTION(b) == NULL || block_inlined_p(b)) Missing separate debuginfos, use: debuginfo-install glibc-2.15-58.fc17.x86_64 ncurses-libs-5.9-4.20120204.fc17.x86_64 zlib-1.2.5-7.fc17.x86_64 (gdb) bt #0 gdb_function_nameargs (req=<optimized out>) at symtab.c:5263 #1 gdb_command_funnel (req=req@entry=0xdd1e20) at symtab.c:4957 #2 0x00000000004d78c0 in gdb_interface (req=req@entry=0xdd1e20) at gdb_interface.c:397 #3 0x000000000050860d in whatis_variable (sp=<optimized out>) at symbols.c:6767 #4 0x0000000000508ab4 in cmd_whatis () at symbols.c:6199 #5 0x0000000000460694 in exec_command () at main.c:775 #6 0x0000000000521982 in exec_input_file () at cmdline.c:1407 #7 0x00000000004603e6 in is_input_file () at main.c:871 #8 exec_command () at main.c:782 #9 0x00000000004608ba in main_loop () at main.c:723 #10 0x000000000056ee49 in captured_command_loop (data=data@entry=0x0) at ./main.c:228 #11 0x000000000056e28e in catch_errors (func=func@entry=0x56ee40 <captured_command_loop>, func_args=func_args@entry=0x0, errstring=errstring@entry=0x882acb "", mask=mask@entry=6) at exceptions.c:531 #12 0x000000000056fad6 in captured_main (data=data@entry=0x7fffffffe430) at ./main.c:958 #13 0x000000000056e28e in catch_errors (func=func@entry=0x56ef20 <captured_main>, func_args=func_args@entry=0x7fffffffe430, errstring=errstring@entry=0x882acb "", mask=mask@entry=6) at exceptions.c:531 #14 0x000000000056fda4 in gdb_main (args=args@entry=0x7fffffffe430) at ./main.c:973 #15 0x000000000056fdde in gdb_main_entry (argc=<optimized out>, argv=argv@entry=0x7fffffffe588) at ./main.c:993 #16 0x00000000004d69d4 in gdb_main_loop (argc=<optimized out>, argc@entry=1, argv=argv@entry=0x7fffffffe588) at gdb_interface.c:76 #17 0x000000000045eeff in main (argc=1, argv=0x7fffffffe588) at main.c:628 (gdb) But unfortunately, it's not necessarily reproducible, even with the same set of commands! The backtrace above was from a live session, and now I can't seem to reproduce it. But I'm guessing that block_for_pc_sect() returned a NULL "b" pointer. Dave > > From 8ea80a2ddbd0ea524a715a5e188118c39a0ce311 Mon Sep 17 00:00:00 > 2001 > From: Lei Wen <leiwen@xxxxxxxxxxx> > Date: Mon, 11 Mar 2013 10:34:15 +0800 > Subject: [PATCH] whatis: display full parameter name when symbol is > function > > Signed-off-by: Lei Wen <leiwen@xxxxxxxxxxx> > --- > defs.h | 1 + > gdb-7.3.1.patch | 77 > +++++++++++++++++++++++++++++++++++++++++++++++++++++++ > gdb_interface.c | 3 ++ > symbols.c | 50 +++++++++++++++++++++++++++++++++++- > 4 files changed, 130 insertions(+), 1 deletions(-) > > diff --git a/defs.h b/defs.h > index 1f693c3..1b31d1f 100755 > --- a/defs.h > +++ b/defs.h > @@ -3685,6 +3685,7 @@ struct gnu_request { > #define GNU_GET_SYMBOL_TYPE (15) > #define GNU_USER_PRINT_OPTION (16) > #define GNU_SET_CRASH_BLOCK (17) > +#define GNU_FUNCTION_NAMEARGS (18) > #define GNU_DEBUG_COMMAND (100) > /* > * GNU flags > diff --git a/gdb-7.3.1.patch b/gdb-7.3.1.patch > index a12d3d4..3b0f0d1 100644 > --- a/gdb-7.3.1.patch > +++ b/gdb-7.3.1.patch > @@ -1821,3 +1821,80 @@ diff -up gdb-7.3.1/gdb/psymtab.c.orig > gdb-7.3.1/gdb/psymtab.c > break; > > if (cur_sec == NULL) > +--- gdb-7.3.1/gdb/symtab.c.orig > ++++ gdb-7.3.1/gdb/symtab.c > +@@ -4848,6 +4848,7 @@ static void gdb_get_symbol_type(struct > gnu_request *); > + static void gdb_command_exists(struct gnu_request *); > + static void gdb_debug_command(struct gnu_request *); > + static void gdb_function_numargs(struct gnu_request *); > ++static void gdb_function_nameargs(struct gnu_request *); > + static void gdb_add_symbol_file(struct gnu_request *); > + static void gdb_delete_symbol_file(struct gnu_request *); > + static void gdb_patch_symbol_values(struct gnu_request *); > +@@ -4952,6 +4953,10 @@ gdb_command_funnel(struct gnu_request *req) > + gdb_set_crash_block(req); > + break; > + > ++ case GNU_FUNCTION_NAMEARGS: > ++ gdb_function_nameargs(req); > ++ break; > ++ > + default: > + req->flags |= GNU_COMMAND_FAILED; > + break; > +@@ -5054,8 +5059,9 @@ gdb_get_datatype(struct gnu_request *req) > + if (gdb_CRASHDEBUG(2)) > + console("expr->elts[0].opcode: OP_VAR_VALUE\n"); > + type = expr->elts[2].symbol->type; > ++ req->typecode = TYPE_CODE(type); > ++ req->length = TYPE_LENGTH(type); > + if (TYPE_CODE(type) == TYPE_CODE_ENUM) { > +- req->typecode = TYPE_CODE(type); > + req->value = SYMBOL_VALUE(expr->elts[2].symbol); > + req->tagname = TYPE_TAG_NAME(type); > + if (!req->tagname) { > +@@ -5243,6 +5249,44 @@ gdb_function_numargs(struct gnu_request *req) > + req->value = (ulong)TYPE_NFIELDS(sym->type); > + } > + > ++static void > ++gdb_function_nameargs(struct gnu_request *req) > ++{ > ++ struct block *b; > ++ struct dict_iterator iter; > ++ struct symbol *sym = NULL; > ++ int len; > ++ char *buf = req->buf; > ++ > ++ b = block_for_pc_sect(req->pc, find_pc_mapped_section(req->pc)); > ++ /* Get the lexical block, which is not a inline function */ > ++ while ((BLOCK_FUNCTION(b) == NULL || block_inlined_p(b)) > ++ && BLOCK_SUPERBLOCK(b) != NULL) > ++ b = BLOCK_SUPERBLOCK(b); > ++ > ++ ALL_BLOCK_SYMBOLS (b, iter, sym) > ++ { > ++ if (!SYMBOL_IS_ARGUMENT (sym)) > ++ continue; > ++ > ++ if (*SYMBOL_LINKAGE_NAME (sym)) > ++ { > ++ struct symbol *nsym; > ++ > ++ nsym = lookup_symbol (SYMBOL_LINKAGE_NAME (sym), > ++ b, VAR_DOMAIN, NULL); > ++ gdb_assert (nsym != NULL); > ++ if (SYMBOL_CLASS (nsym) != LOC_REGISTER > ++ || SYMBOL_IS_ARGUMENT (nsym)) > ++ sym = nsym; > ++ } > ++ > ++ len = strlen(SYMBOL_PRINT_NAME(sym)); > ++ sprintf(buf, "%s,", SYMBOL_PRINT_NAME(sym)); > ++ buf += len + 1; > ++ } > ++} > ++ > + struct load_module *gdb_current_load_module = NULL; > + > + static void > diff --git a/gdb_interface.c b/gdb_interface.c > index afc197c..a460ea8 100755 > --- a/gdb_interface.c > +++ b/gdb_interface.c > @@ -590,6 +590,9 @@ gdb_command_string(int cmd, char *buf, int live) > case GNU_SET_CRASH_BLOCK: > sprintf(buf, "GNU_SET_CRASH_BLOCK"); > break; > + case GNU_FUNCTION_NAMEARGS: > + sprintf(buf, "GNU_FUNCTION_NAMEARGS"); > + break; > case 0: > buf[0] = NULLCHAR; > break; > diff --git a/symbols.c b/symbols.c > index 4fb397c..b38a2a3 100755 > --- a/symbols.c > +++ b/symbols.c > @@ -6660,18 +6660,62 @@ whatis_datatype(char *st, ulong flags, FILE > *ofp) > } > > /* > + * add the function argument to the function type showing > + * The arg name input is seperated by comma > + */ > +static void > +add_function_name(char *argnames, char *func) > +{ > + char *arg, *seperator, *tmp; > + > + tmp = func; > + for (arg = strtok(argnames, ","); arg; ) { > + seperator = strstr(tmp, ","); > + if (!seperator) > + seperator= strrchr(func, ')'); > + > + shift_string_right(seperator, strlen(arg) + 1); > + BCOPY(arg, seperator + 1, strlen(arg)); > + tmp = seperator + 2 + strlen(arg); > + arg = strtok(NULL, ","); > + } > +} > + > +/* > * Scan the symbol file for a variable declaration. > */ > static void > whatis_variable(struct syment *sp) > { > + struct datatype_member datatype_member, *dm; > + struct gnu_request *req; > + int ret; > char *p1; > char buf[BUFSIZE]; > > + dm = &datatype_member; > + strcpy(buf, sp->name); > + if (!arg_to_datatype(buf, dm, RETURN_ON_ERROR|DATATYPE_QUERY)) > + return FALSE; > + > open_tmpfile(); > sprintf(buf, "whatis %s", sp->name); > - if (!gdb_pass_through(buf, fp, GNU_RETURN_ON_ERROR)) { > + > + req = (struct gnu_request *)GETBUF(sizeof(struct gnu_request)); > + req->buf = GETBUF(BUFSIZE); > + > + ret = gdb_pass_through(buf, fp, GNU_RETURN_ON_ERROR); > + if (ret && dm->type == FUNCTION) { > + req->command = GNU_FUNCTION_NAMEARGS; > + req->flags |= GNU_RETURN_ON_ERROR; > + req->pc = symbol_value(sp->name); > + > + gdb_interface(req); > + } > + if (!ret || req->flags & GNU_COMMAND_FAILED) { > close_tmpfile(); > + FREEBUF(req->buf); > + FREEBUF(req); > error(FATAL, "gdb request failed: whatis %s\n", > sp->name); > } > > @@ -6693,6 +6737,7 @@ whatis_variable(struct syment *sp) > if (index(buf, '(') == rindex(buf, '(')) { > shift_string_right(p1, strlen(sp->name)); > BCOPY(sp->name, p1, strlen(sp->name)); > + add_function_name(req->buf, p1 + strlen(sp->name)); > } else { > p1 = strstr(buf, ")"); > shift_string_right(p1, strlen(sp->name)); > @@ -6705,6 +6750,9 @@ whatis_variable(struct syment *sp) > fprintf(fp, "%s%s%s;\n", p1, LASTCHAR(p1) == '*' ? > "":" ", > sp->name); > } > + > + FREEBUF(req->buf); > + FREEBUF(req); > } > > /* > -- > 1.7.5.4 > -- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility