[Crash-utility] whatis: display full parameter name when symbol is function
Dave Anderson
anderson at redhat.com
Tue Mar 12 20:05:35 UTC 2013
----- 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.
Dave
>
>
> >
> > From 8ea80a2ddbd0ea524a715a5e188118c39a0ce311 Mon Sep 17 00:00:00
> > 2001
> > From: Lei Wen <leiwen at marvell.com>
> > 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 at marvell.com>
> > ---
> > 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
> >
>
More information about the Crash-utility
mailing list