From 8e41f5af6c3eaa398a0070d43e175da9c285c476 Mon Sep 17 00:00:00 2001
From: Lei Wen <leiwen@marvell.com>
Date: Thu, 14 Mar 2013 09:51:12 +0800
Subject: [PATCH] whatis: display full parameter name when symbol is function

Change-Id: I856b9458d8a73ab131bf378e8438bab9447e6184
Signed-off-by: Lei Wen <leiwen@marvell.com>
---
 Makefile        |   10 +++---
 defs.h          |    1 +
 gdb-7.3.1.patch |   80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 gdb_interface.c |    3 ++
 symbols.c       |   50 +++++++++++++++++++++++++++++++++-
 5 files changed, 138 insertions(+), 6 deletions(-)

diff --git a/Makefile b/Makefile
index 11c7e0d..4b5be5c 100644
--- a/Makefile
+++ b/Makefile
@@ -23,8 +23,8 @@ PROGRAM=crash
 # Supported targets: X86 ALPHA PPC IA64 PPC64
 # TARGET and GDB_CONF_FLAGS will be configured automatically by configure
 #
-TARGET=
-GDB_CONF_FLAGS=
+TARGET=ARM
+GDB_CONF_FLAGS=--target=arm-elf-linux CFLAGS=-m32
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
 ifeq (${ARCH}, ppc64)
@@ -36,7 +36,7 @@ endif
 #
 GDB=gdb-7.3.1
 GDB_FILES=${GDB_7.3.1_FILES}
-GDB_OFILES=
+GDB_OFILES=${GDB_7.3.1_OFILES}
 GDB_PATCH_FILES=gdb-7.3.1.patch
 
 #
@@ -175,7 +175,7 @@ GDB_7.3.1_OFILES=${GDB}/gdb/symtab.o
 # 
 # GDB_FLAGS is passed up from the gdb Makefile.
 #
-GDB_FLAGS=
+GDB_FLAGS=-DGDB_7_3_1
 
 #
 # WARNING_OPTIONS and WARNING_ERROR are both applied on a per-file basis. 
@@ -188,7 +188,7 @@ GDB_FLAGS=
 #WARNING_ERROR=-Werror
 
 # TARGET_CFLAGS will be configured automatically by configure
-TARGET_CFLAGS=
+TARGET_CFLAGS=-m32 -D_FILE_OFFSET_BITS=64
 
 CRASH_CFLAGS=-g -D${TARGET} ${TARGET_CFLAGS} ${GDB_FLAGS} ${CFLAGS}
 
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..574d290 100644
--- a/gdb-7.3.1.patch
+++ b/gdb-7.3.1.patch
@@ -1821,3 +1821,83 @@ 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
++++ 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,47 @@ 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));
++	if (!b)
++		return;
++
++	/* 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..75ffc69 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))
+                error(FATAL, "gdb request failed: whatis %s\n", sp->name);
+
         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

