Hi Dave,
I'm sorry for the last submission. It seems I forgot to refresh the
patches, so it was completely bogus. Should be fixed now. I'm also
attaching my changes as one big patch to this message.
Petr Tesarik
--- a/symbols.c
+++ b/symbols.c
@@ -72,7 +72,10 @@ struct elf_common;
static void Elf32_Sym_to_common(Elf32_Sym *, struct elf_common *);
static void Elf64_Sym_to_common(Elf64_Sym *, struct elf_common *);
static void cmd_datatype_common(ulong);
-static int display_per_cpu_info(struct syment *);
+static void do_datatype_addr(struct datatype_member *, ulong, int,
+ ulong, char **, int);
+static void process_gdb_output(char *, unsigned, const char *, int);
+static int display_per_cpu_info(struct syment *, int, char *);
static struct load_module *get_module_percpu_sym_owner(struct syment *);
static int is_percpu_symbol(struct syment *);
static void dump_percpu_symbols(struct load_module *);
@@ -116,6 +119,8 @@ static int show_member_offset(FILE *, st
#define IN_STRUCT (0x40000)
#define DATATYPE_QUERY (0x80000)
#define ANON_MEMBER_QUERY (0x100000)
+#define SHOW_RAW_DATA (0x200000)
+#define DEREF_POINTERS (0x400000)
#define INTEGER_TYPE (UINT8|INT8|UINT16|INT16|UINT32|INT32|UINT64|INT64)
@@ -132,6 +137,7 @@ static void dump_datatype_flags(ulong, F
static long anon_member_offset(char *, char *);
static int gdb_whatis(char *);
static void do_datatype_declaration(struct datatype_member *, ulong);
+static int member_to_datatype(char *, struct datatype_member *, ulong);
#define DEBUGINFO_ERROR_MESSAGE1 \
"the use of a System.map file requires that the accompanying namelist\nargument is a kernel file built with the -g CFLAG. The namelist argument\nsupplied in this case is a debuginfo file, which must be accompanied by the\nkernel file from which it was derived.\n"
@@ -5704,13 +5710,13 @@ dereference_pointer(ulong addr, struct d
static void
cmd_datatype_common(ulong flags)
{
- int i, c;
+ int c;
ulong addr, aflag;
+ char *cpuspec;
+ ulong *cpus;
struct syment *sp;
- int rawdata;
- long len;
ulong list_head_offset;
- int count, pflag;
+ int count;
int argc_members;
int optind_save;
unsigned int radix, restore_radix;
@@ -5721,19 +5727,19 @@ cmd_datatype_common(ulong flags)
dm = &datatype_member;
count = 0xdeadbeef;
- rawdata = 0;
aflag = addr = 0;
list_head_offset = 0;
argc_members = 0;
radix = restore_radix = 0;
separator = members = NULL;
- pflag = 0;
+ cpuspec = NULL;
+ cpus = NULL;
while ((c = getopt(argcnt, args, "pxdhfuc:rvol:")) != EOF) {
switch (c)
{
case 'p':
- pflag++;
+ flags |= DEREF_POINTERS;
break;
case 'd':
@@ -5756,7 +5762,7 @@ cmd_datatype_common(ulong flags)
break;
case 'r':
- rawdata = 1;
+ flags |= SHOW_RAW_DATA;
break;
case 'v':
@@ -5816,11 +5822,22 @@ cmd_datatype_common(ulong flags)
if (aflag && (count != 0xdeadbeef))
error(FATAL, "too many arguments!\n");
+ if (!aflag) {
+ cpuspec = strchr(args[optind], ':');
+ if (cpuspec)
+ *cpuspec++ = NULLCHAR;
+ }
+
if (clean_arg() && IS_A_NUMBER(args[optind])) {
if (aflag)
count = stol(args[optind],
FAULT_ON_ERROR, NULL);
- else {
+ else if (cpuspec) {
+ if (pc->curcmd_flags & MEMTYPE_FILEADDR)
+ error(FATAL, "-f option cannot be used with percpu\n");
+ addr = htol(args[optind], FAULT_ON_ERROR, NULL);
+ aflag++;
+ } else {
if (pc->curcmd_flags & MEMTYPE_FILEADDR)
pc->curcmd_private = stoll(args[optind],
FAULT_ON_ERROR, NULL);
@@ -5835,6 +5852,12 @@ cmd_datatype_common(ulong flags)
aflag++;
}
} else if ((sp = symbol_search(args[optind]))) {
+ if (cpuspec && !is_percpu_symbol(sp)) {
+ error(WARNING,
+ "%s is not percpu; cpuspec ignored.\n",
+ sp->name);
+ cpuspec = NULL;
+ }
addr = sp->value;
aflag++;
} else {
@@ -5846,6 +5869,15 @@ cmd_datatype_common(ulong flags)
}
}
+ if (cpuspec) {
+ cpus = get_cpumask_buf();
+ if (STREQ(cpuspec, "")) {
+ SET_BIT(cpus, CURRENT_CONTEXT()->processor);
+ } else {
+ make_cpumask(cpuspec, cpus, FAULT_ON_ERROR, NULL);
+ }
+ }
+
optind = optind_save;
if (count == 0xdeadbeef)
@@ -5853,7 +5885,7 @@ cmd_datatype_common(ulong flags)
else if (!aflag)
error(FATAL, "no kernel virtual address argument entered\n");
- if (pflag && !aflag)
+ if ((flags & DEREF_POINTERS) && !aflag)
error(FATAL, "-p option requires address argument\n");
if (list_head_offset)
@@ -5878,6 +5910,15 @@ cmd_datatype_common(ulong flags)
DATATYPE_QUERY|ANON_MEMBER_QUERY|RETURN_ON_ERROR) < 1))
error(FATAL, "invalid data structure reference: %s\n", structname);
+ if (! (flags & (STRUCT_REQUEST|UNION_REQUEST)) ) {
+ flags |= dm->type;
+ if (!(flags & (UNION_REQUEST|STRUCT_REQUEST)))
+ error(FATAL, "invalid argument");
+ } else if ( (flags &(STRUCT_REQUEST|UNION_REQUEST)) != dm->type) {
+ error(FATAL, "data type mismatch: %s is not a %s\n",
+ dm->name, flags & UNION_REQUEST ? "union" : "struct");
+ }
+
if ((argc_members > 1) && !aflag) {
error(INFO, flags & SHOW_OFFSET ?
"-o option not valid with multiple member format\n" :
@@ -5891,7 +5932,52 @@ cmd_datatype_common(ulong flags)
error(FATAL,
"-o option not valid with multiple member format\n");
- len = dm->size;
+ set_temporary_radix(radix, &restore_radix);
+
+ /*
+ * No address was passed -- dump the structure/member declaration.
+ */
+ if (!aflag) {
+ if (argc_members &&
+ !member_to_datatype(memberlist[0], dm,
+ ANON_MEMBER_QUERY))
+ error(FATAL, "invalid data structure reference: %s.%s\n",
+ dm->name, memberlist[0]);
+ do_datatype_declaration(dm, flags | (dm->flags & TYPEDEF));
+ } else if (cpus) {
+ for (c = 0; c < kt->cpus; c++) {
+ ulong cpuaddr;
+
+ if (!NUM_IN_BITMAP(cpus, c))
+ continue;
+
+ cpuaddr = addr + kt->__per_cpu_offset[c];
+ fprintf(fp, " [%d]: %lx\n", c, cpuaddr);
+ do_datatype_addr(dm, cpuaddr , count,
+ flags, memberlist, argc_members);
+ }
+ } else
+ do_datatype_addr(dm, addr, count, flags,
+ memberlist, argc_members);
+
+ restore_current_radix(restore_radix);
+
+freebuf:
+ if (argc_members) {
+ FREEBUF(structname);
+ FREEBUF(members);
+ }
+
+ if (cpus)
+ FREEBUF(cpus);
+}
+
+static void
+do_datatype_addr(struct datatype_member *dm, ulong addr, int count,
+ ulong flags, char **memberlist, int argc_members)
+{
+ int i, c;
+ long len = dm->size;
if (count < 0) {
addr -= len * abs(count);
@@ -5908,83 +5994,44 @@ cmd_datatype_common(ulong flags)
i = 0;
do {
if (argc_members) {
- *separator = '.';
- strcpy(separator+1, memberlist[i]);
- }
-
- switch (arg_to_datatype(structname, dm,
- ANON_MEMBER_QUERY|RETURN_ON_ERROR))
- {
- case 0: error(FATAL, "invalid data structure reference: %s\n",
- structname);
- break;
- case 1: break;
- case 2: if (rawdata)
+ if (!member_to_datatype(memberlist[i], dm,
+ ANON_MEMBER_QUERY))
+ error(FATAL, "invalid data structure reference: %s.%s\n",
+ dm->name, memberlist[i]);
+ if (flags & SHOW_RAW_DATA)
error(FATAL,
- "member-specific output not allowed with -r\n");
- break;
+ "member-specific output not allowed with -r\n");
}
- if (!(dm->flags & TYPEDEF)) {
- if (flags &(STRUCT_REQUEST|UNION_REQUEST) ) {
- if ((flags & (STRUCT_REQUEST|UNION_REQUEST)) != dm->type)
- goto freebuf;
- } else
- flags |= dm->type;
- }
-
- /*
- * No address was passed -- dump the structure/member declaration.
- */
- if (!aflag || (aflag && (flags & SHOW_OFFSET))) {
- if (aflag)
- dm->vaddr = addr;
- set_temporary_radix(radix, &restore_radix);
- do_datatype_declaration(dm, flags | (dm->flags & TYPEDEF));
- restore_current_radix(restore_radix);
- goto freebuf;
- }
-
- if (!(flags & (UNION_REQUEST|STRUCT_REQUEST)))
- error(FATAL, "invalid argument");
-
/*
- * Display data.
+ * Display member addresses or data
*/
- if (rawdata)
+ if (flags & SHOW_OFFSET) {
+ dm->vaddr = addr;
+ do_datatype_declaration(dm, flags | (dm->flags & TYPEDEF));
+ } else if (flags & SHOW_RAW_DATA)
raw_data_dump(addr, len, flags & STRUCT_VERBOSE);
- else if (pflag && !dm->member) {
- set_temporary_radix(radix, &restore_radix);
+ else if ((flags & DEREF_POINTERS) && !dm->member) {
print_struct_with_dereference(addr, dm, flags);
- restore_current_radix(restore_radix);
} else {
if (dm->member)
open_tmpfile();
- set_temporary_radix(radix, &restore_radix);
-
if (flags & UNION_REQUEST)
print_union(dm->name, addr);
else if (flags & STRUCT_REQUEST)
print_struct(dm->name, addr);
if (dm->member) {
- if (!(pflag &&
+ if (!((flags & DEREF_POINTERS) &&
dereference_pointer(addr, dm, flags)))
parse_for_member(dm, PARSE_FOR_DATA);
close_tmpfile();
}
- restore_current_radix(restore_radix);
}
} while (++i < argc_members);
}
-
-freebuf:
- if (argc_members) {
- FREEBUF(structname);
- FREEBUF(members);
- }
}
@@ -6108,13 +6155,7 @@ arg_to_datatype(char *s, struct datatype
if (!both)
return 1;
- dm->member = p1+1;
-
- if ((dm->member_offset = MEMBER_OFFSET(dm->name, dm->member)) >= 0)
- return 2;
-
- if ((flags & ANON_MEMBER_QUERY) &&
- ((dm->member_offset = ANON_MEMBER_OFFSET(dm->name, dm->member)) >= 0))
+ if (member_to_datatype(p1 + 1, dm, flags))
return 2;
datatype_member_fatal:
@@ -6137,6 +6178,21 @@ datatype_member_fatal:
return (error(FATAL, "invalid argument: %s\n", s));
}
+static int
+member_to_datatype(char *s, struct datatype_member *dm, ulong flags)
+{
+ dm->member = s;
+
+ if ((dm->member_offset = MEMBER_OFFSET(dm->name, s)) >= 0)
+ return TRUE;
+
+ if ((flags & ANON_MEMBER_QUERY) &&
+ ((dm->member_offset = ANON_MEMBER_OFFSET(dm->name, s)) >= 0))
+ return TRUE;
+
+ return FALSE;
+}
+
/*
* debug routine -- not called on purpose by anybody.
*/
@@ -6388,13 +6444,12 @@ cmd_p(void)
{
int c;
struct syment *sp, *percpu_sp;
- unsigned radix, restore_radix;
- int leader, do_load_module_filter, success;
+ unsigned radix;
+ int do_load_module_filter;
char buf1[BUFSIZE];
- char buf2[BUFSIZE];
- char *p1;
+ char *cpuspec;
- leader = do_load_module_filter = radix = restore_radix = 0;
+ do_load_module_filter = radix = 0;
while ((c = getopt(argcnt, args, "dhxu")) != EOF) {
switch(c)
@@ -6427,33 +6482,57 @@ cmd_p(void)
if (argerrs || !args[optind])
cmd_usage(pc->curcmd, SYNOPSIS);
+ cpuspec = strrchr(args[optind], ':');
+ if (cpuspec)
+ *cpuspec++ = NULLCHAR;
+
+ sp = NULL;
if ((sp = symbol_search(args[optind])) && !args[optind+1]) {
if ((percpu_sp = per_cpu_symbol_search(args[optind])) &&
- display_per_cpu_info(percpu_sp))
+ display_per_cpu_info(percpu_sp, radix, cpuspec))
return;
- sprintf(buf2, "%s = ", args[optind]);
- leader = strlen(buf2);
if (module_symbol(sp->value, NULL, NULL, NULL, *gdb_output_radix))
do_load_module_filter = TRUE;
} else if ((percpu_sp = per_cpu_symbol_search(args[optind])) &&
- display_per_cpu_info(percpu_sp))
+ display_per_cpu_info(percpu_sp, radix, cpuspec))
return;
else if (st->flags & LOAD_MODULE_SYMS)
do_load_module_filter = TRUE;
+ if (cpuspec) {
+ if (sp)
+ error(WARNING, "%s is not percpu; cpuspec ignored.\n",
+ sp->name);
+ else
+ /* maybe a valid C expression (e.g. ':') */
+ *(cpuspec-1) = ':';
+ }
+
+ process_gdb_output(concat_args(buf1, 0, TRUE), radix,
+ sp ? sp->name : NULL, do_load_module_filter);
+}
+
+static void
+process_gdb_output(char *gdb_request, unsigned radix,
+ const char *leader, int do_load_module_filter)
+{
+ unsigned restore_radix;
+ int success;
+ char buf1[BUFSIZE];
+ char *p1;
+
if (leader || do_load_module_filter)
open_tmpfile();
set_temporary_radix(radix, &restore_radix);
- success = gdb_pass_through(concat_args(buf1, 0, TRUE), NULL,
- GNU_RETURN_ON_ERROR);
+ success = gdb_pass_through(gdb_request, NULL, GNU_RETURN_ON_ERROR);
if (success && (leader || do_load_module_filter)) {
int firstline;
if (leader) {
- fprintf(pc->saved_fp, "%s", buf2);
+ fprintf(pc->saved_fp, "%s = ", leader);
fflush(pc->saved_fp);
}
@@ -6482,8 +6561,41 @@ cmd_p(void)
restore_current_radix(restore_radix);
if (!success)
- error(FATAL, "gdb request failed: %s\n",
- concat_args(buf1, 0, TRUE));
+ error(FATAL, "gdb request failed: %s\n", gdb_request);
+}
+
+/*
+ * Get the type of an expression using gdb's "whatis" command.
+ * The returned string is dynamically allocated, and it should
+ * be passed to FREEBUF() when no longer needed.
+ * Return NULL if the type cannot be determined.
+ */
+static char *
+expr_type_name(const char *expr)
+{
+ char buf[BUFSIZE], *p;
+
+ open_tmpfile();
+ sprintf(buf, "whatis %s", expr);
+ 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();
+
+ if (p) {
+ size_t len = strlen(clean_line(p));
+ /* GDB reports unknown types as <...descriptive text...> */
+ if (p[0] == '<' && p[len-1] == '>')
+ return NULL;
+ return strcpy(GETBUF(len + 1), p);
+ }
+ return NULL;
}
/*
@@ -6491,30 +6603,74 @@ cmd_p(void)
* the addresses of each its per-cpu instances.
*/
static int
-display_per_cpu_info(struct syment *sp)
+display_per_cpu_info(struct syment *sp, int radix, char *cpuspec)
{
+ ulong *cpus;
int c;
ulong addr;
char buf[BUFSIZE];
+ char leader[sizeof("&per_cpu(") + strlen(sp->name) +
+ sizeof(", " STR(UINT_MAX) ")")];
+ char *typename;
+ int do_load_module_filter;
if (((kt->flags & (SMP|PER_CPU_OFF)) != (SMP|PER_CPU_OFF)) ||
(!is_percpu_symbol(sp)) ||
!((sp->type == 'd') || (sp->type == 'D') || (sp->type == 'V')))
return FALSE;
- fprintf(fp, "PER-CPU DATA TYPE:\n ");
- sprintf(buf, "whatis %s", sp->name);
- if (!gdb_pass_through(buf, pc->nullfp, GNU_RETURN_ON_ERROR))
- fprintf(fp, "[undetermined type] %s;\n", sp->name);
- else
- whatis_variable(sp);
+ if (cpuspec) {
+ cpus = get_cpumask_buf();
+ if (STREQ(cpuspec, "")) {
+ SET_BIT(cpus, CURRENT_CONTEXT()->processor);
+ } else {
+ make_cpumask(cpuspec, cpus, FAULT_ON_ERROR, NULL);
+ }
+ } else
+ cpus = NULL;
+
+ typename = expr_type_name(sp->name);
+
+ if (!cpus) {
+ fprintf(fp, "PER-CPU DATA TYPE:\n ");
+ if (!typename)
+ fprintf(fp, "[undetermined type] %s;\n", sp->name);
+ else
+ whatis_variable(sp);
+
+ fprintf(fp, "PER-CPU ADDRESSES:\n");
+ }
+
+ do_load_module_filter =
+ module_symbol(sp->value, NULL, NULL, NULL, *gdb_output_radix);
- fprintf(fp, "PER-CPU ADDRESSES:\n");
for (c = 0; c < kt->cpus; c++) {
+ if (cpus && !NUM_IN_BITMAP(cpus, c))
+ continue;
addr = sp->value + kt->__per_cpu_offset[c];
- fprintf(fp, " [%d]: %lx\n", c, addr);
+ if (!cpus)
+ fprintf(fp, " [%d]: %lx\n", c, addr);
+ else if (typename) {
+ snprintf(buf, sizeof buf, "p *(%s*) 0x%lx",
+ typename, addr);
+ sprintf(leader, "per_cpu(%s, %u)",
+ sp->name, c);
+ process_gdb_output(buf, radix, leader,
+ do_load_module_filter);
+ } else {
+ snprintf(buf, sizeof buf, "p (void*) 0x%lx", addr);
+ sprintf(leader, "&per_cpu(%s, %u)",
+ sp->name, c);
+ process_gdb_output(buf, radix, leader,
+ do_load_module_filter);
+ }
}
+ if (typename)
+ FREEBUF(typename);
+ if (cpus)
+ FREEBUF(cpus);
+
return TRUE;
}
@@ -6859,6 +7015,10 @@ dump_datatype_flags(ulong flags, FILE *o
fprintf(ofp, "%sDATATYPE_QUERY", others++ ? "|" : "");
if (flags & ANON_MEMBER_QUERY)
fprintf(ofp, "%sANON_MEMBER_QUERY", others++ ? "|" : "");
+ if (flags & SHOW_RAW_DATA)
+ fprintf(ofp, "%sSHOW_RAW_DATA", others++ ? "|" : "");
+ if (flags & DEREF_POINTERS)
+ fprintf(ofp, "%sDEREF_POINTERS", others++ ? "|" : "");
fprintf(ofp, ")\n");
}
--- a/defs.h
+++ b/defs.h
@@ -4321,6 +4321,7 @@ int calculate(char *, ulong *, ulonglong
int endian_mismatch(char *, char, ulong);
uint16_t swap16(uint16_t, int);
uint32_t swap32(uint32_t, int);
+ulong *get_cpumask_buf(void);
int make_cpumask(char *, ulong *, int, int *);
size_t strlcpy(char *, char *, size_t);
struct rb_node *rb_first(struct rb_root *);
--- a/kernel.c
+++ b/kernel.c
@@ -5377,7 +5377,6 @@ cmd_irq(void)
int i, c;
int nr_irqs;
ulong *cpus;
- int len;
int show_intr, choose_cpu;
char buf[10];
char arg_buf[BUFSIZE];
@@ -5485,9 +5484,7 @@ cmd_irq(void)
error(FATAL, "cannot determine number of IRQs\n");
if (show_intr) {
- if ((len = STRUCT_SIZE("cpumask_t")) < 0)
- len = DIV_ROUND_UP(kt->cpus, BITS_PER_LONG) * sizeof(ulong);
- cpus = (ulong *)GETBUF(len);
+ cpus = get_cpumask_buf();
if (choose_cpu) {
make_cpumask(arg_buf, cpus, FAULT_ON_ERROR, NULL);
--- a/tools.c
+++ b/tools.c
@@ -5489,6 +5489,19 @@ swap32(uint32_t val, int swap)
return val;
}
+/*
+ * Get a sufficiently large buffer for cpumask.
+ * You should call FREEBUF() on the result when you no longer need it.
+ */
+ulong *
+get_cpumask_buf(void)
+{
+ int cpulen;
+ if ((cpulen = STRUCT_SIZE("cpumask_t")) < 0)
+ cpulen = DIV_ROUND_UP(kt->cpus, BITS_PER_LONG) * sizeof(ulong);
+ return (ulong *)GETBUF(cpulen);
+}
+
int
make_cpumask(char *s, ulong *mask, int flags, int *errptr)
{
@@ -5505,14 +5518,20 @@ make_cpumask(char *s, ulong *mask, int f
p = strtok(s, ",");
while (p) {
s = strtok(NULL, "");
- start = end = -1;
- q = strtok(p, "-");
- start = dtoi(q, flags, errptr);
- if ((q = strtok(NULL, "-")))
- end = dtoi(q, flags, errptr);
- if (end == -1)
- end = start;
+ if (STREQ(p, "a") || STREQ(p, "all")) {
+ start = 0;
+ end = kt->cpus - 1;
+ } else {
+ start = end = -1;
+ q = strtok(p, "-");
+ start = dtoi(q, flags, errptr);
+ if ((q = strtok(NULL, "-")))
+ end = dtoi(q, flags, errptr);
+
+ if (end == -1)
+ end = start;
+ }
for (i = start; i <= end; i++)
SET_BIT(mask, i);
--- a/help.c
+++ b/help.c
@@ -1083,10 +1083,15 @@ NULL
char *help_p[] = {
"p",
"print the value of an expression",
-"[-x|-d][-u] expression",
+"[-x|-d][-u] expression[:cpuspec]",
" This command passes its arguments on to gdb \"print\" command for evaluation.",
"",
" expression The expression to be evaluated.",
+" cpuspec CPU specification for per-cpu variables:",
+" : CPU of the currently selected task.",
+" :a[ll] all CPUs.",
+" :#[-#][,...] CPU list(s), e.g. \"1,3,5\", \"1-3\",",
+" or \"1,3,5-7,10\".",
" -x override default output format with hexadecimal format.",
" -d override default output format with decimal format.",
" -u the expression evaluates to a user address reference.",
@@ -1144,6 +1149,13 @@ char *help_p[] = {
" swap_address = 0x0, ",
" segments = 0x0",
" }",
+"",
+" Print the contents of the variable \"blk_cpu_iopoll\" on the current CPU:\n",
+" %s> p blk_cpu_iopoll:",
+" per_cpu(blk_cpu_iopoll, 2) = $1 = {",
+" next = 0xffff88011e290100, ",
+" prev = 0xffff88011e290100",
+" }",
NULL
};
@@ -2841,7 +2853,7 @@ char *help_irq[] = {
" irq stats of all cpus will be displayed.",
" -c cpu only usable with the -s option, dump the irq stats of the ",
" specified cpu[s]; cpu can be specified as \"1,3,5\", \"1-3\",",
-" or \"1,3,5-7,10\".",
+" \"1,3,5-7,10\", \"all\", or \"a\" (shortcut for \"all\").",
"\nEXAMPLES",
" Display the relevant data for IRQ 18 from a pre-2.6.37 kernel:\n",
" %s> irq 18",
@@ -4092,8 +4104,8 @@ NULL
char *help_struct[] = {
"struct",
"structure contents",
-"struct_name[.member[,member]][-o][-l offset][-rfuxdp][address | symbol]\n"
-" [count | -c count]",
+"struct_name[.member[,member]][-o][-l offset][-rfuxdp]\n"
+" [address | symbol][:cpuspec] [count | -c count]",
" This command displays either a structure definition, or a formatted display",
" of the contents of a structure at a specified address. When no address is",
" specified, the structure definition is shown along with the structure size.",
@@ -4127,6 +4139,11 @@ char *help_struct[] = {
" to an embedded list_head structure contained within the",
" target data structure, then the \"-l\" option must be used.",
" symbol symbolic reference to the address of a structure.",
+" cpuspec CPU specification for per-cpu variables:",
+" : CPU of the currently selected task.",
+" :a[ll] all CPUs.",
+" :#[-#][,...] CPU list(s), e.g. \"1,3,5\", \"1-3\",",
+" or \"1,3,5-7,10\".",
" count count of structures to dump from an array of structures;",
" if used, this must be the last argument entered.",
" -c count \"-c\" is only required if \"count\" is not the last argument",
@@ -4382,8 +4399,8 @@ NULL
char *help_union[] = {
"union",
"union contents",
-"union_name[.member[,member]] [-o][-l offset][-rfuxdp] [address | symbol]\n"
-" [count | -c count]",
+"union_name[.member[,member]] [-o][-l offset][-rfuxdp]\n"
+" [address | symbol][:cpuspec] [count | -c count]",
" This command displays either a union definition, or a formatted display",
" of the contents of a union at a specified address. When no address is",
" specified, the union definition is shown along with the union size.",
@@ -4418,6 +4435,11 @@ char *help_union[] = {
" to an embedded list_head structure contained within the",
" target union structure, then the \"-l\" option must be used.",
" symbol symbolic reference to the address of a union.",
+" cpuspec CPU specification for per-cpu variables:",
+" : CPU of the currently selected task.",
+" :a[ll] all CPUs.",
+" :#[-#][,...] CPU list(s), e.g. \"1,3,5\", \"1-3\",",
+" or \"1,3,5-7,10\".",
" count count of unions to dump from an array of unions; if used,",
" this must be the last argument entered.",
" -c count \"-c\" is only required if \"count\" is not the last argument",
--
Crash-utility mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/crash-utility