Dave, On Wed, Mar 13, 2013 at 4:05 AM, Dave Anderson <anderson@xxxxxxxxxx> wrote: > > > ----- Original Message ----- > >> 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 > > I was able to reproduce once by running this set of commands > from an input file: > > $ cat /tmp/input > whatis crash_read > mod -s crash > whatis crash_read > whatis call_transmit > mod -s sunrpc > whatis call_transmit > whatis nfs_alloc_server > mod -s nfs > whatis nfs_alloc_server > $ > > which resulted in: > > crash> < /tmp/input > crash> whatis crash_read > crash> mod -s crash > MODULE NAME SIZE OBJECT FILE > ffffffffa07c5140 crash 12577 /lib/modules/3.7.9-104.fc17.x86_64/kernel/drivers/char/crash.ko > crash> whatis crash_read > ssize_t crash_read(struct file * file, char * buf, size_t count, loff_t * poff); > crash> whatis call_transmit > <segmentation violation in gdb> > > 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> whatis nfs_alloc_server > <segmentation violation in gdb> > > crash> mod -s nfs > MODULE NAME SIZE OBJECT FILE > ffffffffa07ad920 nfs 169253 /lib/modules/3.7.9-104.fc17.x86_64/kernel/fs/nfs/nfs.ko > crash> whatis nfs_alloc_server > <segmentation violation in gdb> > > crash> > > But again, it's not reproducible all of the time? > > Anyway, it was getting a NULL back from the first call to to block_for_pc_sect(): > > 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); > > And I note that other gdb usage of block_for_pc_sect() or the block_for_pc() > wrapper function do seem to ensure a non-NULL return value. > I see... How about below patch, I add the checking for return value of block_for_pc_sect, is it better now? >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 Change-Id: I4f8067f89ec67b7799be26912d76092bb844f7d2 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,82 @@ 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,46 @@ 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 */ ++ if (b) { ++ 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