Hi Dave, Sorry about the delay. I completely forgot about this one! Please note I have only addressed the case when the argument to the 'struct' command is not an address: When a percpu symbol is of type pointer, the 'struct' command does not generate the expected output. For example: Note: The correct value of 'exec_start' should be 0x15b070b28b0c27 not 0x0 crash> struct task_struct.se.exec_start softlockup_watchdog:0 [0]: ffff880214e55a00 se.exec_start = 0x0, crash> px softlockup_watchdog:0-1 per_cpu(softlockup_watchdog, 0) = $1 = (struct task_struct *) 0xffff880fe97e2e00 crash> px ((struct task_struct *)0xffff880fe97e2e00)->se.exec_start $2 = 0x15b070b28b0c27 Currently, the 'struct' and 'p' command simply calculates 'cpuaddr' as follows -- where 'addr' is a percpu's value: cpuaddr = addr + __per_cpu_offset This is correct if the percpu symbol or offset (i.e. [percpu symbol:cpu-specifier] or [percpu value:cpu-specifier]) is not of type pointer. If a given percpu symbol is of type pointer such as in 'static DEFINE_PER_CPU(struct task_struct *, softlockup_watchdog)', we need to dereference the pointer to obtain the above correct kernel virtual address. For instance, using the above example, we need to pass the following to gdb to resolve appropriately: kernel virtual addresses for the cpus specified. crash> set gdb on gdb: on gdb> p *(struct task_struct **) 0xffff880fffc0ddc0 $1 = (struct task_struct *) 0xffff880fe97e2e00 gdb> With this patch, we now obtain the expected output: crash> struct task_struct.se.exec_start softlockup_watchdog:0 [0]: ffff880214e55a00 se.exec_start = 0x15b070b28b0c27, Signed-off-by: Aaron Tomlin <atomlin@xxxxxxxxxx> --- symbols.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/symbols.c b/symbols.c index 8b0d8b9..b68d0d3 100644 --- a/symbols.c +++ b/symbols.c @@ -81,6 +81,7 @@ static void cmd_datatype_common(ulong); static void do_datatype_addr(struct datatype_member *, ulong, int, ulong, char **, int); static void process_gdb_output(char *, unsigned, const char *, int); +static char *expr_type_name(const char *); 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 *); @@ -6112,6 +6113,11 @@ cmd_datatype_common(ulong flags) char *separator; char *structname, *members; char *memberlist[MAXARGS]; + char *typename; + char buf[BUFSIZE]; + char *argv[MAXARGS]; + FILE *tmpfp; + ushort ptype; dm = &datatype_member; count = 0xdeadbeef; @@ -6122,6 +6128,7 @@ cmd_datatype_common(ulong flags) separator = members = NULL; cpuspec = NULL; cpus = NULL; + ptype = 0; while ((c = getopt(argcnt, args, "pxdhfuc:rvol:")) != EOF) { switch (c) @@ -6262,6 +6269,12 @@ cmd_datatype_common(ulong flags) SET_BIT(cpus, CURRENT_CONTEXT()->processor); else make_cpumask(cpuspec, cpus, FAULT_ON_ERROR, NULL); + + if (sp) { + typename = expr_type_name(sp->name); + ptype = typename && + LASTCHAR(typename) == '*' ? 1 : 0; + } } optind = optind_save; @@ -6346,6 +6359,19 @@ cmd_datatype_common(ulong flags) continue; } + if (ptype) { + open_tmpfile(); + snprintf(buf, sizeof buf, "p *(%s*) 0x%lx", + typename, cpuaddr); + gdb_pass_through(buf, pc->tmpfile, GNU_RETURN_ON_ERROR); + + rewind(pc->tmpfile); + fgets(buf, BUFSIZE, pc->tmpfile); + parse_line(buf, argv); + cpuaddr = htol(argv[3], FAULT_ON_ERROR, NULL); + close_tmpfile(); + } + fprintf(fp, "%lx\n", cpuaddr); do_datatype_addr(dm, cpuaddr , count, flags, memberlist, argc_members); @@ -6364,6 +6390,9 @@ freebuf: if (cpus) FREEBUF(cpus); + + if (typename) + FREEBUF(typename); } static void -- 2.5.5 -- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility