----- 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(a)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(a)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