[PATCH 2/3] Extend percpu to recognize static percpu variables

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch extends the "percpu" command so that it can be used on static
variable directly (a bit like the "p" command).

Signed-off-by: Petr Tesarik <ptesarik@xxxxxxx>

---
 help.c    |    4 ++--
 symbols.c |   57 ++++++++++++++++++++++++++++++++++++++++++++++++++-------
 2 files changed, 52 insertions(+), 9 deletions(-)
Extend percpu to recognize static variables

This patch extends the "percpu" command so that it can be used on static
variable directly (a bit like the "p" command).

Signed-off-by: Petr Tesarik <ptesarik@xxxxxxx>

---
 help.c    |    4 ++--
 symbols.c |   57 ++++++++++++++++++++++++++++++++++++++++++++++++++-------
 2 files changed, 52 insertions(+), 9 deletions(-)

--- a/help.c
+++ b/help.c
@@ -1150,7 +1150,7 @@ NULL
 char *help_percpu[] = {
 "percpu",
 "percpu variables",
-"[-a] [-c cpu] [cpu]... [struct|union|*] struct_name [address|symbol]",
+"[-a] [-c cpu] [cpu]... [struct|union|*] [struct_name] [address|symbol]",
 "  This command displays a formatted display of the contents of a per-cpu",
 "  variable for a given set of CPUs.",
 " ",
@@ -1163,7 +1163,7 @@ char *help_percpu[] = {
 "  currently selected task.",
 "\nEXAMPLES",
 "  Show the value of a per-cpu variable on processor 2:\n",
-"    %s> percpu 2 list_head blk_cpu_iopoll",
+"    %s> percpu 2 blk_cpu_iopoll",
 "      [2]: ffff88011e290100",
 "    struct list_head {",
 "      next = 0xffff88011e290100, ",
--- a/symbols.c
+++ b/symbols.c
@@ -5987,6 +5987,27 @@ freebuf:
 	}
 }
 
+static char *
+symbol_type_name(const char *name)
+{
+	char buf[BUFSIZE], *p;
+
+	open_tmpfile();
+	sprintf(buf, "whatis %s", name);
+	if (!gdb_pass_through(buf, fp, GNU_RETURN_ON_ERROR)) {
+		close_tmpfile();
+		return NULL;
+	}
+
+	rewind(pc->tmpfile);
+	while (fgets(buf, BUFSIZE, pc->tmpfile) && !STRNEQ(buf, "type = "))
+		;
+	p = feof(pc->tmpfile) ? NULL : buf + strlen("type = ");
+	close_tmpfile();
+
+	return p ? strdup(clean_line(p)) : NULL;
+}
+
 /*
  * This command displays a data type after adjusting the address with
  * a per-cpu offset.
@@ -6052,34 +6073,45 @@ cmd_percpu(void)
 
 	flags = 0UL;
 	structname = NULL;
+	sp = NULL;
 
 	if (STREQ(args[optind], "struct")) {
 		flags |= STRUCT_REQUEST;
 		structname = args[++optind];
+		++optind;
 	} else if (STREQ(args[optind], "union")) {
 		flags |= UNION_REQUEST;
 		structname = args[++optind];
+		++optind;
 	} else if (args[optind][0] == '*') {
 		structname = args[optind][1]
 			? args[optind] + 1
 			: args[++optind];
-	} else {
+		++optind;
+	} else if (! (sp = per_cpu_symbol_search(args[optind]))) {
 		structname = args[optind];
+		++optind;
 	}
-	++optind;
 
-	if (argerrs || !structname || !args[optind] || args[optind+1]) {
+	if (argerrs || !args[optind] || args[optind+1] ||
+	    (!structname && !sp)) {
 		FREEBUF(cpus);
 		cmd_usage(pc->curcmd, SYNOPSIS);
 	}
 
-	if (arg_to_datatype(structname, dm,
+	if (structname && arg_to_datatype(structname, dm,
 			    DATATYPE_QUERY|ANON_MEMBER_QUERY|RETURN_ON_ERROR) < 1) {
 		FREEBUF(cpus);
 		error(FATAL, "invalid data structure reference: %s\n", structname);
 	}
 
-	if (dm->flags & TYPEDEF) {
+	if (sp) {
+		typename = symbol_type_name(sp->name);
+		if (arg_to_datatype(typename, dm,
+				    DATATYPE_QUERY|RETURN_ON_ERROR) < 1)
+			dm->type = 0;
+		flags |= dm->type;
+	} else if (dm->flags & TYPEDEF) {
 		flags |= dm->type;
 		typename = strdup(dm->name);
 	} else {
@@ -6099,7 +6131,9 @@ cmd_percpu(void)
 		goto freebuf;
 	}
 
-	if (clean_arg() && IS_A_NUMBER(args[optind])) {
+	if (sp) {
+		addr = sp->value;
+	} else if (clean_arg() && IS_A_NUMBER(args[optind])) {
 		addr = htol(args[optind], FAULT_ON_ERROR, NULL);
 	} else if ((sp = per_cpu_symbol_search(args[optind]))) {
 		addr = sp->value;
@@ -6131,7 +6165,16 @@ cmd_percpu(void)
 			continue;
 		}
 
-		fprintf(fp, "%s ", typename);
+		/* If it is a struct or union, make output similar to that
+		 * of cmd_datatype_common(), otherwise print a type cast.
+		 * Note that gdb already prints a typecast for pointer types,
+		 * so do not duplicate it here.
+		 */
+		if (dm->type & (STRUCT_REQUEST|UNION_REQUEST))
+			fprintf(fp, "%s ", typename);
+		else if (! (dm->type & POINTER))
+			fprintf(fp, "(%s) ", typename);
+
 		snprintf(buf, sizeof buf, "output *(%s*) 0x%lx",
 			 typename, cpuaddr);
 		gdb_pass_through(buf, NULL, GNU_RETURN_ON_ERROR);
--
Crash-utility mailing list
Crash-utility@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/crash-utility

[Index of Archives]     [Fedora Development]     [Fedora Desktop]     [Fedora SELinux]     [Yosemite News]     [KDE Users]     [Fedora Tools]

 

Powered by Linux